关于 Cocos Creator 在 Chrome 控制台性能调试·指东不指南(略讲)

关于 Cocos Creator 在 Chrome 控制台性能调试·指东不指南(略讲)

起因::=>

最近看到麒麟子大大发布了个挺有意思的 Cocos版冰墩墩仿真渲染 ::=>
Cocos Creator | bindundun (creator-star.cn)
麒麟子老大已经开源,感兴趣的朋友可以去研究下::=>
[Kylins]Cocos版冰墩墩仿真渲染

发展::=> 大概看了下,感觉真的非常流畅

经过::=>

正好本人最近也有在研究这个 Chrome Performance 调试这一块,本来是打算分享会讲的,
看到麒麟子老大发的这个就有了个想法,在这里就提前讲了吧,
就用麒麟子老大发的这个来演示下如何更好地进行 ** Chrome 调试 **?!!!

结尾::=> 就写了这个文章,欢迎大家查漏补缺 :smiley: :laughing: :smiley:

本文引用的资料来源::=>

1. Microsoft Edge Development 的内容:::=>

1.1 在任何网页上运行 JavaScript 的代码片段 - Microsoft Edge Development | Microsoft Docs
1.2 调试 JavaScript 入门 - Microsoft Edge Development | Microsoft Docs
1.3 使用实时表达式监视 JavaScript 中的更改 - Microsoft Edge Development | Microsoft Docs
1.4 分析运行时性能入门 - Microsoft Edge Development | Microsoft Docs
1.5 分析运行时性能 - Microsoft Edge Development | Microsoft Docs
1.6 在控制台中运行 JavaScript - Microsoft Edge Development | Microsoft Docs
1.7 性能功能参考 - Microsoft Edge Development | Microsoft Docs

2. Google Chrome 控制台里面 Performance 的 Warning Long task 的内容:::=>

2.1 Google Chrome 控制台里面 Performance 的 Warning Long task 的使用 RAIL 模型衡量性能

开讲,仅讲个人比较常用的地方(其余,略)

1.1 在任何网页上运行 JavaScript 的代码片段

1.1.1 个人理解就是可以替代 bookmarklet 来使用,很方便

代码片段是在工具中创作的脚本。
代码段有权访问网页的 JavaScript 上下文,并且您可以在任何网页上运行代码段
代码段是 bookmarklet 的替代方法,
区别在于代码段仅在 DevTools 中运行,并且不限于 URL 的允许长度

1.1.2 举例截图,而且感觉更方便,可以自由保存,可以换行格式化代码

1.2 调试 JavaScript 入门

1.2.1 事件侦听器断点,可以自动断点调试,断点时建议开启 Pause on exceptions

简单来说就是可以监听鼠标点击事件,然后断点(其它事件也可以)
想在 click 侦听器运行期间暂停代码 , 事件侦听器断点 可让实现此要求:

  1. 在调试 器窗格中 ,单击 “事件侦听器断点” 以展开部分。 开发工具显示可展开事件类别的列表,如 动画剪贴板
  2. 在" 鼠标事件" 类别旁边, 单击"展开 (展开"图标。) 。 开发工具显示鼠标事件的列表,如 单击鼠标按下 。 每个事件旁边都有一个复选框。
  3. 选中单击旁边的 复选框 。 现在开发工具设置为在运行任何 click 事件侦听器时自动暂停。

1.2.2 举例截图,自动监听用户点击事件,然后断点,

1.2.3 Pause on exceptions 自动报错断点可以追踪代码错误然后自动断点


1.3 使用实时表达式监视 JavaScript 中的更改

1.3.1 添加新实时表达式,点小眼睛,输入表达式


image
image

1.4 分析运行时性能入门

1.4.1 模拟移动 CPU,可以用于模拟 IOS 的环境,非常方便测试(建议使用)

与台式机和笔记本电脑相比,移动设备的 CPU 功率更小。 每当你分析页面时,都可使用 CPU 节流来模拟页面在移动设备上的表现。

  1. 在 DevTools 中,打开 性能 工具。
  2. 选中"屏幕截图"旁边的 复选框
  3. 单击 "捕获设置 ( 捕获设置。)。 DevTools 显示了有关如何捕获效果指标的设置。
  4. 对于 " CPU ",选择 4x 减速 。 DevTools 将 CPU 限制为比平时慢 4 倍(类似IOS环境)。

CPU 限制。

中文版截图::=>

在测试其他页面时;如果想确保每个页面在低端移动设备上都能很好的运行,将CPU限制设置为 6倍减速 。 演示在速度慢 6 倍时运行不顺利,因此它仅使用 4 倍减速进行说明。

1.4.2 记录运行时性能,可以监测代码 Long Task 耗时的地方(建议使用)

运行优化版本的页面时,蓝色图标会移动得更快。 为什么? 两种版本都应该在相同的时间内将图标移动相同的空间。 在性能工具 录制,了解如何检测未优化版本中的性能瓶颈。

  1. 在 DevTools 中 ,单击" 记录 (记录 "。) 。 页面运行时,DevTools 将捕获效果指标。配置文件页面。
  2. 稍等几秒钟。
  3. 单击 停止 。 DevTools 停止录制,处理数据,然后在性能工具 中显示 结果。配置文件的结果。

1.4.3 记录运行时性能,可以监测+分析每秒帧数(建议使用)

测量任何动画性能的主要指标是每秒帧数 (FPS) 。 当动画以 60 FPS运行时,用户会觉得很享受。

  1. 查看 FPS 图表,如下所示。 每当红色条显示在 FPS 上方时,这意味着帧速率下降得过低,可能损害用户体验。 通常,绿色条越高,FPS 越高。FPS 图表。
  2. FPS 图表下方,显示 CPU 图表。 CPU 图表中的颜色对应于 “性能"工具底部的"摘要”**** 面板 的颜色。 CPU 图表充满颜色意味着在录制过程中 CPU 已达到极限。 只要 CPU 长时间达到最大值,即表示你应该找到减少工作的方法。CPU 图表和摘要面板。
  3. 将鼠标悬停在 FPSCPUNET 图表上。 DevTools 将显示该时间点处的页面截图。 左右移动鼠标以重播录音。 操作称为 推移 ,它可用于手动分析动画进度。查看 2500 毫秒记录标记周围的页面屏幕截图。
  4. 在“ 框架 ”部分,将鼠标悬停在其中一个绿色方块上。 DevTools 将显示该特定帧的 FPS。 每帧可能远低于 60 FPS的目标。将鼠标悬停在图框上。

1.4.4 打开 FPS 计数,可以监测+分析每秒帧数(建议使用)

另一个非常方便的工具是 FPS 计数,可在页面运行时提供对 FPS 的实时估计

  1. Control``P``Shift ++ (Windows、Linux) 或 Command``Shift ++ P (macOS) 打开命令 菜单
    1.1 如下图打开, windows 上控制台快捷键(ctrl+shift+p),输入fps,直接show::=>

  2. 开始在"命令 Rendering 菜单" 中键入内容, 然后单击" 显示呈现"
  3. 在呈现 工具 中,打开 FPS 指示器 。 新的叠加层将显示在视线的右上角。FPS 指示器。
  4. 关闭 FPS 指示器, 然后按 Escape 以关闭 呈现 工具。 本教程中未 使用 FPS 指示器。

1.4.5 控制台 录制 Performance 后查找瓶颈(建议使用)

测量并验证动画运行不佳后,下一步是回答"为什么?"这一问题。

  1. 未选择任何事件时,“ 摘要 ”面板将显示活动的细目。 页面大部分时间都在渲染。 由于性能是减少工作量的艺术,因此你的目标是减少花费在进行绘制工作上的时间。摘要面板。
  2. 展开 重点 部分。 DevTools 将显示一段时间内主线程上活动的帧图表。 x 轴表示一段时间内的记录。 每个条形表示一个事件。 宽条表示该事件花费了更长的时间。 Y 轴表示调用堆叠。 当事件堆叠在一起时,这意味着上面的事件导致了下面的事件。"主"部分。
  3. 录制中有很多数据。 To Zoom into a single event, click, hold, and drag your cursor over the Overview , which is the section that includes the FPSCPU , and NET charts. " 节"和" 摘要 "面板仅显示记录的选定部分的信息。放大事件。另一种缩放方式是:将焦点放在 "主 "部分,单击背景或事件,然后按、 W``A 、、 SD
  4. 重点关注 动画帧触发 事件右上角的红色三角形。 每当显示红色三角形时,都会显示一条警告,指出可能有与事件相关的问题。每当运行 requestAnimationFrame() 时,将发生 动画帧触发 事件。
  5. 单击 动画帧触发 事件。 “ 摘要 ”面板现在将显示有关该事件的信息。 请注意“ 显示 ”链接。 单击它后,DevTools 将突出显示启动 动画帧触发事件 的事件。 另外,请关注 app.js:95 链接。 单击它后,将显示源代码中的相关行。有关动画帧触发事件详细信息。单击事件后,使用箭头键选择它旁边的事件。
  6. app.update 事件下,有一组紫色事件。 如果每个紫色事件都比较宽,看起来每个事件上可能都有个红色三角形。
  7. 单击紫色的 Layout 事件 之一。 DevTools 在 摘要 面板中提供了有关事件详细信息。 实际上,存在一条有关强制重排的 (另一个单词的 _布局) _ 。
  8. 在摘要 面板中 ,单击布局强制下的app.js ** :71** 链接 。 DevTools 将转到强制布局的代码行。导致强制布局的代码行。这段代码的问题在于,在每个动画帧中,它都会改变每个图标的样式,然后查询每个图标在页面上的位置。 由于样式发生更改,浏览器不知道每个图标位置是否更改,因此必须重新布局图标才能计算新位置。

1.5 分析运行时性能

1.5.1 控制台 录制 Performance 后的一些分析

在性能工具 中录制 并查找可疑的长 Evaluate Script 事件。
在"性能"工具 中录制 。 检查录制中是否显示 Recalculate Style 紫色 (大) 。
在" Recalculate Style 详细信息"窗格中选择一个事件以查看其 详细信息 。 如果样式更改需要很长时间,则性能下降。 如果样式计算影响大量元素,则这是另一个有改进空间的区域。

长重新计算样式。

若要降低事件 Recalculate Style 的影响,请:

  • 使用 CSS 触发器了解 哪些 CSS 属性触发器布局、绘制和复合。 这些属性对呈现性能的影响最大。
  • 切换到影响较少的属性。
    " 性能 "窗格标识页面何时导致强制同步布局。 这些事件 Layout 用红色条标记。

强制同步布局。

"布局分隔"是强制同步布局条件的重复。 当 JavaScript 重复写入和读取 DOM 时,会出现此情况,这会强制浏览器重新计算一次又一次布局。 若要标识布局限制,请查找多个强制同步布局警告的模式。 查看上图。

1.6 在控制台中运行 JavaScript ,简单执行(个人比较常用)

1.6.1 在控制台输入简单的代码

可以在控制台中输入任何 JavaScript 表达式、语句或代码段,并且**** 它会在键入时立即以交互方式运行。 这是可行的,因为 DevTools 中的控制台工具是一个 REPL 环境。**** REPL 代表 Read、Evaluate、Print 和 Loop。

控制台:

  1. 读取您键入的 JavaScript。
  2. 评估代码。
  3. 输出表达式的结果。
  4. 循环回第一步。

若要在控制台中以交互方式输入 JavaScript 语句和表达式:

  1. 在网页中右键单击,然后选择"检查 " 。 将打开 DevTools。 或者,按 Control ++ Shift``J \ (Windows、Linux) 或 J Command + Option +\ (macOS) 直接打开 DevTools 控制台。
  2. 如有必要,请在 DevTools 中单击以赋予其焦点,然后按 Esc 以打开 控制台
  3. 在控制台 中单击 ,然后键入 2+2 ,而无需按 Enter 。键入 ,控制台会立即在 4 下一行上显示结果。 该功能 Eager evaluation 可帮助你编写有效的 JavaScript。 无论 JavaScript 是否正确以及是否存在有效结果,控制台都会在键入时显示结果。控制台将在您键入表达式"2 + 2"时以交互方式显示该表达式的结果。
  4. 按 时 Enter ,控制台将**** 运行 JavaScript 命令 (表达式或语句) ,显示结果,然后向下移动光标以允许您输入下一个 JavaScript 命令。连续运行多个 JavaScript 表达式。

1.6.2 在控制台编写复杂表达式的自动完成(写Cocos的代码也会有自动代码提示)

控制台 可帮助 你使用自动完成编写复杂的 JavaScript。 此功能是了解以前不知道的 JavaScript 方法的一种好方法。

在编写多部分表达式时尝试自动完成:

  1. 键入 doc
  2. 按箭头键在下拉菜单 document 上突出显示。
  3. Tab 以选择 document
  4. 键入 .bo
  5. Tab 以选择 document.body
  6. 键入另 . 一个,获取当前网页正文中可用的可能属性和方法的大型列表。JavaScript 表达式的控制台自动完成。

1.6.3 控制台输入 Cocos 的代码

image
image

1.6.4 控制台历史记录(之前输入的代码也能找到)

与许多其他命令行环境一样,输入的命令历史记录也可供重复使用。 按 Up Arrow 以显示之前输入的命令。

同样,自动完成会保留以前键入的命令的历史记录。 可以键入之前命令的前几个字母,之前的选择将显示在文本框中。

此外, 控制台 还提供了很多实用程序 方法 ,可简化您的生活。 例如, $_ 始终包含你在控制台中运行的最后一个表达式 的结果

控制台中的 $_ 表达式始终包含最后的结果。

1.6.5 控制台多行编辑

默认情况下, 控制台只 为你提供一行来编写 JavaScript 表达式。 按 时,代码将运行 Enter 。 单行限制可能会使您费时无用。 若要绕绕 1 行限制,请按 Shift + Enter 而不是 。 Enter 在下面的示例中,显示的值是运行顺序 (语句) 的结果:

按 Shift+Enter 可编写几行 JavaScript。 生成的值为 output。

如果在控制台中启动多行语句,将自动识别**** 代码块并缩进。 例如,如果通过输入大括号来启动块语句,则下一行将自动缩进:

控制台使用大括号和缩进识别多行表达式。

1.6.6 控制台使用顶级 await () 的网络请求

除了在你自己的脚本中, 控制台支持顶级 await 在它内运行任意异步 JavaScript。 例如,使用 API 时 fetch 无需使用 await async 函数包装语句。

若要获取最近 50 个在 Microsoft Edge 开发人员工具中Visual Studio Code GitHub存储库:

  1. 在 DevTools 中,打开 控制台
  2. 复制并粘贴以下代码段,获取包含 10 个条目的对象:

Javascript复制

await ( await fetch(
'https://api.github.com/repos/microsoft/vscode-edge-devtools/issues?state=all&per_page=50&page=1'
)).json();

控制台显示顶级异步提取请求的结果。这 10 个条目很难识别,因为会显示大量信息。
3. (可选)使用 console.table() log 方法仅接收您感兴趣的信息:使用"console.table"以可读格式显示最后的结果。若要重用从表达式返回的数据,请使用 copy() 控制台的实用程序 方法
4. 粘贴以下代码。 它将发送请求并将响应数据复制到剪贴板:

Javascript复制

copy(await (await fetch(
'https://api.github.com/repos/microsoft/vscode-edge-devtools/issues?state=all&per_page=50&page=1'
)).json())

1.6.7 控制台查看所有代码历史记录(之前输入的历史代码可以导出, :grinning:)

1.先把控制台独立出来, 固定控制台页面
2. 按快捷键:ctrl+shift+j
3.打开 Application(内存) 的 Local Storage(本地存储) 的 devtools 里面就可以看到了
4.可以用关键词 previouslyViewedFiles, consoleHistory ,consolePins ,experiments 操作



image

1.7 性能功能参考(稍多一点点,比较好)

1.7.1 记录运行时性能

当你想在页面运行时 (而非加载时) 分析其性能时,将记录运行时性能。

  1. 转到要分析的页面。
  2. 单击 DevTools 中的"性能"工具。****
  3. 单击" 录制 ( "图标。)按钮。记录。
  4. 与页面交互。 DevTools 将记录由于交互而发生的所有页面活动。
  5. 再次 单击"录制 "或单击 "停止 "停止录制。

1.7.2 记录加载性能

当你想在页面加载时 (而非运行时) 分析其性能时,将记录加载时性能。

  1. 转到要分析的页面。
  2. 在 DevTools 中,打开 性能 工具。
  3. 单击" 刷新"页 ( "刷新页面"。) "按钮。 DevTools 在页面刷新时记录性能指标,然后在加载完成后几秒钟自动停止记录。

刷新页面。

DevTools 会自动放大大部分活动发生的记录部分。

页面加载录制。

1.7.3 录制时捕获屏幕截图

若要在录制时捕获每个帧的屏幕截图,请选中 “屏幕截图” 复选框。

"屏幕截图"复选框。

若要了解如何与屏幕截图进行交互,请参阅 查看屏幕截图

1.7.4 录制时强制收集垃圾

在记录页面时,单击****"收集垃圾 (收集垃圾图标。) 强制进行垃圾回收。

收集垃圾。

1.7.5 显示录制设置

单击 捕获 ( 捕获设置。) 公开与 DevTools 如何捕获性能记录相关的更多设置。

"捕获设置部分。

1.7.6 禁用 JavaScript 示例

默认情况下,录制的 部分会显示录音期间调用的 JavaScript 函数的详细调用栈。 禁用以下调用堆栈:

  1. 打开 “捕获设置” 菜单。 请参阅 显示录制设置
  2. 打开 “禁用 JavaScript 示例” 复选框。
  3. 记录页面。

以下两个图显示了禁用和启用 JavaScript 示例的区别。 当禁用取样时,录音的 部分要短得多,因为它省略了所有的 JavaScript 调用堆栈。

禁用 JS 示例时录制的示例:

禁用 JS 示例时录制的示例。

启用 JS 示例时录制的示例:

启用 JS 示例时录制的示例。

1.7.7 在录制时限制网络

若要在录制时限制网络:

  1. 打开 “捕获设置” 菜单。 请参阅 显示录制设置
  2. “网络” 设置为所需的限制级别。

1.7.8 录制时限制 CPU

若要在录制时限制 CPU:

  1. 打开 “捕获设置” 菜单。 请参阅 显示录制设置
  2. “CPU” 设置为所需的限制级别。

限制是相对于计算机的功能而言的。 例如, 两倍减速 选项使 CPU 运行速度比正常情况下慢两倍。 DevTools 不会真正模拟移动设备的 CPU,因为移动设备的体系结构与台式机和笔记本电脑的体系结构完全不同。

1.7.9 启用高级画图检测工具

查看详细画图检测工具:

  1. 打开 “捕获设置” 菜单。 请参阅 显示录制设置
  2. 选中 “启用画图检测工具 (慢速)” 复选框。

若要了解如何与绘制信息进行交互,请参阅查看 图层查看画图探查器

1.7.10 保存录制内容

若要保存录制,请右键单击该录制,然后选择"保存 配置文件"

保存配置文件。

1.7.11 加载录制

若要加载录制,请右键单击该录制,然后选择" 加载配置文件"

加载配置文件。

1.7.12 清除上一记录

录制后,单击 "清除录制 (清除录制" 图标。) "性能"工具清除 录制。

清除录制。

1.7.13 分析性能录制

录制运行性能录制加载性能 之后, 性能 面板将提供许多数据以分析刚发生的操作的性能。

1.7.14 选择录制的一部分

“概述” 上向左或向右拖动鼠标,以选择一段录音的一部分。 概述 是包含 FPSCPUNET 图表的部分。

将鼠标拖动到概述中可缩放。

若要使用键盘选择一部分:

  1. 选择" 主"部分 的背景或它旁边的任何部分,如" 交互 "、网络或 GPU 。 **** 此键盘工作流仅在其中一个分区为焦点时有效。
  2. 使用 WASD 键分别进行放大、向左移动、缩小和向右移动。

若要使用跟踪板选择部分:

  1. 将鼠标悬停在 “概述” 部分或 “详细信息” 上。 概述 部分是包含 FPSCPUNET 图表的区域。 详细信息 部分是包含 部分、 交互 部分等的区域。
  2. 使用两根手指,向上轻扫进行缩小,向左轻扫向左移动,向下轻扫进行放大,向右轻扫向右移动。

若要在"主"部分或任何元素**** 中滚动长图表,请在向上和向下拖动时单击并按住。 向左和向右拖动,移动录音中所选的部分。

1.7.15 搜索活动

Ctrl + F (Windows、Linux) 或 F Command + (macOS) 打开"性能"面板底部的 搜索 框。

搜索框。

导航与查询匹配的活动:

  1. 单击"上 一 ( "。 ) "下 一 ("下一) 按钮。
  2. 若要选择下一个活动,请按 Enter 。 若要选择上一个活动,请按 Shift + Enter

修改查询设置:

  • 若要使查询区分大小写,请单击****"区分大小写 (区分大小写。) 按钮。
  • 若要在查询中使用正则表达式,请单击****"正则表达式 (正则表达式") 按钮。

若要隐藏搜索框,请单击"取消 "

1.7.16 查看主线程活动

使用 部分查看出现在页面主线程上的活动。

"主"部分。

在"摘要"面板中选择一个事件以查看其 详细信息 。 DevTools 概括了所选事件。

有关"摘要"面板中的匿名函数详细信息。

DevTools 使用火焰图表示主线程活动。 x 轴表示一段时间内的记录。 Y 轴表示调用堆叠。 顶部事件将导致其下方事件。

绘制图表。

在上一图中, click 事件在 53 行的 activitytabs.js 中造成了 Function Call 。 在 Function Call 下面,查看匿名函数运行。 匿名函数请求 Minor GC 的请求 wait 的请求 a

DevTools 为脚本随机分配颜色。 在上图中,请求来自脚本的函数请求染成为浅绿色。 来自另一个脚本的请求以米色表示。 深黄色代表脚本活动,紫色事件代表渲染活动。 这些深黄色和紫色事件在所有记录中都是一致的。

如果要隐藏 JavaScript 请求的详细图表,请参阅上面的 禁用 JavaScript 示例。 禁用 JS 示例后 Event: click``Function Call ,仅处理上图中的和等高级事件 显示。

1.7.17 查看表格中的活动

录制页面后,无需仅依赖"主 "部分来 分析活动。 DevTools 还提供了三种用于分析活动的表格视图。 每个视图提供对待活动的不同视角:

  • 若要查看导致工作最多的根活动,请使用"调用树 " 选项卡。
  • 若要查看直接花费时间最多的活动,请使用" 底部向上" 选项卡。
  • 若要按记录期间活动发生的顺序查看活动,请使用" 事件日志" 选项卡。

1.7.18 根活动

打开新 窗口或选项卡 中的活动选项卡演示网页。

下面是"呼叫树"面板、 "底部向上"面板和"事件 日志"面板中**** 提及的根活动 概念 的说明。

活动是导致浏览器执行某些工作的活动。 例如,当您单击某个网页时,浏览器将运行一 Event 个活动作为根活动。 Event 可能会导致处理程序运行等。

部分的火焰图中,根活动位于图表顶部。 在 “调用树”“活动日志” 面板中,根活动是顶级项目。

有关根活动的示例,请参阅下一节"调用树选项卡"。

1.7.19 "呼叫树"选项卡

打开新 窗口或选项卡 中的活动选项卡演示网页。

使用" 呼叫树 "选项卡可查看 哪些根活动 导致工作最多。

" 呼叫树 "选项卡仅显示在录制的选定部分期间的活动。 请参阅 选择录音的一部分 ,了解如何选择部分。

"呼叫树"面板。

在上图中, “活动” 列中的顶级项目,如 Evaluate ScriptParse HTML 是根活动。 嵌套表示调用堆栈。 例如,在上图中,导致 Compile Script(anonymous)Evaluate ScriptParse HTML

“自我时间” 表示直接用于该活动的时间。 “总时间” 表示花在该活动或任何子项上的时间。

单击 "自时间 、总时间"或 "活动 "按该列对表进行排序。

使用 “筛选器” 文本框按活动名称筛选事件。

默认情况下, “分组” 菜单设置为 “无分组” 。 使用 “分组” 菜单,根据各种条件对活动表进行排序。

单击 "显示最 (堆栈") 显示"活动"表 右侧的另一 个表。 单击活动以填充 “最富堆栈” 表。 “最重堆栈” 表显示所选活动的子项需要最长的运行时间。

1.7.20 自下而上面板

打开新 窗口或选项卡 中的活动选项卡演示网页。

使用 “自下而上” 面板查看直接采用聚合时间的活动。

“自下向上” 面板仅在录制的选定部分期间显示活动。 请参阅 选择录音的一部分 ,了解如何选择部分。

"Bottom-Up面板。

在上 的主节绘制图中,可以看到几乎所有的时间都用于运行 Parse HTML 。 前图中 “自下而上” 面板中最上面的活动是 Parse HTML 。 In the Bottom-Up tab, the next most expensive activity is Layout .

“自我时间” 列表示跨越发生的所有直接用于该活动的聚合时间。

“总时间” 列表示花在该活动或任何子项上的聚合时间。

1.7.21 事件日志面板

使用 “事件日志” 面板按记录期间发生的顺序查看活动。

“事件日志” 面板仅显示录制的选定部分期间的活动。 请参阅 选择录音的一部分 ,了解如何选择部分。

"事件日志"面板。

“开始时间” 列表示活动开始时与录制开始相对的点。 例如,上图中所选项目 175.7 ms 的开始时间意味着录制开始 175.7 毫秒后活动开始。

“自我时间” 列表示直接用于该活动的时间。

“总时间” 列表示直接用于该活动或任何子项中的时间。

单击 "开始时间 "、“开始时间” 或"总 时间"按该列对表进行排序。

使用 “筛选” 文本框按名称筛选活动。

使用 “持续时间” 菜单筛选出所有耗时少于 1 毫秒或 15 毫秒的活动。 默认情况下, “持续时间” 菜单设置为 “全部” ,这意味着会显示所有活动。

禁用 加载脚本渲染绘制 复选框以筛选这些类别中的所有活动。

1.7.22 查看 GPU 活动

GPU 部分查看 GPU 活动。

GPU 部分。

1.7.23 查看光栅活动

光栅 部分中查看光栅活动。

"Raster"部分。

1.7.24 查看交互

使用 “交互” 部分查找和分析在录制期间发生的用户交互。

"交互"部分。

交互底部的红线表示等待主线程所花费的时间。

单击交互,在摘要面板中查看 有关它 的信息。

1.7.25 分析每秒帧数 (FPS)

DevTools 提供了许多方法,以分析每秒帧数:

1.7.26 FPS 图表

FPS 图表提供整个录制期间的帧率概况。 一般来说,绿条越高,帧率越好。

FPS 图上方的红色条形是警告,说明帧率降得太低,很可能会损害用户的体验。

FPS 图表。

1.7.27 ”帧“ 部分

“帧” 部分会准确告知特定帧所需的时间。

将鼠标悬停在框架上,查看工具提示,详细了解它。

将鼠标悬停在图框上。

在摘要面板中选择一个帧以查看有关 详细信息。 DevTools 用蓝色勾勒出所选框架的轮廓。

在摘要面板中查看帧。

1.7.28 查看网络请求

展开 “网络” 部分,以查看录制期间发生的网络请求瀑布图。

"网络"部分。

请求的颜色编码如下:

  • HTML: 蓝色
  • CSS: 紫色
  • JS: 黄色
  • 图像: 绿色

单击请求以查看"摘要"选项卡中 有关它 的信息。 例如,在上图中,“摘要”**** 选项卡显示有关在"网络"部分选择的蓝色 请求详细信息。

在请求的左上方有一个深蓝色的方块,意味着它是一个优先级较高的请求。 浅蓝色的方块表示优先级较低。 比如上图中,蓝色所选的请求是优先级较高的,而下方绿色的请求为优先级较低的。

在下面的第一个 www.bing.com 图中,对 的请求表示为左侧的一行、中间有深色部分的条形和浅色部分,以及右边的一条线。 下图显示了网络工具的"计时"选项卡中相同请求的相应 表示 形式。****

下面将说明这两种表示形式如何相互映射:

  • 左行是到事件的 Connection Start 组的所有内容 (包括)。 换句话说,它是之前的所有内容,不包括 Request Sent
  • 条形图的浅部分为 Request SentWaiting (TTFB)
  • 条形图的深色部分为 Content Download
  • 右行基本上是等待主线程所花的时间。 This isn’t represented in the Timing tab.

请求的线栏表示 www.bing.com 形式:

请求的线 www.bing.com 表示。

网络工具

网络工具。

1.7.29 查看内存指标

打开 “内存” 复选框以查看上次记录中的内存指标。

"内存"复选框。

DevTools 在 “摘要” 面板上方显示新的 “内存” 图表。 NET 图表下方还有一个新的图表,称为 “HEAP”“HEAP” 图表提供的信息与 “内存” 表中的 “JS Heap” 行相同。

内存指标。

图表上的彩色线条会映射到图表上方的彩色复选框上。 清除复选框以在图表中隐藏该类别。

图表只显示当前选择的记录区域。 例如,在上一个图中, 内存 图表仅显示从 400 毫秒标记上下到 1750 毫秒标记左右的内存使用情况。

1.7.30 查看部分录制的持续时间

当分析像 网络 或者 这样的部分时,有时你需要更精确地估计某些事件花了多长时间。 按住 Shift 、单击并按住,然后向左或向右拖动以选择录制的一部分。 在所选内容底部,DevTools 显示该部分所话费的时间。

查看录制的一部分的持续时间。

2.1 使用 RAIL 模型衡量性能(就是把 Game Logic 控制在50ms以内,越小越好)

2.1.1 使用 RAIL 模型衡量性能(全)

RAIL 是一种以 用户为中心 的性能模型,它提供了一种考虑性能的结构。该模型将用户体验分解到按键操作(例如,点击、滚动、加载)中,帮助您为每个操作定义性能目标。

RAIL 代表 Web 应用生命周期的四个不同方面:响应、动画、空闲和加载。用户对这些上下文分别有不同的性能期望,因此,性能目标是根据上下文以及用户如何感知延迟的用户体验研究来定义的。

2.1.2 RAIL 性能模型的四个部分

以用户为中心 #

将用户作为性能工作的关键点。下表介绍了用户如何感知性能延迟的关键指标:

用户对性能延迟的看法

0 至 16 毫秒 用户非常关注轨迹运动,他们不喜欢不流畅的动画。如果每秒渲染 60 个新帧,他们就认为动画很流畅。也就是说,每一帧只有 16 毫秒时间,这包括浏览器将新帧绘制到屏幕所需的时间,因而应用约有 10 毫秒的时间来生成一个帧。
0 到 100 毫秒 在此时间窗口内响应用户操作会让用户觉得结果是即时呈现的。如果时间更长,操作与用户反应之间的联系就会中断。
100 到 1000 毫秒 在此时间窗口内,用户会觉得任务进展基本上是自然连续的。对 Web 上的大多数用户来说,加载页面或更改视图是一项任务。
1000 毫秒或更长 超过 1000 毫秒(1 秒),用户的注意力就会从正在执行的任务上转移。
10000 毫秒或更长 超过 10000 毫秒(10 秒),用户会感到失望,并且可能放弃任务。他们以后可能会回来,也可能不会再回来。

用户对性能延迟的感知有所不同,具体取决于网络条件和硬件。例如,通过快速 Wi-Fi 连接,在功能强大的台式机上加载站点时,通常只需不到 1 秒时间,用户已经习以为常。通过速度较慢的 3G 网络连接,在移动设备上加载站点则需要更长的时间,因此,移动用户通常会更有耐心。在移动设备上,5 秒钟内完成加载是更现实的目标。

2.1.3 目标和准则 #

在 RAIL 的上下文中,术语 目标准则 具有特定的含义:

  • 目标 :与用户体验相关的关键性能指标。例如,点击即可在 100 毫秒内绘制。由于人类的感知相对一致,因此,这些目标不太可能很快发生改变。
  • 准则 :帮助您实现目标的建议。这些准则可能特定于当前硬件和网络连接条件,因此可能会随着时间而改变。

响应:在 50 毫秒内处理事件 #

目标 :在 100 毫秒内完成由用户输入发起的转换,让用户感觉交互是即时的。

准则

  • 为了确保在 100 毫秒内产生可见响应,需要在 50 毫秒内处理用户输入事件。这适用于大多数输入,例如点击按钮、切换表单控件或启动动画。但是,这不适用于触摸拖动或滚动。
  • 尽管听起来可能有些自相矛盾,但是,即时响应用户输入并非总是正确的做法。您可以利用这 100 毫秒的时间窗口来执行其他需要消耗大量资源的工作,但是,注意不能妨碍用户。如果可能,应在后台工作。
  • 对于需要 50 毫秒以上才能完成的操作,请随时提供反馈。

2.1.4 在50 毫秒还是 100 毫秒? #

目标是在 100 毫秒内响应输入,那么,为什么我们的预算只有 50 毫秒?这是因为除输入处理外,通常还有需要执行其他工作,而且这些工作会占用可接受输入响应的部分可用时间。如果应用程序在空闲时间以推荐的 50 毫秒区块执行工作,这就意味着,如果输入在这些工作区块之一中发生,它最多可能会排队 50 毫秒。考虑到这一点,假设只有剩余的 50 毫秒可用于实际输入处理才是安全地做法。下图展示了这种影响,图中显示了在空闲任务期间收到的输入如何排队,从而减少可用的处理时间:

空闲任务如何影响输入响应预算。

动画:在 10 毫秒内生成一帧 #

目标

  • 在 10 毫秒或更短的时间内生成动画的每一帧。从技术上来讲,每帧的最大预算为 16 毫秒(1000 毫秒/每秒 60 帧≈16 毫秒),但是,浏览器需要大约 6 毫秒来渲染一帧,因此,准则为每帧 10 毫秒。
  • 目标为流畅的视觉效果。用户会注意到帧速率的变化。

准则

  • 在动画之类对计算速度要求极高的场景下,关键在于即使可行,您也不能执行任何其他操作,让不能执行的操作保持绝对最少。只要可能,您就要利用这 100 毫秒的响应时间预先计算最消耗资源的工作,从而最大限度地提高达到 60 fps 的几率。
  • 有关各种动画优化策略,请参阅渲染性能

识别所有类型的动画。动画不是花哨的 UI 效果。下面这些交互都是动画:

  • 视觉动画,例如进入和退出,补间和加载指示器。
  • 滚动。这包括滑动,即用户开始滚动,然后松开,而页面会继续滚动。
  • 拖放。动画通常遵循用户交互,例如平移地图或捏合缩放。

空闲:最大限度增加空闲时间 #

目标 :最大限度增加空闲时间以提高页面在 50 毫秒内响应用户输入的几率。

准则

  • 利用空闲时间完成延缓的工作。例如,对于初始页面加载,应加载尽可能少的数据,然后利用空闲时间加载其余数据。
  • 在 50 毫秒或更短的空闲时间内执行工作。如果时间更长,您可能会干扰应用在 50 毫秒内响应用户输入的能力。
  • 如果用户在空闲时间工作期间与页面交互,则应中断空闲时间工作,用户交互始终具有最高优先级。

加载:在 5 秒内交付内容并实现可交互 #

当页面加载缓慢时,用户注意力会分散,他们会认为任务已中断。加载速度快的网站具有更长的平均会话时间、更低的跳出率和更高的广告可见性

2.1.5 目标

  • 根据用户的设备和网络能力优化相关的快速加载性能。目前,对于首次加载,在使用速度较慢 3G 连接的中端移动设备上,理想的目标是在 5 秒或更短的时间实现可交互
  • 对于后续加载,理想的目标是在 2 秒内加载页面。

请注意,这些目标可能会随时间而改变。

2.1.6 准则

2.1.7 识别影响页面加载性能的因素:

  • 网络速度和延迟
  • 硬件(例如,速度较慢的 CPU)
  • 缓存逐出
  • L2/L3 缓存的差异
  • 解析 JavaScript

测量 RAIL 的工具 #

有一些工具可以帮助您自动执行 RAIL 测量。具体使用哪一种取决于您需要什么类型的信息,以及您喜欢什么类型的工作流程。

Chrome DevTools #

Chrome DevTools 对加载或运行页面时发生的一切活动进行深入分析。请参阅分析运行时性能入门,熟悉 性能 面板 UI。

2.1.8 以下 DevTools 功能密切相关:

Lighthouse #

web.dev/measure 下的 Chrome DevTools 中以 Chrome 扩展和 Node.js 模块的形式提供了 Lighthouse,WebPageTest 中也提供了此工具。只要您提供一个 URL,它就会模拟使用速度较慢的 3G 连接的中端设备在页面上运行一系列审核,然后提供关于加载性能的报告以及如何改进的建议。

2.1.9 以下审核密切相关:

响应

加载

WebPageTest 网页性能测试工具 #

WebPageTest 是一款网页性能测试工具,它使用实际浏览器来访问网页并收集计时指标。在 webpagetest.org/easy 上输入一个 URL,您可以获取在真实的 Moto G4 设备上使用速度较慢的 3G 连接时关于该页面的加载性能报告。您也可以将其配置为包含 Lighthouse 审核。

概述 #

2.1.10 RAIL 是一个将网站用户体验视为由不同交互组成的旅程的透镜。了解用户如何感知您的网站,从而设定对用户体验影响最大的性能目标。

  • 以用户为中心。
  • 在 100 毫秒内响应用户输入。
  • 播放动画或执行滚动时,在 10 毫秒内生成一帧。
  • 最大限度延长主线程空闲时间。
  • 在 5000 毫秒内加载交互式内容。

附加补充内容(控制台代码,黑科技 :laughing:)

继续补充一个优雅 :smile:的Ts写法 + 一种入侵式的日志大法 ! - 白玉无冰 ::=>

续补一个操作::=>

52赞

给大佬点赞!!!

1赞

:smile: :smile:
希望 Cocos 越来越好

各位大佬如果也有独门调试的Debug技巧,欢迎来这分享一下呀, :grinning: :grinning:,
后续如果有新内容,会继续更新到这个帖子里面 :grinning:

量很多,给大佬点赞

1赞

:rofl:好长的文章啊,大佬太用心了

1赞

这么长的讲解,不收藏就说不过去了

1赞

补充个内容,刚刚一直在回忆,
原来是想补充这个内容,忙了一下子就整忘了,现在补充下::=>

Cocos 浏览器预览页面的 控制台黑科技 (简写版)

1. 控制台日志输出(Ctrl+L可以快速清除日志记录)

  • console.log :普通信息
  • console.info :提示类信息
  • console.error :错误信息
  • console.warn :警示信息
console.log('祝愿 Cocos越来越好 ~');
console.info('祝愿 Cocos越来越好 ~');
console.warn('祝愿 Cocos越来越好 ~');
console.error('祝愿 Cocos越来越好 ~');

2. 控制台输出的日志点击后,可以直接跳转到对应代码


3. 再配合 console.groupconsole.groupEnd ,可以将这种分类管理的思想发挥到极致

console.group("app.foo");
console.log("来自 Cocos 1 模块的信息...");
console.groupEnd();
console.group("app.bar");
console.log("来自  Cocos2 模块的信息...");
console.groupEnd();

3.1 如下图::=>

4. 关于 console.log , Chrome 提供了这么一个API:第一个参数可以包含一些格式化的指令比如 %c

//注意要%c放在第一个位置
//console.log的第二个参数里面就是CSS的样式表,但是控制台支持的有限
console.log('%c祝愿 Cocos越来越好 ~', 'background-image:-webkit-gradient( linear, left top, right top, color-stop(0, #f22), color-stop(0.15, #f2f), color-stop(0.3, #22f), color-stop(0.45, #2ff), color-stop(0.6, #2f2),color-stop(0.75, #2f2), color-stop(0.9, #ff2), color-stop(1, #f22) );color:transparent;-webkit-background-clip: text;font-size:5em;');

console.log('祝愿 Cocos越来越好 ~ %c', 'background-image:-webkit-gradient( linear, left top, right top, color-stop(0, #f22), color-stop(0.15, #f2f), color-stop(0.3, #22f), color-stop(0.45, #2ff), color-stop(0.6, #2f2),color-stop(0.75, #2f2), color-stop(0.9, #ff2), color-stop(1, #f22) );color:transparent;-webkit-background-clip: text;font-size:5em;');

console.log('%c祝愿 Cocos越来越好 ~', 'color:purple;font-size:5em;');

4.1 举例截图::=>(这不是很赞?)

5. console.table 直接以表格的形式将数据输出

let testData=[{
    'cocos2.4.1':"2D",
    'cocos3.4.2':"3D",
    'cocos2.4.2':"2D",
    'cocos3.4.1':"3D",
}];
console.table(testData);

5.1 如下图::=>

6. 条件判断输出日志 console.assert

当你想代码满足某些条件时才输出信息到 控制台
那么你大可不必写 if 或者三元表达式(let a=3>3?(true):(false))来达到目的,
cosole.assert 便是这样场景下一种很好的工具,
它会先对传入的表达式进行断言,只有表达式为假时才输出相应信息到 控制台

var isDebug=false;
console.assert(isDebug,'开发中的log信息。。。');

var isDebug=!false;
console.assert(isDebug,'开发中的log信息。。。');

var isDebug=!!false;
console.assert(isDebug,'开发中的log2信息。。。');

6.1 如下图::=>

7. 计数日志 console.count

统计某段代码执行了多少次时也大可不必自己去写相关逻辑,
控制台内置的 console.count 可以很地胜任这样的任务。

function cocosFoo(){
	//其他函数逻辑。。。
	console.count('foo 被执行的次数::=>');
}
cocosFoo();
cocosFoo();
cocosFoo();

7.1 如下图::=>

image

8. 数据树形输出 console.dir

将DOM结点以JavaScript对象的形式输出到 控制台,
直接将该DOM结点以DOM树的结构进行输出,
与在元素审查时看到的结构是一致的。不同的展现形式,同样的优雅

let testData=[{
    'cocos2.4.1':"2D",
    'cocos3.4.2':"3D",
    'cocos2.4.2':"2D",
    'cocos3.4.1':"3D",
}];
console.dir(document.body);
console.log(document.body);
console.dir(testData);

8.1 如下图::=>

9. 函数执行时间计算输出 console.time & console.timeEnd

需要考量一段代码执行的耗时情况时,可以用 console.timeconsole.timeEnd 来做此事

console.time("Cocos Array initialize");
var array= new Array(10000000);
for (var i = array.length - 1; i >= 0; i--) {
    array[i] = new Object();
};
console.timeEnd("Cocos Array initialize");

9.1 如下图::=>

image

10. 查看CPU使用相关的信息 console.profile & console.timeLime

当想要查看CPU使用相关的信息时,
可以使用 console.profile 配合 console.profileEnd 来完成这个需求。
这一功能可以通过UI界面来完成,
Chrome 开发者工具里面有个tab便是 Profile

与此类似的功能还有 console.timeLine 配合 console.timeLineEnd ,
它的作用是开始记录一段时间轴,
同样可以通过 Chrome 开发者工具里的 Timeline 标签来进行相应操作。

console.profile("Cocos Array initialize");
var array= new Array(1000);
for (var i = array.length - 1; i >= 0; i--) {
    array[i] = new Object();
};
console.profileEnd("Cocos Array initialize");

10.1 如下图::=>

image

11. 堆栈跟踪相关的调试可以使用 console.trace

堆栈跟踪相关的调试可以使用 console.trace
这个同样可以通过UI界面完成。当代码被打断点后,
可以在 Call Stack 面板中查看相关堆栈信息。
上面介绍的都是挂在 window.console 这个对象下面的方法,
统称为Console API,接下来的这些方法确切地说应该叫命令,
Chrome 内置提供,在 控制台 中使用的,他们统称为Command Line API

console.time("Cocos Array initialize");
var array= new Array(3);
for (var i = array.length - 1; i >= 0; i--) {
    array[i] = new Object();
    console.trace(i);
};
console.timeEnd("Cocos Array initialize");

11.1 如下图::=>

12. 控制台自带的内容:: $

Chrome控制台 里,$用处是蛮多且方便的
$_ 命令返回最近一次表达式执行的结果,$0~$4则代表了最近5个你选择过的DOM节点,
功能跟按向上的方向键再回车是一样的,但它可以做为一个变量使用在你接下来的表达式中:

2+2//回车,再
$_+1//回车得5

12.1 如下图::=>

image

13. 复制控制台的数据结构 copy

//通过此命令可以将在控制台获取到的内容复制到剪贴板
//其它类似数据也行,但有时候不支持(可能被其它代码覆盖了)
copy(document.body)

13.1 如下图::=>

14. 对象操作 keys & values

前者返回传入对象所有属性名组成的数据,后者返回所有属性值组成的数组

let testData2=[{
    'cocos2.4.1':"2D",
    'cocos3.4.2':"3D",
    'cocos2.4.2':"2D",
    'cocos3.4.1':"3D",
}];
let kk=keys(testData2[0]);
let vv=values(testData2[0]);
console.log(kk,vv);
//不一样的log日志输出:::=>
console.log("输出对象内容::=>",[kk,vv]);

14.1 如下图::=>

15. monitor & unmonitor

monitor(function),它接收一个函数名作为参数,
比如 function a ,每次 a 被执行了,
都会在 控制台 输出一条信息,里面包含了函数的名称 a 及执行时所传入的参数。

而unmonitor(function)便是用来停止这一监听。

function sayCocos(name){
	alert('hello,'+name);
}
monitor(sayCocos);
sayCocos('Cocos welcome you!');
unmonitor(sayCocos);
sayCocos('Cocos welcome you!');

15.1 如下图::=>

16. debug & undebug

debug同样也是接收一个函数名作为参数。当该函数执行时自动断下来以供调试,
类似于在该函数的入口处打了个断点,可以通过debugger来做到,
同时也可以通过在 Chrome 开发者工具里找到相应源码然后手动打断点。
undebug 则是解除该断点。

function sayCocos(name){
    debugger;
    //console.debug("testDebug");
	console.log('hello,'+name);
};

16.1 如下图, debugger 代码断点调试更好用::=>

image

17. console.clear(); 用代码清空日志

console.clear() ==> 直接清空控制台所有的日志

// 用代码清空日志
console.clear();

17.1 如下图, 清除效果::=>

5赞

牛逼 看着感觉自己成长了、不少

1赞

666,奈何自己没文化,一句666行天下。

1赞

收藏收藏,肯定有用

1赞

单凭大佬截图数量,给大佬递茶,递烟,递茅台,大佬辛苦了。

2赞

上班摸鱼算啥

置顶两个月,以表敬意

1赞

:grinning: :grinning:
感谢大大的关注和鼓励

:rofl:,有点失眠,就来补充点内容吧::=>
1.之前补充的控制台的整合写法(筛选的几种),稍微优雅一点? :slightly_smiling_face: :grin:
2. 白玉无冰 大佬的=> 一种入侵式的日志大法

// 注意: TS 开发环境
// const { ccclass, property, executeInEditMode, playOnFocus, menu } = cc._decorator;

// @ccclass
// @executeInEditMode
// @playOnFocus
export class clog {
    constructor() {
        // super();
    };
    //  * @param logType  日志类型
    // ```js
    // // example
    // cl.log('hello,cocos');
    // ```
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings  普通信息
     * @param cssStyle  样式
     * @example
     * import { cl } from "./com_console_new";
     * cl.log('hello,cocos', 'color:red;font-size:20px;');
    */
    //  export function log(...logStrings: string | any[], cssStyle: string = 'color:purple;font-size:5em;'): void {
    // log(logStrings: string | any[], cssStyle: string = 'color:purple;font-size:5em;'): void {
    log(logStrings: string | any[], cssStyle: string = ''): void {
        if (CC_EDITOR) {
            Editor.log(["log=>", logStrings], cssStyle);
        } else {
            if (cssStyle.length <= 0) {
                console.log(logStrings);
            } else {
                console.log('%c' + logStrings, cssStyle);
            };
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 树形结构输出日志
     * @example
     * import { cl } from "./com_console_new";
     * cl.dir('hello,cocos');
    */
    dir(logStrings: string | any[]): void {
        if (CC_EDITOR) {
            Editor.log(["dir=>", logStrings]);
        } else {
            console.dir(logStrings);
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 提示类信息
     * @example
     * import { cl } from "./com_console_new";
     * cl.info('hello,cocos');
    */
    info(logStrings: string | any[]): void {
        if (CC_EDITOR) {
            Editor.log(["info=>", logStrings]);
        } else {
            console.info(logStrings);
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 错误类信息,爆红
     * @example
     * import { cl } from "./com_console_new";
     * cl.error('hello,cocos');
    */
    error(logStrings: string | any[]): void {
        if (CC_EDITOR) {
            Editor.log(["error=>", logStrings]);
        } else {
            console.error(logStrings);
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 警告类信息
     * @example
     * import { cl } from "./com_console_new";
     * cl.warn('hello,cocos');
    */
    warn(logStrings: string | any[]): void {
        if (CC_EDITOR) {
            Editor.log(["warn=>", logStrings]);
        } else {
            console.warn(logStrings);
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 表格样式结构输出日志
     * @example
     * import { cl } from "./com_console_new";
     * cl.table({hello:'hello,cocos',to:'world'});
    */
    table(logStrings: string | any[]): void {
        if (CC_EDITOR) {
            Editor.log(["table=>", logStrings]);
        } else {
            console.table(logStrings);
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 分组结构输出日志
     * @example
     * import { cl } from "./com_console_new";
     * cl.group('hello,cocos');
    */
    // group(logStrings: string|any[]): void {
    group(logStrings: string): void {
        if (CC_EDITOR) {
            Editor.log(["group=>", logStrings]);
        } else {
            console.group(logStrings);
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 分组结构End输出日志
     * @example
     * import { cl } from "./com_console_new";
     * cl.groupEnd();
    */
    groupEnd(): void {
        if (CC_EDITOR) {
            Editor.log("groupEnd");
        } else {
            console.groupEnd();
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 开始记录时间日志
     * @example
     * import { cl } from "./com_console_new";
     * cl.time('hello,cocos');
    */
    // time(logStrings: string | any[]): void {
    time(logStrings: string): void {
        if (CC_EDITOR) {
            Editor.log(["time=>", logStrings]);
        } else {
            console.time(logStrings);
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 时间日志结束
     * @example
     * import { cl } from "./com_console_new";
     * cl.timeEnd('hello,cocos');
    */
    timeEnd(logStrings: string): void {
        if (CC_EDITOR) {
            Editor.log(["timeEnd=>", logStrings]);
        } else {
            console.timeEnd(logStrings);
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 堆栈跟踪调试日志
     * @example
     * import { cl } from "./com_console_new";
     * cl.trace('hello,cocos');
    */
    trace(logStrings: string | any[] | any): void {
        if (CC_EDITOR) {
            Editor.log(["trace=>", logStrings]);
        } else {
            console.trace(logStrings);
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param logStrings 记录代码执行次数日志
     * @example
     * import { cl } from "./com_console_new";
     * cl.count('hello,cocos');
    */
    count(logStrings: string): void {
        if (CC_EDITOR) {
            Editor.log(["count=>", logStrings]);
        } else {
            console.count(logStrings);
        };
    };

    /**
     * !#en Log a DEBUG level message.
     * !#zh 输出 DEBUG 级别的信息。
     * @param isShowBool 是否输出日志
     * @param logStrings 条件判断输出日志
     * @example
     * import { cl } from "./com_console_new";
     * cl.assert(true,'hello,cocos');
    */
    assert(isShowBool: boolean = true, logStrings: string | any[]): void {
        if (CC_EDITOR) {
            Editor.log(["assert=>", isShowBool, logStrings]);
        } else {
            console.assert(isShowBool, logStrings);
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 直接清空控制台的所有的日志
     * @example
     * import { cl } from "./com_console_new";
     * cl.clear();
    */
    clear(): void {
        if (CC_EDITOR) {
            Editor.log("clear");
        } else {
            console.clear();
        };
    };
    /**
     * !#en Log a DEBUG level message.
     * !#zh 一种入侵式的日志大法 
     * 参考::=>白玉无冰=>http://lamyoung.com/javascript/2020/12/30/log/
     * @param target 注意!如果有 update || lateUpdate 方法,会一直输出这个日志!!!请谨慎使用!!!
     * @example
     ```js
      import { cl } from "./com_console_new";
      // &#64; == @
      &#64;cl.logClassFunc();
      &#64;ccclass
     ```
     */
    logClassFunc(): any {
        return function (target: any) {
            const className = target.prototype.constructor?.name || 'No Name';
            const propNames = Object.getOwnPropertyNames(target.prototype);
            for (let i = 0; i < propNames.length; ++i) {
                const prop = propNames[i];
                if (prop !== 'constructor') {
                    const desc = Object.getOwnPropertyDescriptor(target.prototype, prop);
                    const func = desc && desc.value;
                    if (typeof func === 'function') {
                        let oldFunc = (func as Function);
                        target.prototype[prop] = function () {
                            console.log(`[${className}] [${prop}] Begin`, ...arguments);
                            const ret = oldFunc.call(this, ...arguments);
                            console.log(`[${className}] [${prop}] End`);
                            return ret;
                        }
                    }
                }
            }
        }
    };
};
// export function logClassFunc() {
//     return function (target: any) {
//         const className = target.prototype.constructor?.name || 'No Name';
//         const propNames = Object.getOwnPropertyNames(target.prototype);
//         for (let i = 0; i < propNames.length; ++i) {
//             const prop = propNames[i];
//             if (prop !== 'constructor') {
//                 const desc = Object.getOwnPropertyDescriptor(target.prototype, prop);
//                 const func = desc && desc.value;
//                 if (typeof func === 'function') {
//                     let oldFunc = (func as Function);
//                     target.prototype[prop] = function () {
//                         console.log(`[${className}] [${prop}] Begin`, ...arguments);
//                         const ret = oldFunc.call(this, ...arguments);
//                         console.log(`[${className}] [${prop}] End`);
//                         return ret;
//                     }
//                 }
//             }
//         }
//     }
// };
export let cl = new clog();

大佬这叫「略讲」,是我格局小了,给大佬递茶 :rofl: :rofl: :rofl:

1赞

大佬控制台玩得溜啊!

1赞

帖子收下,膝盖给你

1赞