准备阶段 Profiler性能分析工具的使用(一)

Unity 性能分析器 (Unity Profiler)

性能分析器记录应用程序性能的多个方面并显示相关信息。使用此信息可以做出有关应用程序中可能需要优化的事项的明智决策,并确认所做的优化是否产生预期结果。

默认情况下,性能分析器记录并保留游戏的最后 300 帧,并显示有关每一帧的详细信息。可以在 Preferences 窗口(菜单:__File > Preferences__)中增加其记录的帧数(至多 2,000 帧)。注意:如果将此设置增加到很大的帧数,则性能分析器的开销和内存使用量可能产生更大的性能影响。

可以检查脚本代码,以及应用程序如何使用某些资源(这可能会降低应用程序速度)。还可以比较应用程序在不同设备上的性能。性能分析器具有几个不同的性能分析器模块,这些模块可以添加到性能分析会话中,从而获取有关渲染、内存和音频等方面的更多信息。

Profiler 窗口布局

  • A:性能分析器模块。这是可以在应用程序中接受性能分析的所有模块的列表。使用此区域顶部的下拉菜单可以在窗口中添加和删除模块。
  • B:性能分析器控件。使用这些控件可以设置要从哪个设备进行性能分析以及 Unity 应该执行哪种性能分析,可以在帧之间进行导航,还可以开始记录数据。
  • C:帧图表。此区域包含性能分析器进行性能分析的每个模块的图表。首次打开性能分析器时,该区域为空白;开始对应用程序进行性能分析时,该区域中将填充信息。
  • D:模块详细信息面板。此窗口区域中的信息根据所选择的模块而异。例如,选择 CPU Usage Profiler 模块时,此区域包含详细的Timeline时间轴和切换到 Hierarchy 视图的选项。选择 Rendering Profiler 模块时,此区域显示调试信息列表。首次打开性能分析器时,该区域为空白;开始对应用程序进行性能分析时,该区域中将填充信息。

A性能分析器模块

Profiler 窗口的顶部被分为几个性能分析器模块,这些模块对游戏的特定方面进行性能分析。对应用程序进行性能分析时,Unity 在相应图表中显示与每个模块相关的数据。

CPU Usage 模块最能够体现应用程序在每帧中花费的时间。其他模块收集更具体的数据,有助于检查更具体的方面或监测应用程序的重要信息,例如内存消耗、渲染或音频统计信息。

每个模块都有自己的图表。选择模块时,模块详细信息面板将显示在窗口的底部,可用于检查该模块收集的详细数据。

性能分析器模块功能
CPU Usage概要显示应用程序在哪些方面花费最多时间(涉及物理、脚本、动画和垃圾收集等多个方面)。该模块包含有关应用程序的大量性能分析信息,您可以使用这些信息来决定进一步使用哪些其他模块来调查应用程序中的更具体问题。该模块始终处于激活状态(即使您将其关闭)。请参阅 CPU Usage Profiler 模块
GPU Usage显示与图形处理有关的信息。默认情况下,此模块处于非激活状态,因为它的开销较大。请参阅 GPU Usage Profiler 模块。
渲染显示有关 Unity 如何在应用程序中渲染图形的信息,包括有关静态和动态批处理、SetPass 和 Draw 调用、三角形和顶点的信息。请参阅 Rendering Profiler 模块。
Memory显示有关 Unity 如何在应用程序中分配内存的信息。这尤其适合用于查看脚本分配 (GC.Alloc) 如何引起垃圾收集或者是应用程序的资源内存使用量随时间变化的趋势。请参阅 Memory Profiler 模块。
Audio显示应用程序中的音频相关信息,例如何时播放音频源以及播放的音频源数量、音频系统需要的 CPU 使用率以及 Unity 为其分配的内存量。请参阅 Audio Profiler 模块。
Video显示应用程序中的视频相关信息。请参阅 Video Profiler 模块。
Physics显示应用程序中物理引擎已进行的物理处理的相关信息。请参阅 Physics Profiler 模块。
Physics (2D)与 Physics Profiler 模块类似,此模块显示应用程序中物理引擎已进行的 2D 物理处理的相关信息。
Network Messages
(已弃用)
显示有关多玩家高级 API 发送或接收的较低级数据包和消息的信息。
注意:多玩家高级 API 已被弃用。
Network Operations
(已弃用)
显示有关多玩家高级 API 发送和接收的消息中含有哪些类型或操作的详细信息,例如已传输的 SyncVar 或命令的数量。
注意:多玩家高级 API 已被弃用。
UI显示有关 Unity 如何为应用程序处理 UI 批处理的信息,包括 Unity 为何以及如何对项目进行批处理。请参阅 UI Profiler 模块。
UI Details与 UI 模块类似,此模块的图表添加有关批处理和顶点计数的数据,以及标记(包含有关触发 UI 变化的用户输入事件的信息)。
Global Illumination显示有关 Unity 在应用程序中的全局光照 (Global Illumination) 光照子系统中花费的 CPU 资源的信息。请参阅 Global Illumination Profiler 窗口。
性能分析器模块开销

某些性能分析器模块具有大量的数据收集开销,例如 GPU、UI 和 Audio Profiler 模块。为了防止这些模块影响应用程序的性能,可以通过在 Profiler Module 下拉选单中取消选择这些模块来将它们停用。这样可从窗口删除模块,让性能分析器停止收集该模块的数据,并减少性能分析器的开销。

这不适用于 CPU Usage 模块,该模块始终会收集数据(即使该模块处于非激活状态),因为其他模块依赖这些数据。

要添加模块,请选择 Profiler Module 下拉选单,然后选择要激活的性能分析器。从下拉选单选择性能分析器模块后,这个模块开始收集数据,但是在非激活时段内不显示任何数据。

为了避免 GPU Profiler 模块的开销,默认情况下该模块处于非激活状态。GPU Profiler 模块必须在应用程序启动时处于激活状态,才能挂接到图形驱动程序。如果稍后添加,在大多数平台上均无效,并且性能分析器显示消息:“GPU profiling is not supported by the graphics card driver (or it was disabled because of driver bugs)”。

如果您指示性能分析器收集数据并通过 Profiler.logFile API 而不是通过 Profiler 窗口将数据发送到磁盘,您可以通过 Profiler.SetAreaEnabled() 来关闭性能分析器模块。

某些通过外部 IDE 来调试脚本的设置也可能产生开销。为了避免发生此开销并获得更准确的测量值,请禁用 Editor Attaching 设置(菜单:__Preferences > External Tools__)。同样,对构建播放器进行性能分析时,请打开 Build Settings 并禁用 Script Debugging 以避免发生此开销。

B性能分析器控件

性能分析器控件位于 Profiler 窗口顶部的工具栏中。使用这些控件可开始或停止记录性能分析器数据以及浏览分析的帧。

控件功能
Attach to Player选择对应用程序进行性能分析时所在的目标。默认设置为 Playmode。也可以选择 Editor 以对 Unity Editor 进行性能分析并显示 Editor 当前在使用的资源。

Unity 还自动检测网络上正在运行或通过 USB 连接的所有设备,并将这些设备显示在下拉选单中。单击下拉选单中的 Enter IP 可手动输入设备的 IP 地址,以便在该设备上对应用程序进行性能分析。有关更多信息,请参阅应用程序性能分析。
Record启用此设置可以在运行应用程序时记录活跃模块的性能分析信息。如果未启用此按钮,则在运行应用程序时,性能分析器不会收集任何数据。
Back arrow向后导航一帧。
Forward arrow向前导航一帧。
Current Frame单击 Current Frame 按钮时,帧指示线会跳到最后记录的帧,并且性能分析器进入 Current Frame 模式。性能分析器在此模式下收集数据时,它会停留在当前帧上并实时显示收集的数据。再次单击该按钮将退出 Current Frame 模式。
Frame number指示当前在性能分析器中查看的帧的编号。
Clear从 Profiler 窗口擦除所有数据。
Clear on Play启用此设置后,下次单击 Player 窗口中的 Play 或连接到新的目标设备时,可从 Profiler 窗口擦除所有数据。
Deep Profile启用此设置可对所有 C# 方法进行性能分析。启用此设置后,Unity 会将检测功能添加到所有 Mono 调用,然后便可以对脚本进行更详细的调查。请参阅深度性能分析。
Call Stacks要记录用于脚本内存分配的调用栈,请单击此开关。启用此选项时,性能分析器记录的帧具有 GC.Alloc 样本中的信息;即使在 Deep Profile 未激活的情况下,完整调用栈上的这些样本也会导致托管脚本分配。有关更多信息,请参阅“CPU Usage Profiler 模块”页面的分配调用栈部分。
Load将已保存的性能分析器数据加载到 Profiler 窗口中。还可以加载播放器通过 Profiler.logFile API 写出到文件的二进制性能分析数据。

按住 Shift 按钮并单击 Load 按钮可将文件内容附加到当前性能分析帧。
Save将性能分析器数据保存到 Project 文件夹中的 .data 文件中。
上下文菜单
Color Blind Mode启用此设置可使性能分析器在其图形中使用更高对比度的颜色。这样可以增强红绿色盲(例如绿色盲、红色盲或蓝色盲)用户的视觉感知度。
Show stats for “current” frame默认情况下,选择 Current Frame 按钮并进入 Current Frame 模式时,帧指示线不会随当前帧统计信息显示相关注释。这是因为统计信息注释可能导致难以实时查看数据。要显示注释,请启用此设置。
Preferences打开 Preferences 菜单以调整特定于性能分析器的属性。

为了保持低开销,Unity 仅每隔五帧重绘一次 Editor UI。这样会导致更新过程略有卡顿。

深度性能分析

通常,性能分析器仅对用 ProfilerMarker 显式包裹的代码时序进行性能分析。这包括从引擎原生代码到脚本代码的调用(例如 MonoBehaviour 的 StartUpdate 或类似方法)的第一个调用栈深度。

如果未向您自己的代码添加更显式的 ProfilerMarker 检测,您可以视为脚本代码的子样本的唯一其他样本是回调到 Unity API 中的样本(如果已对该 API 进行检测)。带有性能开销的大多数 API 调用都会经过检测。例如,通过 Camera.main API 访问主摄像机的操作被注册为“FindMainCamera”样本。

启用 Deep Profile 设置后,性能分析器会对脚本代码的每个部分进行性能分析,并记录所有函数调用,至少包括进入任何 Unity API 中的第一个调用栈深度。此信息可用于帮助您确定代码对应用程序性能的影响,但这会带来很大的开销。

对应用程序进行深度性能分析时,Unity 会将性能分析器检测功能注入到所有脚本方法中,从而记录所有函数调用。这有助于了解应用程序代码在哪些方面花费最多的时间。

深度性能分析是资源密集型操作,会耗用大量内存。因此,在进行性能分析时,应用程序运行速度显著降低。深度性能分析更适合用简单脚本编写的小游戏。如果使用的是复杂脚本代码,则应用程序可能根本无法使用深度性能分析。对于许多较大的应用程序,深度性能分析可能会使 Unity 耗尽内存。

如果遇到问题,导致性能分析器的太多样本存储在环形缓冲区(用于将样本流式传输到性能分析器)中,Unity 将显示一条错误消息。为了增加环形缓冲区的大小,可以调整进行性能分析的播放器的 Profiler.maxUsedMemory 属性。

如果深度性能分析导致应用程序的帧率下降太多而无法运行,您可以手动对脚本代码块进行性能分析,此方法的开销小于深度性能分析。使用 ProfilerMarker 可以手动添加标记脚本块所需的检测。这些会显示在 CPU Usage Profiler 模块中。

如果要找出产生 GC.Alloc 样本的调用栈而不想进行深度性能分析,可以开启__分配调用栈__的收集。启用性能分析器控件中的 Call Stacks 设置,然后可以在 Timeline 视图中选择 GC.Alloc 样本,或者使用 Hierarchy 视图中的 Show Related Objects 面板来查找这些样本的调用栈。

C性能分析器帧图表

Profiler 窗口的上半部分逐帧显示随时间推移的性能数据。运行应用程序时,性能分析器会记录每帧的数据。默认情况下,Profiler 窗口显示其进行性能分析的最近 300 帧的历史记录。可以在 Preferences 窗口中增加性能分析器进行性能分析的帧的数量(最多为 2,000 帧)。

在 Profiler 窗口的性能分析器帧图表区域中单击时,将出现一条白线来突出显示应用程序的一帧。要在帧之间导航,请使用 Profiler 窗口的工具栏中的传输控件。

Unity 自动管理图表的垂直刻度,而且图表会尝试填充窗口的垂直空间。要查看图表中的更多详细信息,可以删除其他性能分析器模块,也可以拖动图表和详细统计信息区域之间的分隔线来增大图表的屏幕区域。

要在图表中切换指标的隐藏和显示,请在相关模块中单击相应标签旁的有色方块。这样可以方便找到出现尖峰的原因。在堆积图表(例如 CPU Usage Profiler 的图表)中,可以将指标标签重新排序以影响堆积顺序。这样可以使干扰较多的指标更加明显,从而使图表更清晰。

每个性能分析器模块收集不同的性能数据指标并将它们显示在单独的图表中。单击某个帧时,Unity 在 Profiler 窗口下半部分的模块详细信息面板中显示有关该帧的更多详细信息。此窗口中的详细信息类型会因选择的性能分析器模块而异。有关每个模块在此区域中显示的特定详细信息的更多信息。

命令行参数

如果从命令行(例如 Windows 上的命令提示符,macOS 上的终端,Linux Shell,或者 Android 的 adb)启动构建的播放器或 Unity Editor,可以传递命令行参数来配置一些性能分析器设置。

命令行参数描述
-deepprofiling在构建的播放器中启用深度性能分析。
-profiler-enable对播放器或 Editor 的启动进行性能分析。将此参数与播放器一起使用时,效果与在 Build Settings 中启用 Autoconnect Profiler 选项来构建播放器的效果相同。

将此参数与 Editor 一起使用时,在 Editor 启动时会开始在 Profiler 窗口中收集和显示性能分析器信息。
-profiler-log-file <Path/To/Log/File.raw>此参数用于设置性能分析器,使其在启动时将性能分析数据流式传输到 .raw 文件。对播放器和 Editor 都有效。
-profiler-capture-frame-count <NumberOfFrames>此参数用于设置启动后流式传输到 .raw 文件时要在性能分析中捕获的帧数量。仅对播放器有效。
-profiler-maxusedmemorymaxUsedMemory 的默认值是 16MB(对于播放器)和 256MB(对于 Editor)。可以在启动时使用此参数将 maxUsedMemory 参数设置为自定义大小(例如,-profiler-maxusedmemory 16777216)。此大小以字节为单位。

D 模块详细信息面板(Hierarchy 

CPU Usage函数热点开销追踪

WaitForTargetFPS:Stats显示绘制能力:234FPS,真实绘制54FPS,对于游戏来说60FPS就够了,剩下的时间结余,可以休息。因此WaitForTargetFPS越高,休眠时间越多,越好。

Camera.Render:绘制摄像机的画面

Overhead:引擎没有统计到的未知开销

Animation.Update:采样出来某一帧的模型动画

BehaviourUpdate:所有脚本里的Update

  •  如何获取方法中循环代码所消耗的时间,除了将它改写成一个方法外,还可以用这句代码解决
  • Profiler.NeginSample("Test Input 10000");
    
    for()
    {
       int i =0;
       int x=i;
    }
    
    Profiler.EndSample();

Gui.Repaint:OnGui的一个开销,消耗极大

AudioManager.Update:声音播放的消耗

MeshSkinning.Update:蒙皮的消耗,这也是为啥stat里为啥要显示蒙皮的数量的原因

Cavas.RenderOverlays:与UGUI绘制相关的消耗

Graphics.Blit:摄像机后处理

什么是一个函数的开销:函数的开销=(调用一次函数消耗的时间:调用别人函数所占的时间+自己所占的时间)*调用次数

test(){

Debug.Log("helloword");

int i=1000+1000;

}

追踪过程:谁Total高,谁作为优化的热点,Total是自己及其子物体所占的内存,Self是自己所占的内存。Calls是执行次数。

解决方案:减少调用时间(优化算法,优化结构),减少调用次数(减小问题的规模)
 

Rendering渲染热点开销追踪

优化Drawcall

算出哪儿些物体占的drawcall比较多,drawcall是怎么分布的

显示和隐藏场景文件中的游戏物体来查看是哪儿个游戏物体所占的drawcall较高

合批的数量也是有上限的,这也是为啥800个小兵是两个批次,而不是一个批次

优化思路

a:找到优化的热点

b:找到了以后再来想对策

今天是2024年11月20日

重复一段毒鸡汤来勉励我和你

你的对手在看书

你的仇人在磨刀

你的闺蜜在减肥

隔壁的老王在练腰

而你在干嘛?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/921810.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

01Web3.0行业

目录 一、什么是Web 3.0? 二、Web 1.0 vs Web 2.0 vs Web 3.0 三、为什么选择Web 3.0 四、从法律角度观察Web 3.0 1. Web 3.0前时代的数字身份 问题1&#xff1a;个人信息的过度收集 问题2&#xff1a;个人信息的泄露和滥用 2. Web 3.0的解决方案及其法律问题 问题一&…

archlinux安装waydroid

目录 参考资料 注意 第一步切换wayland 第二步安装binder核心模组 注意 开始安装 AUR安裝Waydroid 启动waydroid 设置网络&#xff08;正常的可以不看&#xff09; 注册谷歌设备 安装Arm转译器 重启即可 其他 参考资料 https://ivonblog.com/posts/archlinux-way…

互联网时代的隐私保护

在这个数字化时代&#xff0c;我们的生活与互联网密不可分。打开手机刷刷朋友圈&#xff0c;浏览一下购物网站&#xff0c;约个网约车&#xff0c;点个外卖&#xff0c;这些看似平常的行为都在默默产生着数据足迹。可就在这不经意间&#xff0c;我们的个人信息正在被收集、分析…

python之使用django框架开发web项目

本问将对django框架在python的web项目中的使用进行介绍,有不对之处,烦请指正。 首先使用创建一个django工程(本示例中使用pycharm2024+python3.12),名称和项目保存路径根据自己的需要自行修改,新手直接默认本机环境就好(关于conda将会另开一篇进行讲解。),最后点击cre…

基于YOLOv8深度学习的扰乱公共秩序打架异常行为检测系统研究与实现(PyQt5界面+数据集+训练代码)

随着智能监控技术和人工智能的发展&#xff0c;基于深度学习的行为检测技术在公共安全和防范领域中发挥着越来越重要的作用。传统的监控系统通常依赖于人工监控&#xff0c;这不仅耗费大量的人力和时间&#xff0c;且容易因为人的疲劳或疏忽而漏检关键的异常行为。而近年来&…

gocv调用opencv添加中文乱码的解决方案

前言 相信很多做视觉的同学在使用opencv给图片添加中文文字的时候会出现这样的乱码显示: 而实际上你期望的是“告警时间:2011-11-11 11:11:11 告警类型:脱岗检测告警 Area:XXXXX Camera:Camera001-001”这样的显示内容,那么这篇文章我将用很简单的方法来解决乱码问题,只需…

JavaScript中的this指向问题

JavaScript中的this指向问题 1.1 为什么需要this? 为什么需要this? 在常见的编程语言中&#xff0c;几乎都有this这个关键字&#xff08;Objective-C中使用的是self),但是在JavaScript中的this和常见的面向对象语言中的this不太一样 常见面向对象的编程语言中&#xff0c;比…

预测气动阻尼

TLDR&#xff1a;通过结合 ANSYS Mechanical 和 ANSYS CFX&#xff0c;可以通过模拟预测气动阻尼。此方法可用于涡轮叶片、飞机机翼或 MEMS 微镜&#xff01; MEMS 系统的频率响应。峰值的高度取决于阻尼……那么阻尼比是多少&#xff1f; 多年来&#xff0c;很多人问我“嘿&am…

在 CentOS 系统上直接安装 MongoDB 4.0.25

文章目录 步骤 1&#xff1a;配置 MongoDB 官方源步骤 2&#xff1a;安装 MongoDB步骤 3&#xff1a;启动 MongoDB 服务步骤 4&#xff1a;验证安装步骤 5&#xff1a;可选配置注意事项 以下是在 CentOS 系统上直接安装 MongoDB 4.0.25 的详细步骤&#xff1a; 步骤 1&#x…

.NET9 - 新功能体验(一)

被微软形容为“迄今为止最高效、最现代、最安全、最智能、性能最高的.NET版本”——.NET 9已经发布有一周了&#xff0c;今天想和大家一起体验一下新功能。 此次.NET 9在性能、安全性和功能等方面进行了大量改进&#xff0c;包含了数千项的修改&#xff0c;今天主要和大家一起体…

乐理的学习(调式)

大致了解乐理之后的总结 跟着西蒙哥也是把基础乐理差不多能有一个大致的总结框架了&#xff0c;主要还是为了弹钢琴&#xff0c;也是知道了很多的规则都是为了人们的感受服务的 对手指要了解 对于手指的弹音局限 各个手指的使用频率 不同年龄的不同的人对手指的使用存在差…

08 —— Webpack打包图片

【资源模块 | webpack 中文文档 | webpack中文文档 | webpack中文网】https://www.webpackjs.com/guides/asset-modules/?sid_for_share99125_3 Webpack打包图片以8KB为临界值判断 大于8KB的文件&#xff1a;发送一个单独的文件并导出URL地址 小于8KB的文件&#xff1a;导出一…

Python爬虫能处理动态加载的内容吗?

Python爬虫确实可以处理动态加载的内容。动态加载的内容通常是通过JavaScript在客户端执行&#xff0c;这意味着当网页首次加载时&#xff0c;服务器返回的HTML可能并不包含最终用户看到的内容。相反&#xff0c;JavaScript代码会在页面加载后从服务器请求额外的数据&#xff0…

SQL注入--DNSlog外带注入--理论

什么是DNSlog? DNS的作用是将域名解析为IP 而DNSlog就是存储在DNS服务器上的域名信息&#xff0c;它记录着用户对域名访问信息。可以理解为DNS服务器上的日志文件。 多级域名 比如blog.csdn.net&#xff0c;以点为分隔&#xff0c;从右向左依次是顶级域名、二级域名、三级域…

【Flask+Gunicorn+Nginx】部署目标检测模型API完整解决方案

【Ubuntu 22.04FlaskGunicornNginx】部署目标检测模型API完整解决方案 文章目录 1. 搭建深度学习环境1.1 下载Anaconda1.2 打包环境1.3 创建虚拟环境1.4 报错 2. 安装flask3. 安装gunicorn4. 安装Nginx4.1 安装前置依赖4.2 安装nginx4.3 常用命令 5. NginxGunicornFlask5.1 ng…

速度革命:esbuild如何改变前端构建游戏 (1)

什么是 esbuild&#xff1f; esbuild 是一款基于 Go 语言开发的 JavaScript 构建打包工具&#xff0c;以其卓越的性能著称。相比传统的构建工具&#xff08;如 Webpack&#xff09;&#xff0c;esbuild 在打包速度上有着显著的优势&#xff0c;能够将打包速度提升 10 到 100 倍…

Ros Noetic 20.04 跑通mpc_ros包保姆级教程

前言: 本文将简述mpc_ros包在noetic20.04中的安装,mpc是 一种跟踪、MPC_ROS 是一个基于ROS(Robot Operating System)的模型预测控制(Model Predictive Control,MPC)库。该项目旨在为机器人控制提供一个灵活且高效的MPC实现,使得开发者能够在ROS环境中轻松集成和使用MPC…

接上一主题,C++14中如何设计类似于std::any,使集合在C++中与Python一样支持任意数据?

这篇文章的重点是C多态的应用&#xff0c;但是如果你是C新手&#xff0c; 你需要了解以下C知识&#xff1a; 类 构造函数 拷贝构造函数 虚拟函数 纯虚拟函数 析构函数 类的继承 运算符重写 模板类 模板参数 数组 数组的传递 指针与动态内存分配 Python&#xff1a; s …

AndroidStudio与开发板调试时连接失败或APP闪退的解决方案,涉及SELINUX及获取Root权限

现象 用AndroidStudio打开工程代码,点击运行后,报错: 解决方案 具体原因是尝试运行 su(通常用于获取超级用户权限)时失败了,提示 “Permission denied” 通过 CONFIG_SECURITY_SELINUX 变量控制 SElinux 开启或关闭 在vim /rk3568_android_sdk/device/rockchip/rk…

数据结构 (6)栈的应用举例

1. 递归调用 递归函数在执行时&#xff0c;会将每一层的函数调用信息&#xff08;包括局部变量、参数和返回地址&#xff09;存储在栈中。当递归函数返回时&#xff0c;这些信息会从栈中弹出&#xff0c;以便恢复之前的执行状态。栈的后进先出&#xff08;LIFO&#xff09;特性…