<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>狂飙</title>
    <link>https://networm.me/</link>
    <description>Recent content on 狂飙</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-cn</language>
    <lastBuildDate>Sun, 22 Mar 2026 23:29:46 +0800</lastBuildDate><atom:link href="https://networm.me/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Spine 插件导致 Unity 打包耗时过长</title>
      <link>https://networm.me/2026/03/22/unity-spine-import-slow/</link>
      <pubDate>Sun, 22 Mar 2026 23:29:46 +0800</pubDate>
      
      <guid>https://networm.me/2026/03/22/unity-spine-import-slow/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;打包时需要使用两次 &lt;code&gt;BuildPipeline.BuildPlayer&lt;/code&gt; 分别构建不同版本的包，只调用一次则打包时间很正常只有 5 分钟，但是打包两次时间则会膨胀到 30 分钟。&lt;/p&gt;
&lt;p&gt;通过阅读分析 Unity 打包日志，发现在两次 &lt;code&gt;BuildPipeline.BuildPlayer&lt;/code&gt; 中间有大量长时间耗时的操作呢？实际项目中出现了 1300+ 条类似下面的日志，而且耗时达22分钟：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;16:43:08.145856 Unloading 1 Unused Serialized files (Serialized files now loaded: 0)
16:43:09.158184 Unloading 17 unused Assets / (24.7 KB). Loaded Objects now: 38901.
16:43:09.158184 Memory consumption went from 0.72 GB to 0.72 GB.
16:43:09.158184 Total: 960.310500 ms (FindLiveObjects: 2.454500 ms CreateObjectMapping: 3.433300 ms MarkObjects: 954.311900 ms  DeleteObjects: 0.110200 ms)
16:43:09.158184 
16:43:09.158184 Unloading 1 Unused Serialized files (Serialized files now loaded: 0)
16:43:10.170468 Unloading 17 unused Assets / (4.4 KB). Loaded Objects now: 38901.
16:43:10.170468 Memory consumption went from 0.72 GB to 0.72 GB.
16:43:10.170468 Total: 956.463900 ms (FindLiveObjects: 2.442300 ms CreateObjectMapping: 3.146500 ms MarkObjects: 950.779100 ms  DeleteObjects: 0.095300 ms)

...

17:05:10.661445 Unloading 2 Unused Serialized files (Serialized files now loaded: 0)
17:05:11.675348 Unloading 13 unused Assets / (6.2 KB). Loaded Objects now: 40923.
17:05:11.675348 Memory consumption went from 0.71 GB to 0.71 GB.
17:05:11.675348 Total: 891.505800 ms (FindLiveObjects: 2.536600 ms CreateObjectMapping: 3.384700 ms MarkObjects: 885.480900 ms  DeleteObjects: 0.102900 ms)
17:05:11.675348 
17:05:11.675348 Unloading 4 Unused Serialized files (Serialized files now loaded: 0)
17:05:12.688781 Unloading 20 unused Assets / (12.8 KB). Loaded Objects now: 40923.
17:05:12.688781 Memory consumption went from 0.72 GB to 0.72 GB.
17:05:12.688781 Total: 890.204700 ms (FindLiveObjects: 2.589100 ms CreateObjectMapping: 3.347600 ms MarkObjects: 884.123500 ms  DeleteObjects: 0.143700 ms)
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;环境&#34;&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Unity 2022.3.62f1&lt;/li&gt;
&lt;li&gt;Windows 10 22H2&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;问题分析&#34;&gt;问题分析&lt;/h2&gt;
&lt;p&gt;上面的日志是卸载资源，Unity 编辑器下对应的 API 是 &lt;code&gt;EditorUtility.UnloadUnusedAssetsImmediate()&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.unity3d.com/2022.3/Documentation/ScriptReference/EditorUtility.UnloadUnusedAssetsImmediate.html&#34;&gt;Unity - Scripting API: EditorUtility.UnloadUnusedAssetsImmediate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;问题出在 Spine 插件的构建预处理器 &lt;code&gt;SpineBuildProcessor.cs&lt;/code&gt;。它作为 &lt;code&gt;IPreprocessBuildWithReport&lt;/code&gt;（callbackOrder = -2000）在 &lt;code&gt;BuildPipeline.BuildPlayer&lt;/code&gt; 之前执行：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SpineBuildProcessor.cs&lt;/code&gt; Lines 73-93&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span class=&#34;k&#34;&gt;internal&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PreprocessSpinePrefabMeshes&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;BuildUtilities&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IsInSkeletonAssetBuildPreProcessing&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;StartAssetEditing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;prefabsToRestore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Clear&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
        &lt;span class=&#34;kt&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prefabAssets&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FindAssets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;t:Prefab&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;foreach&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;asset&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prefabAssets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;assetPath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;GUIDToAssetPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;asset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;GameObject&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prefabGameObject&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LoadAssetAtPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;GameObject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assetPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SpineEditorUtilities&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CleanupSpinePrefabMesh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prefabGameObject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;prefabsToRestore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assetPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;EditorUtility&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UnloadUnusedAssetsImmediate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;StopAssetEditing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;prefabAssets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SaveAssets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;finally&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;BuildUtilities&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IsInSkeletonAssetBuildPreProcessing&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;同样的问题也出现在 &lt;code&gt;PreprocessSpriteAtlases&lt;/code&gt; 中：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SpineBuildProcessor.cs&lt;/code&gt; Lines 111-131&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span class=&#34;k&#34;&gt;internal&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PreprocessSpriteAtlases&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;BuildUtilities&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IsInSpriteAtlasBuildPreProcessing&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;StartAssetEditing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;spriteAtlasTexturesToRestore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Clear&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
        &lt;span class=&#34;kt&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spriteAtlasAssets&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FindAssets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;t:SpineSpriteAtlasAsset&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;foreach&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;asset&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;spriteAtlasAssets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;assetPath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;GUIDToAssetPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;asset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;SpineSpriteAtlasAsset&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;atlasAsset&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LoadAssetAtPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SpineSpriteAtlasAsset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assetPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;atlasAsset&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;atlasAsset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;materials&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;spriteAtlasTexturesToRestore&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assetPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;GetAssetPath&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;atlasAsset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;materials&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainTexture&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;atlasAsset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;materials&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;mainTexture&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;null&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;EditorUtility&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UnloadUnusedAssetsImmediate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;StopAssetEditing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;spriteAtlasAssets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;AssetDatabase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SaveAssets&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;finally&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;BuildUtilities&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IsInSpriteAtlasBuildPreProcessing&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;问题本质&#34;&gt;问题本质&lt;/h2&gt;
&lt;p&gt;这两个方法的致命问题是：在 &lt;code&gt;foreach&lt;/code&gt; 循环的每次迭代内部调用了 &lt;code&gt;EditorUtility.UnloadUnusedAssetsImmediate()&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;从日志中可以看到：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;指标&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;值&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;每次 &lt;code&gt;MarkObjects&lt;/code&gt; 耗时&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;~950ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;已加载对象数&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;38,901 ~ 40,923&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;每次卸载的资源&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;仅 13~20 个（几 KB）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;循环次数&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;1,300+ 次（= 项目中 Prefab 总数 + SpineSpriteAtlasAsset 数量）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;总耗时&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;1,300 × ~1s ≈ 22 分钟&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;每次调用 &lt;code&gt;UnloadUnusedAssetsImmediate()&lt;/code&gt; 都需要完整遍历内存中所有 38,901+ 个对象来执行 &lt;code&gt;MarkObjects&lt;/code&gt;，但每次只卸载了十几个微小资源（几 KB），内存从 0.72GB 到 0.72GB 几乎没有变化——这完全是无效的重复劳动。&lt;/p&gt;
&lt;h2 id=&#34;修复方案&#34;&gt;修复方案&lt;/h2&gt;
&lt;p&gt;修改文件： &lt;code&gt;Assets/Plugins/Spine/Editor/spine-unity/Editor/Utility/SpineBuildProcessor.cs&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;两处改动： 将 &lt;code&gt;EditorUtility.UnloadUnusedAssetsImmediate()&lt;/code&gt; 从 &lt;code&gt;foreach&lt;/code&gt; 循环内部移到循环结束后（&lt;code&gt;StopAssetEditing&lt;/code&gt; 之后）只调用一次。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&#34;text-align:left&#34;&gt;&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;修改前&lt;/th&gt;
&lt;th style=&#34;text-align:left&#34;&gt;修改后&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;&lt;code&gt;PreprocessSpinePrefabMeshes&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;循环内每个 Prefab 都调用一次&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;循环外只调用一次&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;&lt;code&gt;PreprocessSpriteAtlases&lt;/code&gt;&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;循环内每个 Atlas 都调用一次&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;循环外只调用一次&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&#34;text-align:left&#34;&gt;预估耗时&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;1,300+ 次 × ~1s = 22 分钟&lt;/td&gt;
&lt;td style=&#34;text-align:left&#34;&gt;1 次 × ~1s = 1 秒&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这个修复将这部分构建时间从 22 分钟压缩到约 1 秒。&lt;code&gt;UnloadUnusedAssetsImmediate&lt;/code&gt; 的目的是防止循环中加载大量 Prefab 导致内存溢出，但每次循环只加载一个 Prefab 然后立即卸载是极其低效的做法——在循环结束后统一清理一次就足够了。&lt;/p&gt;
&lt;h2 id=&#34;官方现状&#34;&gt;官方现状&lt;/h2&gt;
&lt;p&gt;截止到 2026-03-22 最新的 Spine 4.2 版本依然存在此问题&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/EsotericSoftware/spine-runtimes/blob/4.2/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineBuildProcessor.cs#L114&#34;&gt;spine-runtimes/spine-unity/Assets/Spine/Editor/spine-unity/Editor/Utility/SpineBuildProcessor.cs at 4.2 · EsotericSoftware/spine-runtimes · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Unity 测量游戏启动时间</title>
      <link>https://networm.me/2026/02/08/unity-startup-profiler/</link>
      <pubDate>Sun, 08 Feb 2026 23:49:58 +0800</pubDate>
      
      <guid>https://networm.me/2026/02/08/unity-startup-profiler/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;测量游戏启动时间，用于性能优化，需要量化这个数值。&lt;/p&gt;
&lt;h2 id=&#34;环境&#34;&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Unity 2022.3.62f1&lt;/li&gt;
&lt;li&gt;Windows 10 22H2&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;启动时间总览&#34;&gt;启动时间总览&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;操作系统加载应用程序&lt;/li&gt;
&lt;li&gt;应用程序进入 main 入口&lt;/li&gt;
&lt;li&gt;Unity 初始化完成&lt;/li&gt;
&lt;li&gt;启动游戏&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;从日志获取启动时间&#34;&gt;从日志获取启动时间&lt;/h2&gt;
&lt;p&gt;可以将 Android Logcat 获取到日志中的绝对时间改成相对时间，以第一条日志为基准。&lt;/p&gt;
&lt;p&gt;使用 Python 3 来编写这个小工具。&lt;code&gt;convert_to_relative_time.py&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;64
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;ch&#34;&gt;#!/usr/bin/env python3&lt;/span&gt;
&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;将 Android Logcat 日志的时间戳转换为相对时间&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;

&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;re&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sys&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;datetime&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;TIMESTAMP_PATTERN&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;re&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;compile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;r&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;^(\d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{4}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;-\d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{2}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;-\d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{2}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt; \d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{2}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;:\d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{2}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;:\d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{2}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;\.\d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{3}&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;) \d+-\d+/\S+ &amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;TIMESTAMP_FORMAT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;%Y-%m-&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%d&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt; %H:%M:%S.&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%f&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;parse_timestamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ts_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;解析时间戳字符串&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;datetime&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;strptime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ts_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TIMESTAMP_FORMAT&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;format_relative_time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;delta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;将时间差格式化为 +HH:MM:SS.mmm 格式&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;total_seconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;delta&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;hours&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;remainder&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;divmod&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;total_seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3600&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;minutes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;seconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;divmod&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;remainder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;milliseconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seconds&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;+&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;hours&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;02d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;minutes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;02d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;02d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;milliseconds&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;03d&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;convert_log_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;output_file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&amp;#34;转换日志文件中的时间戳为相对时间&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;output_file&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;output_file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;input_file&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;rsplit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;-relative.log&amp;#39;&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;first_timestamp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;output_lines&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;r&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;encoding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;match&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TIMESTAMP_PATTERN&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;ts_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;group&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;current_ts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;parse_timestamp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ts_str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

                &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;first_timestamp&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
                    &lt;span class=&#34;n&#34;&gt;first_timestamp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;current_ts&lt;/span&gt;

                &lt;span class=&#34;n&#34;&gt;delta&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;current_ts&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;first_timestamp&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;relative_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format_relative_time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;delta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;relative_str&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;match&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():]&lt;/span&gt;

            &lt;span class=&#34;n&#34;&gt;output_lines&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;open&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;w&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;encoding&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;as&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;writelines&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output_lines&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;转换完成: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output_file&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;output_file&lt;/span&gt;


&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;input_file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;android-logcat.log&amp;#39;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;input_file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;output_file&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;len&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;argv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;convert_log_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;input_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;output_file&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;游戏内测量启动时间&#34;&gt;游戏内测量启动时间&lt;/h2&gt;
&lt;p&gt;使用 DeepSeek 编写：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Unity 中编写一个测量启动时间的脚本，使用 &lt;code&gt;Time.realtimeSinceStartupAsDouble&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;接口为 &lt;code&gt;Mark(step)&lt;/code&gt; &lt;code&gt;PrintSummary&lt;/code&gt; &lt;code&gt;Reset&lt;/code&gt;
所有时间均显示为毫秒整数&lt;/li&gt;
&lt;li&gt;使用单例而不是MonoBehaviour，不用转换为整数而是在显示时格式化为整数&lt;/li&gt;
&lt;li&gt;并不是第一次调用 Mark 才开始计时，所以时间计算不需要减去第一步的时间&lt;/li&gt;
&lt;li&gt;同时输出每一步的占比，耗时与占比需要右对齐，步骤名称列的长度需要是最长步骤名称+4&lt;/li&gt;
&lt;li&gt;同时增加一列相对上一步的耗时，最后增加一行总用时&lt;/li&gt;
&lt;li&gt;占比与增量列交换一下，占比改为相对上一步的占比&lt;/li&gt;
&lt;li&gt;占比改为这一步与上一步之间的用时/总用时&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;结果：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;31
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;32
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;33
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;34
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;35
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;36
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;37
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;38
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;39
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;40
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;41
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;42
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;43
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;44
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;45
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;46
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;47
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;48
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;49
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;50
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;51
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;52
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;53
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;54
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;55
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;56
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;57
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;58
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;59
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;60
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;61
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;62
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;63
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;64
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;65
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;66
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;67
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;68
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;69
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;70
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;71
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;72
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;73
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;74
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;75
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;76
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;77
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;78
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;79
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;80
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;81
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;82
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;83
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;84
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;85
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;86
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;87
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;88
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;89
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;90
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;91
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;92
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;93
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;94
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;95
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;96
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;97
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;98
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-csharp&#34; data-lang=&#34;csharp&#34;&gt;&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;System.Collections.Generic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;System.Linq&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;using&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;UnityEngine&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;StartupTimer&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;readonly&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StartupTimer&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;instance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StartupTimer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;instance&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StartupTimer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StartupTimer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Step&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;();&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StartupTimer&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Instance&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;instance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Step&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;double&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// 秒（从启动开始）
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Step&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Mark&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;step&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Step&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;step&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;time&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;realtimeSinceStartupAsDouble&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PrintSummary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Count&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;Debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;没有记录任何步骤，无法生成总结。&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

        &lt;span class=&#34;kt&#34;&gt;double&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;totalSeconds&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[^&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// 最后一个步骤的绝对时间即为总耗时
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;totalMs&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Math&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Round&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;totalSeconds&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MidpointRounding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AwayFromZero&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

        &lt;span class=&#34;n&#34;&gt;Debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;$&amp;#34;=== 启动时间总结 ===&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;Debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;$&amp;#34;总启动耗时: {totalMs} ms\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

        &lt;span class=&#34;c1&#34;&gt;// 计算最大名称长度（考虑步骤名、表头“步骤名称”和汇总行“总用时”）
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;maxNameLength&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
        &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nameWidth&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Math&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;maxNameLength&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;步骤名称&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;nameWidth&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Math&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Max&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;nameWidth&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;总用时&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

        &lt;span class=&#34;c1&#34;&gt;// 准备数据列表
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timeMs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deltaMs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ratioStr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&amp;gt;();&lt;/span&gt;
        &lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prevTimeMs&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;++)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timeMs&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Math&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Round&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MidpointRounding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AwayFromZero&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deltaMs&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timeMs&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;prevTimeMs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

            &lt;span class=&#34;c1&#34;&gt;// 占比 = 增量 / 总耗时 * 100%
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;            &lt;span class=&#34;kt&#34;&gt;double&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ratio&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;totalMs&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;?&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;deltaMs&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;double&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;totalMs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;100.0&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
            &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ratioStr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ratio&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ToString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;F1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;%&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;

            &lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timeMs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deltaMs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ratioStr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;prevTimeMs&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;timeMs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

        &lt;span class=&#34;c1&#34;&gt;// 表头
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;header&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$&amp;#34;{&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;步骤名称&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;,-nameWidth} {&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;耗时&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ms&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;,8} {&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;增量&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ms&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;,8} {&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;占比&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;,6}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;Debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

        &lt;span class=&#34;c1&#34;&gt;// 输出每一行
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;k&#34;&gt;foreach&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;row&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;rows&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;line&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$&amp;#34;{row.name,-nameWidth} {row.timeMs,8} {row.deltaMs,8} {row.ratioStr,6}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;Debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;line&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

        &lt;span class=&#34;c1&#34;&gt;// 汇总行（总用时）
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;n&#34;&gt;Debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sc&#34;&gt;&amp;#39;-&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;header&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// 分隔线
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;totalLine&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;$&amp;#34;{&amp;#34;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;总用时&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;,-nameWidth} {totalMs,8} {&amp;#34;&amp;#34;,8} {&amp;#34;&amp;#34;,6}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;Debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;totalLine&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;

        &lt;span class=&#34;c1&#34;&gt;// 步骤间耗时明细（可选）
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Count&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;Debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;\n--- 步骤间耗时明细 ---&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Count&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;++)&lt;/span&gt;
            &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
                &lt;span class=&#34;kt&#34;&gt;double&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;elapsedSeconds&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;time&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;Debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;$&amp;#34;{steps[i - 1].name} → {steps[i].name}: {FormatMilliseconds(elapsedSeconds)} ms&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Reset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;steps&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Clear&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FormatMilliseconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;double&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;seconds&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
        &lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ms&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;long&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Math&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Round&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;seconds&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;1000.0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MidpointRounding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AwayFromZero&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ms&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ToString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;// 静态便捷方法
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Mark&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;step&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Instance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Mark&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;step&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PrintSummary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Instance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PrintSummary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Reset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Instance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Reset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;=== 启动时间总结 ===
总启动耗时: 300 ms

步骤名称                耗时(ms) 增量(ms)    占比
Awake                        50        0    0.0%
Start                       150      100   33.3%
ResourcesLoaded             300      150   50.0%
-----------------------------------------------
总用时                      300                  
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
    </item>
    
    <item>
      <title>软件推荐：DouK-Downloader</title>
      <link>https://networm.me/2026/02/01/douk-downloader/</link>
      <pubDate>Sun, 01 Feb 2026 23:50:13 +0800</pubDate>
      
      <guid>https://networm.me/2026/02/01/douk-downloader/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;DouK-Downloader 是一款用于下载抖音 / TikTok 视频的工具。&lt;/p&gt;
&lt;h2 id=&#34;环境&#34;&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Windows 11 23H2&lt;/li&gt;
&lt;li&gt;DouK-Downloader V5.7&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;下载&#34;&gt;下载&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/JoeanAmier/TikTokDownloader&#34;&gt;GitHub - JoeanAmier/TikTokDownloader: TikTok 发布/喜欢/合辑/直播/视频/图集/音乐；抖音发布/喜欢/收藏/收藏夹/视频/图集/实况/直播/音乐/合集/评论/账号/搜索/热榜数据采集工具/下载工具&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;演示&#34;&gt;演示&lt;/h2&gt;
&lt;p&gt;强烈建议通过视频快速了解使用方法。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.bilibili.com/video/BV1d7eAzTEFs/&#34;&gt;前往 bilibili 观看演示&lt;/a&gt;；&lt;a href=&#34;https://youtu.be/yMU-RWl55hg&#34;&gt;前往 YouTube 观看演示&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;使用&#34;&gt;使用&lt;/h2&gt;
&lt;p&gt;整个工具是一款基于命令行的 TUI 工具，实际使用起来并不比 GUI 的工具差，并且由于减少了 GUI 导致使用起来非常简单。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://en.wikipedia.org/wiki/Text-based_user_interface&#34;&gt;Text-based user interface - Wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;配置-cookie&#34;&gt;配置 Cookie&lt;/h3&gt;
&lt;p&gt;建议使用自己账号的 Cookie，方便下载到高清的视频。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/JoeanAmier/TikTokDownloader/blob/master/docs/Cookie%E8%8E%B7%E5%8F%96%E6%95%99%E7%A8%8B.md&#34;&gt;TikTokDownloader/docs/Cookie获取教程.md at master · JoeanAmier/TikTokDownloader · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;视频&#34;&gt;视频&lt;/h3&gt;
&lt;p&gt;可以方便地下载分享链接中的视频，如果通过其他方式保存下来的分享链接，可以批量下载。&lt;/p&gt;
&lt;h3 id=&#34;用户&#34;&gt;用户&lt;/h3&gt;
&lt;p&gt;可以通过修改 &lt;code&gt;_internal/Volume/settings.json&lt;/code&gt; 增加用户信息，后续可以定时批量下载用户发布的视频。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>软件推荐：SourceGit 客户端</title>
      <link>https://networm.me/2025/12/14/sourcegit/</link>
      <pubDate>Sun, 14 Dec 2025 23:47:30 +0800</pubDate>
      
      <guid>https://networm.me/2025/12/14/sourcegit/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;SourceGit 是一款跨平台、开源的 Git GUI 客户端，支持 Windows、macOS、Linux。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://sourcegit-scm.github.io/&#34;&gt;SourceGit - Opensource &amp;amp; Free Git Gui Client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;环境&#34;&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Windows 22H2&lt;/li&gt;
&lt;li&gt;SourceGit 2025.39&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;下载安装&#34;&gt;下载安装&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sourcegit-scm/sourcegit/releases&#34;&gt;Releases · sourcegit-scm/sourcegit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;将压缩包的内容直接解压到 &lt;code&gt;%LOCALAPPDATA%\Programs&lt;/code&gt; 中，推荐使用 &lt;a href=&#34;https://networm.me/2020/12/20/bandizip/&#34;&gt;软件推荐：Bandizip - 狂飙&lt;/a&gt; 解压。&lt;/p&gt;
&lt;h2 id=&#34;使用&#34;&gt;使用&lt;/h2&gt;
&lt;p&gt;进入后可以切换为中文界面。&lt;/p&gt;
&lt;h2 id=&#34;与-fork-比较&#34;&gt;与 Fork 比较&lt;/h2&gt;
&lt;h3 id=&#34;优点&#34;&gt;优点&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;开源&lt;/li&gt;
&lt;li&gt;跨平台&lt;/li&gt;
&lt;li&gt;完全使用 C# 进行开发&lt;/li&gt;
&lt;li&gt;界面与功能都非常像 Fork&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;缺点&#34;&gt;缺点&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;缺少 &lt;code&gt;Lean Branching&lt;/code&gt; &lt;a href=&#34;https://github.com/fork-dev/TrackerWin/issues/1432&#34;&gt;⭐️ Lean Branching - a git branching model to keep clean history · Issue #1432 · fork-dev/TrackerWin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;缺少 pull &amp;ndash;rebase 前后的自动 stash push 与 stash pop 操作&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;虽然现阶段功能没有 Fork 那么全，例如，但由于软件是开源的，相信未来这些功能都会有。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://networm.me/2020/03/29/git-fork/&#34;&gt;软件推荐：Git 客户端 Fork - 狂飙&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;建议将其作为备选，等待其成熟后引入到团队中使用。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Unity 6.3 正式发布</title>
      <link>https://networm.me/2025/12/07/unity-6.3-released/</link>
      <pubDate>Sun, 07 Dec 2025 23:55:49 +0800</pubDate>
      
      <guid>https://networm.me/2025/12/07/unity-6.3-released/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;Unity 6.3 LTS 正式发布：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://unity.com/blog/unity-6-3-lts-is-now-available&#34;&gt;Unity 6.3 LTS is Now Available | Unity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://unity.com/cn/blog/unity-6-3-lts-is-now-available&#34;&gt;Unity 6.3 LTS 现已发布 | Unity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;lts-周期&#34;&gt;LTS 周期&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;只有刚刚开始的新项目推荐使用 Unity 6.3 LTS。&lt;/li&gt;
&lt;li&gt;旧项目需要升级 Unity 版本则推荐 Unity 6 LTS，经过一年多的维护，Unity 6 LTS 基本上没有什么大 Bug 了。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;亮点&#34;&gt;亮点&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Platform Toolkit&lt;/strong&gt; 提供&lt;strong&gt;统一API&lt;/strong&gt;，简化跨平台功能（如账户、存档、成就）开发。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AssetBundle 的 TypeTree去重&lt;/strong&gt;：为部分游戏减少&lt;strong&gt;97%以上&lt;/strong&gt;的运行时内存占用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;稳定性提升&lt;/strong&gt;：回归问题减少30%，用户报告问题减少22%，积压问题处于三年最低水平。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;精灵图集分析器&lt;/strong&gt;：新工具，用于识别图集使用低效问题。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UI系统&lt;/strong&gt;：UGUI持续改进；UI Toolkit新增可定制着色器、SVG支持。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP/2支持&lt;/strong&gt;：在UnityWebRequest中默认启用，可降低服务器与设备负载（安卓测试显示服务器负载降低约40%）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unity Core Standards&lt;/strong&gt;：引入经过验证和签名的资源包认证体系，提高第三方工具可靠性。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;总结&#34;&gt;总结&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Unity 6.3 LTS&lt;/strong&gt; 是一个以&lt;strong&gt;稳定支持、卓越性能和生产就绪&lt;/strong&gt;为核心的版本。它通过&lt;strong&gt;统一的跨平台工具链、经过大型游戏验证的显著性能提升、以及对现代图形和工作流的强大支持&lt;/strong&gt;，旨在让开发团队能够更高效、更自信地开发和运营项目。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Unity 2019 无法删除长路径文件</title>
      <link>https://networm.me/2025/11/30/unity-2019-long-path-support/</link>
      <pubDate>Sun, 30 Nov 2025 23:30:57 +0800</pubDate>
      
      <guid>https://networm.me/2025/11/30/unity-2019-long-path-support/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;在执行 &lt;code&gt;Directory.Delete&lt;/code&gt; 删除目录时，目录内部存在过深的子目录而完整路径超过 260 个字符，删除就会出现异常。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-fallback&#34; data-lang=&#34;fallback&#34;&gt;DirectoryNotFoundException: Could not find a part of the path &amp;#34;C:\Project\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\Output\GradleProject\launcher\build\intermediates\desugar_graph\release\dexBuilderRelease\out\currentProject\jar_8644da973e7b1e319711ad5b4fbc94027d2acce4dda8b1bd6d51994cb312313d_bucket_0\graph.bin&amp;#34;
  at System.IO.File.Delete (System.String path) [0x00073] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.RecursiveDelete (System.String path) [0x0003f] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.RecursiveDelete (System.String path) [0x00024] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.RecursiveDelete (System.String path) [0x00024] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.RecursiveDelete (System.String path) [0x00024] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.RecursiveDelete (System.String path) [0x00024] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.RecursiveDelete (System.String path) [0x00024] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.RecursiveDelete (System.String path) [0x00024] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.RecursiveDelete (System.String path) [0x00024] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.RecursiveDelete (System.String path) [0x00024] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.RecursiveDelete (System.String path) [0x00024] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at System.IO.Directory.Delete (System.String path, System.Boolean recursive) [0x00009] in &amp;lt;eae584ce26bc40229c1b1aa476bfa589&amp;gt;:0
  at Build.Export () [0x0008d] in C:\Project\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\Build.cs:291
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;环境&#34;&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Windows 10 21H2&lt;/li&gt;
&lt;li&gt;Unity 2019.4.41f1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;分析&#34;&gt;分析&lt;/h2&gt;
&lt;p&gt;虽然传入的路径没有那么长，但是在 &lt;code&gt;Directory.Delete&lt;/code&gt; 内部会使用递归删除子目录与子文件，导致路径超过 260 个字符限制。&lt;/p&gt;
&lt;p&gt;Windows 启用长路径支持无效，使用 &lt;code&gt;\?\&lt;/code&gt; 前缀无效&lt;/p&gt;
&lt;p&gt;- &lt;a href=&#34;https://learn.microsoft.com/zh-cn/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN&#34;&gt;文件命名、路径和命名空间 - Win32 apps | Microsoft Learn&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;本质原因是因为路径过长，Unity 内置 mono 系统库版本过老，无法删除长路径。&lt;/p&gt;
&lt;p&gt;- &lt;a href=&#34;https://github.com/mono/mono/blob/main/mcs/class/referencesource/mscorlib/system/io/directory.cs#L1294&#34;&gt;mono/mcs/class/referencesource/mscorlib/system/io/directory.cs at main · mono/mono · GitHub&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;方案&#34;&gt;方案&lt;/h2&gt;
&lt;h3 id=&#34;unity-2019&#34;&gt;Unity 2019&lt;/h3&gt;
&lt;p&gt;推荐使用外部工具删除目录，例如 &lt;code&gt;rmdir&lt;/code&gt; 命令。&lt;/p&gt;
&lt;h3 id=&#34;unity-升级&#34;&gt;Unity 升级&lt;/h3&gt;
&lt;p&gt;实测 Unity 2022.3.62f1 没有这个问题，相同环境下相同代码可以正常删除。&lt;/p&gt;
&lt;p&gt;推荐旧项目尽可能升级到最新的 LTS 版本。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>.NET 10 LTS 正式发布</title>
      <link>https://networm.me/2024/11/16/dotnet-10-released/</link>
      <pubDate>Sun, 16 Nov 2025 23:53:02 +0800</pubDate>
      
      <guid>https://networm.me/2024/11/16/dotnet-10-released/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;.NET 10 LTS 正式发布&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://dotnet.microsoft.com/en-us/download/dotnet/10.0&#34;&gt;Download .NET 10.0 (Linux, macOS, and Windows) | .NET&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;长期支持&#34;&gt;长期支持&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;.NET 10 是 &lt;a href=&#34;https://learn.microsoft.com/zh-cn/dotnet/core/whats-new/dotnet-9/overview&#34;&gt;.NET 9&lt;/a&gt; 的继任者，作为长期支持 （LTS） 版本， &lt;a href=&#34;https://dotnet.microsoft.com/platform/support/policy/dotnet-core&#34;&gt;支持三年&lt;/a&gt; 。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://learn.microsoft.com/zh-cn/dotnet/core/whats-new/dotnet-10/overview?WT.mc_id=dotnet-35129-website&#34;&gt;.NET 10 中的新增功能 | Microsoft Learn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;c-14&#34;&gt;C# 14&lt;/h2&gt;
&lt;p&gt;C# 14 引入了多项新功能和增强功能，以提高开发人员的工作效率和代码质量。 关键更新包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;基于字段的属性为从自动实现属性到编写自定义 &lt;code&gt;get&lt;/code&gt; 和 &lt;code&gt;set&lt;/code&gt; 访问器提供了一条更流畅的路径。 可以使用上下文关键字访问编译器生成的后盾字段 &lt;code&gt;field&lt;/code&gt; 。&lt;/li&gt;
&lt;li&gt;表达式 &lt;code&gt;nameof&lt;/code&gt; 现在支持未绑定的泛型类型，例如 &lt;code&gt;List&amp;lt;&amp;gt;&lt;/code&gt;，它返回类型的名称而无需类型参数。&lt;/li&gt;
&lt;li&gt;对 &lt;code&gt;Span&amp;lt;T&amp;gt;&lt;/code&gt; 和 &lt;code&gt;ReadOnlySpan&amp;lt;T&amp;gt;&lt;/code&gt; 的隐式转换提供一流支持。&lt;/li&gt;
&lt;li&gt;参数修饰符（例如 &lt;code&gt;ref&lt;/code&gt;、&lt;code&gt;in&lt;/code&gt; 或 &lt;code&gt;out&lt;/code&gt;）在 lambda 表达式中允许使用，并且无需指定参数类型。&lt;/li&gt;
&lt;li&gt;支持部分实例构造函数和部分事件，补充 C# 13 中引入的部分方法和属性。&lt;/li&gt;
&lt;li&gt;新 &lt;code&gt;extension&lt;/code&gt; 块添加了对静态扩展方法的支持，以及静态和实例扩展属性。&lt;/li&gt;
&lt;li&gt;使用 &lt;code&gt;?.&lt;/code&gt; 运算符的 Null 条件赋值。&lt;/li&gt;
&lt;li&gt;用户定义的复合赋值运算符，如 &lt;code&gt;+=&lt;/code&gt; 和 &lt;code&gt;-=&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;用户定义的增量 （&lt;code&gt;++&lt;/code&gt;） 和递减 （&lt;code&gt;--&lt;/code&gt;） 运算符。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;有关详细信息，请参阅 &lt;a href=&#34;https://learn.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-14&#34;&gt;C# 14 中的新增&lt;/a&gt;功能。&lt;/p&gt;
&lt;h2 id=&#34;rider&#34;&gt;Rider&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Rider 2025.3 可以对 .NET 10 提供发布当日支持，包括 C# 14 中的扩展成员、扩展运算符和用户自定义复合赋值运算符等功能，同时通过更新确保与最新编译器更改保持一致。 此版本还带来了对 Unity、Unreal Engine 和 Godot 游戏开发的扩展支持，将 Islands 主题设为 JetBrains IDE 的全新默认外观，并提升了解决方案启动的性能。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.jetbrains.com/zh-cn/rider/whatsnew/2025-3/&#34;&gt;Rider 最新变化&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;下载&#34;&gt;下载&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.jetbrains.com/zh-cn/rider/download/other.html&#34;&gt;其他版本 - Rider&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>Windows 迁移到另一块硬盘</title>
      <link>https://networm.me/2025/10/26/windows-migration-disk/</link>
      <pubDate>Sun, 26 Oct 2025 23:08:45 +0800</pubDate>
      
      <guid>https://networm.me/2025/10/26/windows-migration-disk/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;p&gt;系统盘满了不想要重装，需要将系统迁移到大的硬盘上。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;DiskGenius软件，提供了系统迁移功能，使用DiskGenius,可以方便的把系统迁移到SSD固态硬盘，或其他存储设备中去，免去了重新安装系统、驱动、软件及复制数据等工作，非常方便！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.diskgenius.cn/exp/system-migration.php&#34;&gt;迁移Windows系统到ssd固态硬盘或其他硬盘，DiskGenius特色功能介绍&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;环境&#34;&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Windows 10 22H2&lt;/li&gt;
&lt;li&gt;DiskGenius V5.6.0.1565 x64&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;操作过程&#34;&gt;操作过程&lt;/h2&gt;
&lt;p&gt;如果要迁移到的硬盘上还有数据，需要提前将其转移到其他硬盘。&lt;/p&gt;
&lt;p&gt;推荐将所有数据拷贝到另一个硬盘中，然后格式化，因为剪切会在拷贝完成后删除原有文件，而直接拷贝没有删除的话则无需处理可能存在的文件占用、符号链接等导致无法删除的问题。&lt;/p&gt;
&lt;p&gt;另外可以在晚上拷贝，第二天格式化，一晚上的时间足够拷贝所有文件。&lt;/p&gt;
&lt;h2 id=&#34;迁移&#34;&gt;迁移&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;另外，如果用户的电脑比较新，支持UEFI启动，那么在系统迁移窗口中，可以直接指定系统迁移完成后，需要不需要更改启动项，是否需要从迁移后的目标硬盘中的系统启动。省去了用户自己在Bios中手工更改启动项的步骤&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;按照文档操作即可，注意可以勾选修改启动盘符。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;最新版本的DiskGenius，对硬盘的备份还原等操作，做了大幅度的优化，极大的提升了相关操作的速度。得益于此，DiskGenius系统迁移的速度非常快，根据笔者的测试，一般的Windows 系统，包括Win10、Win8、Win7等，数据量不大的情况下，系统迁移的时间不超过10分钟，选择热迁移模式，还不影响电脑的正常使用！&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;实测有效，256G 固态硬盘 18分钟完成迁移。&lt;/p&gt;
&lt;h2 id=&#34;注意事项&#34;&gt;注意事项&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;虽然 DiskGenius 推荐使用热迁移模式，但是为了数据安全建议使用重启到WinPE模式。&lt;/li&gt;
&lt;li&gt;迁移系统后，推荐在管理中直接删除原系统的盘符，保留原系统硬盘一段时间，防止有任何问题可以及时回退。&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Unity CVE-2025-59489 漏洞</title>
      <link>https://networm.me/2025/10/19/unity-cve-upgrade/</link>
      <pubDate>Sun, 19 Oct 2025 23:57:01 +0800</pubDate>
      
      <guid>https://networm.me/2025/10/19/unity-cve-upgrade/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;An important message&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A security vulnerability was identified that affects games and applications built on Unity versions 2017.1 and later for Android, Windows, Linux, and macOS operating systems. There is no evidence of any exploitation of the vulnerability, nor has there been any impact on users or customers. We have proactively provided fixes that address the vulnerability, and they are already available to all developers. The vulnerability was responsibly reported by the security researcher RyotaK, and we thank him for working with us.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Games and applications already built:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We strongly recommend you download the patched update for your version of the Unity Editor, recompile, and republish your application.&lt;/li&gt;
&lt;li&gt;We have provided a tool to patch already-built applications dating back to 2017.1 for Android, Windows, and macOS for developers who prefer not to rebuild their projects. The tool can be accessed &lt;a href=&#34;http://unity.com/security/sept-2025-01/remediation&#34;&gt;here.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://discussions.unity.com/t/unity-platform-protection-take-immediate-action-to-protect-your-games-and-apps/1688031&#34;&gt;Unity Platform Protection: Take Immediate Action to Protect Your Games and Apps - CVE Q&amp;amp;A - Unity Discussions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;简单说就是 Unity CVE-2025-59489 漏洞影响了从 Unity 2017.1 到现在的所有版本，因此需要重新构建所有已发布的游戏才可以修复漏洞。&lt;/p&gt;
&lt;p&gt;推荐通过以下官方说明页面详细了解具体问题及对应方案：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://unity.com/cn/security/sept-2025-01/remediation&#34;&gt;Unity Security Vulnerability:Developer Remediation Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;环境&#34;&gt;环境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Windows 10 22H2&lt;/li&gt;
&lt;li&gt;Unity 2019.4.41f1&lt;/li&gt;
&lt;li&gt;Unity 2022.3.62f1&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;代理服务器&#34;&gt;代理服务器&lt;/h2&gt;
&lt;p&gt;截止到 2025-10-19，由于 Unity 中国强制下载链接跳转到特供版，因此必须使用美国代理服务器才能下载。&lt;/p&gt;
&lt;p&gt;以下所有方法的前提是配置好这个美国代理服务器。&lt;/p&gt;
&lt;h2 id=&#34;在线安装-unity&#34;&gt;在线安装 Unity&lt;/h2&gt;
&lt;h3 id=&#34;在线安装优点&#34;&gt;在线安装优点&lt;/h3&gt;
&lt;p&gt;Unity 虽然在每个版本的页面中都提供了相关的组件下载，但是相对于 Unity Hub 在线安装，缺少了关键的 Android SDK、NDK、JDK。&lt;/p&gt;
&lt;p&gt;由于不同 Unity 版本使用了不同的Android SDK、NDK、JDK，想要自己处理太过于麻烦。&lt;/p&gt;
&lt;p&gt;Unity Hub 内部存储有每个版本对应的 Android SDK、NDK、JDK 版本下载地址并且会自动安装，使用起来极为方便。&lt;/p&gt;
&lt;h3 id=&#34;代理-unity-hub&#34;&gt;代理 Unity Hub&lt;/h3&gt;
&lt;h3 id=&#34;代理模式&#34;&gt;代理模式&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.unity3d.com/cn/2019.4/Manual/upm-network.html&#34;&gt;网络问题 - Unity 2019.4 - Unity 手册&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;使用 CMD 运行以下命令，设置代理服务器启动 Unity Hub。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bat&#34; data-lang=&#34;bat&#34;&gt;&lt;span class=&#34;k&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;HTTP_PROXY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;http://127.0.0.1:7897
&lt;span class=&#34;k&#34;&gt;set&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;http://127.0.0.1:7897
&lt;span class=&#34;k&#34;&gt;start&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Unity Hub\Unity Hub.exe&amp;#34;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;代理服务器在其他机器上时可以修改上面的 IP 部分。&lt;/p&gt;
&lt;h3 id=&#34;tun-模式&#34;&gt;TUN 模式&lt;/h3&gt;
&lt;p&gt;直接打开代理软件的 TUN 模式，然后运行 Unity Hub。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.logiconsole.com/fuck-unity-cn/&#34;&gt;如何逃离Unity中国特供版 | Logiconsole&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;代理-unity-版本下载页面&#34;&gt;代理 Unity 版本下载页面&lt;/h3&gt;
&lt;p&gt;使用美国服务器代理打开下载页面链接，不然页面会自动跳转到 Unity 中国。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://unity.com/releases/editor/archive&#34;&gt;Download Archive - Unity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;点击 &lt;code&gt;Install&lt;/code&gt; 按钮通过 &lt;code&gt;unityhub://&lt;/code&gt; 协议链接进行安装，稍等片刻后 Unity Hub 就会弹出对应的组件选择页面。&lt;/p&gt;
&lt;p&gt;在网络不好的情况下，安装时推荐优先编辑器，这样不会因为网络中断导致整个安装全部失败，然后再通过 &lt;code&gt;Add Modules&lt;/code&gt; 方式顺序安装其他所有需要的组件。&lt;/p&gt;
&lt;h3 id=&#34;实测&#34;&gt;实测&lt;/h3&gt;
&lt;p&gt;通过在线安装了 Unity 2019.4.41f1 与 Unity 2022.3.62f2，可以正常使用。&lt;/p&gt;
&lt;h2 id=&#34;离线安装-unity&#34;&gt;离线安装 Unity&lt;/h2&gt;
&lt;p&gt;我认为最好的方式是在一台可以在线安装的机器上安装好 Unity，然后将整个 Unity 安装目录打包拷贝到需要的机器上。&lt;/p&gt;
&lt;p&gt;如果担心 Unity 安装程序安装了对应的运行时库，那么可以下载 Unity 编辑器的安装包先安装一次，然后再将整个 Unity 安装目录拷贝并覆盖现有的 Unity 安装目录。&lt;/p&gt;
&lt;h3 id=&#34;组件下载方法&#34;&gt;组件下载方法&lt;/h3&gt;
&lt;p&gt;Chrome 默认不支持断点续传，由于文件过大可能在下载过程中经常中断，因此推荐使用支持断点自动续传的 FDM 下载，设置为手动使用代理，确保下载到的链接域名是 unity3d.com，否则就会下载到 unity3d.cn 中国特供版。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.freedownloadmanager.org/zh/&#34;&gt;Free Download Manager - 從網路下載任何東西&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;FDM 本身有数字签名，而且支持只为当前用户安装，安装过程不需要管理员权限，有中文界面、跨平台支持 Windows macOS Linux。&lt;/p&gt;
&lt;h2 id=&#34;补丁方法&#34;&gt;补丁方法&lt;/h2&gt;
&lt;p&gt;由于需要在已发布的程序上打补丁，因此比较麻烦，只建议手动处理。&lt;/p&gt;
&lt;p&gt;如果项目支持自动打包，建议升级 Unity，而不是增加一步打补丁的步骤。由于打补丁需要替换文件后重新签名，所以比较消耗时间。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://discussions.unity.com/t/cve-2025-59489-patcher-tool/1688032&#34;&gt;CVE-2025-59489 Patcher Tool - CVE Q&amp;amp;A - Unity Discussions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;android-sdk-buildtools-问题&#34;&gt;Android SDK buildtools 问题&lt;/h2&gt;
&lt;p&gt;使用 Unity 2019.4.41f1 手动打包 Android 时会弹出提示：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Detected outdated SDK Build Tools version 28.0.3 when the min version is 29.0.2
UnityException: SDK Build Tools version 28.0.3 &amp;lt; 29.0.2.
Note: when building with Gradle, &amp;ldquo;Use Highest Installed&amp;rdquo; option will update SDK Build Tools as well.&lt;/p&gt;
&lt;p&gt;Update Android SDK
Use Highest Installed
Cancel&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在这个弹窗处如果点击了 &lt;code&gt;Update Android SDK&lt;/code&gt; 或 &lt;code&gt;Use Highest Installed&lt;/code&gt; 按钮，Unity 会记住这个行为，不会在后续的命令行运行中提示以下错误。&lt;/p&gt;
&lt;p&gt;使用命令行打包时会提示：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Detected outdated SDK Build Tools version 28.0.3 when the min version is 29.0.2
UnauthorizedAccessException: Access to the path &amp;ldquo;C:/Program Files/Unity/Hub/Editor/2019.4.41f1/Editor/Data/PlaybackEngines/AndroidPlayer\SDK\tempToolsDir&amp;rdquo; is denied.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;使用管理员运行 Android Studio，在 Settings 中 SDK 页面：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;首先切换 SDK 目录到 &lt;code&gt;C:/Program Files/Unity/Hub/Editor/2019.4.41f1/Editor/Data/PlaybackEngines/AndroidPlayer\SDK\&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;切换完成后返回 SDK 页面，手动选择 BuildTools 29.0.2 安装，必须是这个版本，即使有更高的版本 Unity 运行时只会检查这个版本。&lt;/li&gt;
&lt;li&gt;Unity 命令行运行打包。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果不安装这个版本，只能手动打一次 Android 包，在弹出前面的提示时点击 &lt;code&gt;Update Android SDK&lt;/code&gt; 或 &lt;code&gt;Use Highest Installed&lt;/code&gt; 按钮，后续就不会有问题了。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>软件推荐：重复文件查找 DoubleKiller</title>
      <link>https://networm.me/2025/09/14/double-killer/</link>
      <pubDate>Sun, 14 Sep 2025 23:08:45 +0800</pubDate>
      
      <guid>https://networm.me/2025/09/14/double-killer/</guid>
      <description>&lt;h2 id=&#34;介绍&#34;&gt;介绍&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;DoubleKiller&lt;/strong&gt; 是一款针对个人用户免费使用，在 Windows 上查找并删除重复文件的小工具。基于文件名、尺寸、日期、CRC32 校验四种方式相互结合完成重复文件的查找与删除。@&lt;a href=&#34;https://www.appinn.com/doublekiller-2/&#34;&gt;Appinn&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.bigbangenterprises.de/en/doublekiller/&#34;&gt;DoubleKiller - find and remove duplicate files (Big Bang enterprises)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://zhuanlan.zhihu.com/p/5859823817&#34;&gt;电脑软件：推荐一款非常好用的文件重复清理工具DoubleKiller（附下载） - 知乎&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;功能&#34;&gt;功能&lt;/h2&gt;
&lt;p&gt;默认是基于大小与 CRC32 条件判断文件是否相同，可以根据需要修改条件组合。&lt;/p&gt;
&lt;p&gt;扫描完成后支持复制结果。&lt;/p&gt;
&lt;h2 id=&#34;结合-ai-使用&#34;&gt;结合 AI 使用&lt;/h2&gt;
&lt;p&gt;推荐使用 &lt;a href=&#34;https://www.deepseek.com/&#34;&gt;DeepSeek | 深度求索&lt;/a&gt; 等 AI 工具帮忙编写代码，例如可以将一小部分结果直接给 AI，然后描述如何处理重复文件。&lt;/p&gt;
&lt;p&gt;尝试过删除 Unity 项目中的重复资源，将所有重复资源的引用修改为第一个资源，AI 给出的 C# 代码可以正常使用。&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
