CPU使用分析器模块的图表显示了在应用程序中花费的时间。它包含应用程序花费时间的所有重要领域的概述,比如渲染,它的脚本和动画[toc]。本文包括: - CPU使用图表 - CPU使用模块详细信息窗格 - Timeline视图 - 层次结构和原始层次结构视图 - 常见的样品 - 性能警告 - 分配调用堆栈 - 只有在编辑器模式下才会出现的样例
CPU使用分析器模块的图表跟踪应用程序主线程上花费的时间。时间花费分为九类。您可以通过在图表的图例中拖放类别来更改图表中的类别顺序。您还可以单击类别的彩色图例来切换其显示。
应用程序在渲染图形上花费的时间。
应用程序在运行脚本上花费的时间。
应用程序在物理引擎上花费的时间
您的应用程序在动画化SkinnedMeshRenderers、GameObjects上花费的时间 以及应用程序中的其他组件。这还包括用于系统动画和Animator组件的一些计算的时间
应用程序在运行垃圾收集器上花费的时间。
在一个帧中等待targetFrameRate或下一个VBlank同步的时间。这是根据QualitySettings.vSyncCount值,或目标帧率,或VSync设置,该设置是应用程序运行的平台的默认或强制最大值。
全局照明应用程序中用于照明的时间。
显示应用程序的UI花费了多少时间。
其他不属于任何其他类别的代码所花费的时间,例如整个EditorLoop,或者在编辑器中分析Playmode时的分析开销。
当您选择CPU Usage模块时,module details窗格将显示所选帧中所花费时间的详细信息。计时数据要么显示为timeline,要么显示为hierarchical table,您可以通过单击module details窗格中左上角的下拉菜单来更改。可提供的三种意见是:
在帧长度的时间轴旁边显示特定帧的时间细分。 这是惟一一种视图模式,您可以使用它查看主线程以外的线程上的计时,并在线程之间关联计时,例如,作业系统工作线程在主线程上的系统调度它们之后开始运行。
根据时序数据的层次结构对时序数据进行分组。 此选项以降序列表格式显示应用程序调用的元素,按花费的时间(默认值)、分配的脚本内存量(GC.Alloc)或调用的数量排序。 要更改列表的谁许,请单击表列的标题。
以与计时发生的调用堆栈类似的层次结构显示计时数据。 Unity在这种模式下单独列出每个调用堆栈,而不是像在Hierarchy视图中那样合并它们。

时间轴视图是CPU使用分析器模块的默认视图。 它包含应用程序中时间花在何处以及时间如何相互关联的概述。 时间轴视图显示来自所有线程的分析数据,这些数据位于它们自己的子节中,并且沿着相同的时间轴。 这与层次结构视图不同,层次结构视图只显示来自主线程的分析数据。 可以使用时间轴视图查看不同线程上的活动在并行执行时是如何相互关联的。 您可以看到您使用了多少不同的线程,例如作业系统的工作线程,这些线程上的工作是如何排队的,以及是否有任何线程正在空闲(“Idle”sample)或正在等待另一个线程或作业完成(“Wait for x”sample)。 在上面的截图中,作业系统的工作线程中有淡蓝色的动画示例,而主线程也处理动画数据。渲染工作在主线程和渲染线程之间分割。渲染线程与主线程不对齐。 在此特定帧的前0.4 ms期间,渲染线程仍在渲染最后一帧。同样,该帧占用下一帧的前0.1ms。属于其他帧的条形图是灰色的,模块详细窗格顶部的时间标尺上的垂直线在主线程上标记了帧的开始和结束。 当你分析GPU的使用时,工具栏上面的时间标尺显示了帧时间花在CPU上的时间和花在GPU上的时间。在这个例子中,游戏GPU时性能瓶颈的,在CPU上花费的渲染时间最多,所以这个应用程序需要优化它的图形性能。
要放大时间轴的区域,可以使用鼠标上的滚动轮,或者按住Alt键,同时按住鼠标右键拖动。您还可以使用水平滚动条的末端来放大。按下键盘上的A键来重置缩放,这样整个帧的时间都是可见的。 每当您看到线程底部有一个白色箭头时,您可以单击它来展开线程以显示所有的线,或者再次单击以只显示顶部的线。您还可以拖动分隔线程的行,以调整可以看到的行数。双击该行可以将线程部分的高度设置为调用堆栈的最大深度。 要平移视图,请按下鼠标中键或按住Alt键(macOS上的命令键)并按下鼠标左键。 要折叠和展开线程组,请单击视图最左侧线程名称旁边的折叠箭头。 要查看一个项目对CPU图表的贡献,请在下面的窗格中单击它,选择它,分析器将突出显示它的贡献,并使图表的其余部分变暗。若要取消选择该项,请单击视图中的其他位置。按下F键以聚焦您选择的当前样本,或者如果您没有选择任何内容,则显示默认的缩放级别。 要在工具提示中显示托管callstack,请在Profiler窗口工具栏的分配callstack下拉菜单中启用托管callstack选项。 在分析一个帧以显示该帧之前,需要启用Managed Callstacks设置。此选项仅当您在编辑器中进行概要分析时才有效。 您还可以手动测量时间轴视图中的任意时间跨度,方法是单击并水平拖动到任意位置,以在时间轴的某个部分上显示覆盖。您可以在顶部的时间标尺中看到覆盖层所包含的时间。按下F键,同时叠加显示框视图水平沿选定的时间部分。点击任何地方移除覆盖。
当切换到层次结构或原始层次结构视图时,只要示例位于主线程上,您的选择就会保留下来(emm,不太懂这里是啥意思,原文是carries over)。如果你不能立即找到你的选择,按F键聚焦。

Hierarchy视图列出了所有已进行概要分析的示例,并通过它们的共享调用堆栈和profilermarker的层次结构将它们分组在一起。原始层次结构视图不将样本分组在一起,这使得它非常适合在粒度级别上查看样本。在每一行旁边的层次结构中,每一步都显示以下详细信息:
在某一特定功能上的总时间百分比。
在一个特定函数上花费的总时间百分比,不包括Unity调用子函数的时间。 例如,在截图中,41.7%的时间花在了相机渲染功能。这是因为它调用了很多绘图和筛选函数,但是当排除它调用的函数时,只有3.5%的时间花在相机渲染函数本身。
在这个帧中对这个函数的调用次数。 在Raw Hierarchy视图中,该列中的值始终为1,因为分析器不会合并示例的层次结构。
GC分配当前帧中分配了多少脚本堆内存。 脚本堆内存由垃圾收集器管理。 每当调用GC.Collect()或存在脚本堆分配不适合堆当前大小时,垃圾收集器就会被触发。它标记所有不再引用它们的分配并收集它们。这个过程显示为GC。 在分析器中收集样本。 当您在堆上分配更多内存时,Unity会更频繁地运行垃圾收集器。 随着托管堆的增长,Unity需要更长的时间来标记和收集内存。 因此,您应该在应用程序运行时将GC Alloc值保持为零,以防止垃圾收集器影响您的帧率,并保持总体堆大小较小。(这话说得就nmb离谱)
时间ms在特定函数上花费的总时间(以毫秒为单位)。 这一信息可能具有误导性,因为它只包含在主线程上花费的时间。 如果您的应用程序使用Job系统或多线程渲染,您应该注意这一点。
将花费在特定函数上的总时间(以毫秒为单位)用ms表示,不包括Unity调用子函数的时间。
警告由警告图标指示,它显示在当前帧中触发警告的次数。 您还可以通过从模块详细信息窗格右上角的Details下拉菜单中选择Show Related Objects或Show calls视图来获得关于应用程序调用和使用已配置函数的位置的更多信息。 Show Related Objects视图显示UnityEngine的列表。 使用获取UnityEngine.Object的Begin()重载与分析器示例关联的对象。 一些Unity报告的例子内置了这些关联,比如Camera .Render示例,该示例链接到执行渲染的摄像机对象。 这些对象通过实例ID报告,并在Profiler窗口中解析为名称。 当你点击其中一个对象时,Unity会试图通过场景找到该对象 层次结构并ping它。 因为关联使用实例ID,所以只有在分析应用程序编辑器时,以及对象仍然存在时,ping才会起作用。 GC.Alloc示例中,这个视图显示了一个“N/A”项列表,每个项对应于发生在这个层次结构级别的分配,GC中列出了分配的大小。 如果在编辑器中配置应用程序,并启用了Allocation Callstacks,则在选择GC时,在这个视图中,即使没有启用Deep Profiling设置,也会显示所选择的已分配脚本对象的调用堆栈。 Show Calls面板显示所选的样例从何处被调用,以及它调用的其他函数。 此外,在模块详细信息窗格顶部的gear图标下,您可以启用或禁用Collapse Editor Only Sample设置。这将折叠播放器循环中的所有示例,这些示例只会因为编辑器安全检查而发生。 当样本被折叠时,它们的GC.Alloc值不会影响所内建的GC.Alloc值。 默认情况下启用此设置。
除了脚本代码生成的示例外,Unity还提供了大量的示例,这些示例可以让您了解应用程序中占用了哪些时间。下表解释了一些更常见的示例所做的工作。
主线程基本示例提供了在应用程序上花费的时间与在编辑器和分析器活动上花费的时间之间的明确分隔。记录器还可以使用这些样本来获取主线程上帧的计时。
将根循环到来自应用程序主循环的任何示例。当您在播放器以活动播放模式在编辑器中运行时启用Profile Editor设置时,此示例将嵌套在EditorLoop之下。
将根循环到来自编辑器主循环的任何示例。这只在您在编辑器中配置播放器时才会出现。当您禁用Profile Editor设置时,此示例将显示帧的渲染和运行包含播放器的编辑器所花费的时间。
collecteditorstats是与为不同的活动分析器模块收集统计信息相关的任何示例的根。子样本分析器下的任何样本。CollectGlobalStats会给玩家带来开销。所有其他子样例只影响编辑器。 要关闭特定模块,请关闭它们的图表或调用profile.setareaenabled()。
除非你使用的是Job系统,否则你的大部分脚本代码都嵌套在以下示例下面:
这个示例包括对MonoBehaviour的调用。协同程序的更新和处理。
这个示例处理所有Update()方法。
在第一次生成后包含协程样本。
这个示例处理所有的LateUpdate()方法。
这个示例处理所有FixedUpdate()方法。
这些示例显示CPU在哪些地方花费时间为GPU处理数据,或者在哪些地方等待GPU完成。如果GPU分析器不可用,或者它增加了太多的开销,工具栏不会显示这些信息。这些示例可以让您了解是cpu性能瓶颈还是gpu瓶颈。
应用程序等待目标FPS的时间,由Application.targetFrameRate指定。 如果这个示例是Gfx.WaitForPresent的子示例。表示应用程序等待QualitySettings.vSyncCount中配置的VSync的时间。 注意:编辑器不会在GPU上进行VSync,而是使用WaitForTargetFPS来模拟VSync的延迟。 一些平台,特别是Android和iOS,强制执行VSync,或者默认帧速率上限为30或60。
包含渲染线程上渲染命令的所有处理。其中一些时间可能用于等待来自主线程的VSync或新命令,您可以从它的子示例Gfx.WaitForPresent中看到这一点。
表示渲染线程已经为新的命令做好了准备,并且可能表示在主线程上有瓶颈。
表示应用程序等待GPU渲染和呈现帧的时间,这可能包括等待VSync。 主线程上的WaitForTargetFPS示例显示了等待VSync花费了多少时间。
表示主线程已经准备好开始渲染下一帧,但是渲染线程还没有完成对GPU渲染帧的等待。这可能表明您的应用程序是gpu性能瓶颈的。 要查看渲染线程同时花费了多少时间,请检查时间轴视图。 如果渲染线程在Camera.Rende中花费时间,你的应用程序是cpu性能瓶颈的,可能花费太多的时间发送draw calls或纹理到GPU。 如果渲染线程在Gfx.PresentFrame中花费时间。你的游戏是GPU性能瓶颈的,或者它可能正在GPU上等待VSync。一个GFX.WaitForTargetFPS子样例。 Gfx.WaitForPresent指示应用程序花费时间用于等待VSync的部分。
下表概述了一些高级物理分析器示例。 FixedUpdate调用所有这些示例。
通过指示物理引擎(PhysX)运行其模拟来更新当前物理的状态。
所有非布物理作业。展开此示例,以显示物理引擎内部所做工作的底层细节。
处理所有的布物理工作。展开此示例,以显示物理引擎内部所做工作的底层细节。
从物理引擎中收集物理仿真结果。
更新所有物理实体的位置和旋转。此示例还包含在发送这些更新时进行通信的消息。
在物理FixedUpdate结束后运行。处理各个阶段对仿真结果的响应。Contacts、铰链。在这个示例中,中断并触发更新和消息。有四个不同的子阶段: Physics.TriggerEnterExits进程OnTriggerEnter和OnTriggerExit事件。 Physics.TriggerStays处理OnTriggerStay事件。 Physics.Contacts处理OnCollisionEnter、OnCollisionExit和OnCollisionStay事件。 Physics.JointBreaks处理更新和有关关节断裂的信息。
包含了与布及其蒙皮网格相关的更新。
管理所有物理对象的位置和旋转的插值。
CPU分析器可以检测一些常见的性能问题并警告您。这些将出现在模块详细信息窗格中的Hierarchy视图的警告列中。

Profiler可以检测到的具体问题有: Rigidbody.SetKinematic:为刚体重建非凸网格碰撞体 Animation.DestroyAnimationClip:触发RebuildInternalState Animation.AddClip:触发RebuildInternalState Animation.RemoveClip:触发RebuildInternalState Animation.Clone:触发RebuildInternalState AnimationDeactivate:触发RebuildInternalState
如果在编辑器中配置应用程序,可以看到GC的完整调用堆栈样本。 为此,在Profiler窗口工具栏的Allocation Callstacks下拉菜单中启用Managed Allocations。在您打开此选项后GC.Alloc样本包含它们的调用堆栈。 每个脚本堆分配都显示为GC层次结构视图和时间轴视图中的示例。 在时间轴视图中,它是明亮的洋红色。要查看调用堆栈,请选择CPU分析器模块并选择GC.Alloc在时间轴视图中的样本。调用堆栈出现在选择突出显示中。 或者,您可以在层次结构或原始层次结构视图中查看调用堆栈。设置Details视图以显示相关对象。因为GC.Alloc样本没有名称,它们在这个面板中显示为N/A。当您选择一个N/A对象时,调用堆栈将显示在Details视图的下半部分。


有一些在编辑器中进行概要分析时才会出现的一些示例。这包括安全检查,比如GetComponentNullErrorWrapper,它帮助识别空组件的使用情况;校验一致性,验证对象设置;CheckAllowDestructionRecursive,这是一个销毁检查;和Prefab-related活动。所有这些示例都不存在于播放器中。

默认情况下,Editor only samples在Hierarchy视图中折叠,并命名为EditorOnly SampleName。而它们可能导致GC。如果被折叠,它们对其所附样本的GC没有贡献。 要更改默认行为,请单击模块详细信息窗格右上角的gear图标,并禁用折叠编辑器only Samples选项。当您这样做时,您可以扩展样例并贡献它的GC将值赋给所附示例。

此选项不影响时间轴视图。这些示例通常可以被忽略,并提示在目标设备上配置Player构建,以发现实际问题。
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po