[{"data":1,"prerenderedAt":1061},["ShallowReactive",2],{"knowledge:ja:\u002Fknowledge\u002Fgame\u002Funity\u002Fecs-windows-player-performance-baseline":3,"knowledge-locales:\u002Fknowledge\u002Fgame\u002Funity\u002Fecs-windows-player-performance-baseline":1059},{"id":4,"title":5,"appliesTo":6,"body":10,"description":1044,"extension":1045,"meta":1046,"navigation":342,"path":1047,"publishedAt":1048,"seo":1049,"status":1050,"stem":1051,"tags":1052,"technologies":1057,"updatedAt":1048,"__hash__":1058},"knowledge_ja\u002Fknowledge\u002Fgame\u002Funity\u002Fecs-windows-player-performance-baseline.md","Unity 6のWindows PlayerでECS 1,000〜5,000体を再現可能に計測する",[7,8,9],"Unity Editor 6000.5.1f1","Entities 6.5.0","Windows 11",{"type":11,"value":12,"toc":1030},"minimark",[13,17,21,24,27,40,43,83,94,97,100,114,117,120,124,135,138,141,144,272,275,278,281,284,306,320,482,493,504,508,515,562,573,576,686,692,695,699,702,821,824,827,853,856,860,867,885,888,926,929,932,935,955,958,961,981,984,1026],[14,15,16],"h2",{"id":16},"概要",[18,19,20],"p",{},"ECSで多数のEntityを表示できても、Entity数を増やしたときにCPUとGPUのどちらが先に影響を受けるかは、同じ条件で測らなければ判断できません。",[18,22,23],{},"この記事では、単純な移動と描画だけを行うUnity ECSのプロトタイプを、Windows Standalone x64 Development Playerとして実行し、1,000〜5,000体を1,000体刻みで各3回、合計15回計測した方法をまとめます。",[18,25,26],{},"重要なのは特定環境のFPSそのものではなく、次の3点です。",[28,29,30,34,37],"ul",{},[31,32,33],"li",{},"実行条件を固定し、変更前後を比較できるようにする。",[31,35,36],{},"生のProfilerデータを長時間保存せず、段階比較に必要な高レベル指標だけを集める。",[31,38,39],{},"現在最も長い処理と、Entity数の増加に最も敏感な処理を分けて考える。",[14,41,42],{"id":42},"結論",[28,44,45,48,60,70,73,76],{},[31,46,47],{},"1,000体から5,000体へ増やすと、取得フレーム数から算出した参考FPSは約13%低下しました。",[31,49,50,51,55,56,59],{},"CPU Main Threadの3回平均は",[52,53,54],"code",{},"0.726 ms","から",[52,57,58],{},"0.753 ms","で、Entity数に対する増加は小さい結果でした。",[31,61,62,63,55,66,69],{},"GPU Frameの3回平均は",[52,64,65],{},"0.310 ms",[52,67,68],{},"0.464 ms","へ約50%増え、体数増加に対して最も一貫した変化を示しました。",[31,71,72],{},"絶対時間ではCPU Main ThreadがGPU Frameより長い一方、追加Entityへの感度はGPU側が高いと読めます。",[31,74,75],{},"5,000体の段階では先回りの最適化をせず、次の処理を加えた後に同じ条件で再計測する判断にしました。",[31,77,78,79,82],{},"起動直後からの生Profiler captureは約4.59 GBまで膨らみ、バッファ上限へ達したため、",[52,80,81],{},"FrameTimingManager","とUnityの予約メモリ値を使う軽量計測へ切り替えました。",[18,84,85,86,89,90,93],{},"今回のコンパイル、テスト、Playerビルドには",[52,87,88],{},"Unity.exe -batchmode","を使用し、正式計測では生成済みのWindows PlayerをPowerShellから直接起動しました。Unity CLIの",[52,91,92],{},"unity","コマンドで計測したものではありません。",[14,95,96],{"id":96},"計測対象を小さく固定する",[18,98,99],{},"計測用プロトタイプには、次の処理だけを含めました。",[28,101,102,105,108,111],{},[31,103,104],{},"固定seedからEntityを生成する。",[31,106,107],{},"60 Hzの固定ステップで単純移動する。",[31,109,110],{},"領域端へ到達したEntityを反対側へ戻す。",[31,112,113],{},"単純なMeshと単一Materialで描画する。",[18,115,116],{},"戦闘、索敵、衝突、空間セル、分離・回避、資源、アップグレードは含めていません。Unity Physicsと個体ごとのNavMeshも使用していません。",[18,118,119],{},"これは実際のゲーム性能を予測するためではなく、今後処理を追加したときの差分を測る基準を作るためです。最初の基準に複数の仕組みを入れると、増減の原因を分けられなくなります。",[14,121,123],{"id":122},"editorではなくwindows-playerで測る","EditorではなくWindows Playerで測る",[18,125,126,127,134],{},"Unity EditorのPlay Modeは、Editor自身のUI、Inspector、Scene Viewなどと同じプロセスやリソースを共有します。Unityの",[128,129,133],"a",{"href":130,"rel":131},"https:\u002F\u002Fdocs.unity3d.com\u002F2022.2\u002FDocumentation\u002FManual\u002Fprofiler-profiling-applications.html",[132],"nofollow","アプリケーションのプロファイリング","でも、正確なタイミングは公開対象のプラットフォーム上で測り、Editorは素早い反復確認に使うよう案内されています。",[18,136,137],{},"今回はWindows向けゲームを想定し、正式値をWindows Standalone x64 Development Playerから取得しました。Editor再生は、Sceneが起動してEntityを描画できることを確認するスモークテストだけに使っています。",[18,139,140],{},"Development BuildにはProfilerが含まれるため、Release Buildと同じ性能ではありません。この記事の数値は、同じDevelopment Build内でEntity数を変えた相対比較として扱います。",[14,142,143],{"id":143},"計測条件",[145,146,147,160],"table",{},[148,149,150],"thead",{},[151,152,153,157],"tr",{},[154,155,156],"th",{},"項目",[154,158,159],{},"条件",[161,162,163,174,184,192,200,208,216,224,232,240,248,256,264],"tbody",{},[151,164,165,169],{},[166,167,168],"td",{},"Unity",[166,170,171],{},[52,172,173],{},"6000.5.1f1",[151,175,176,179],{},[166,177,178],{},"Entities",[166,180,181],{},[52,182,183],{},"6.5.0",[151,185,186,189],{},[166,187,188],{},"Player",[166,190,191],{},"Windows Standalone x64 \u002F Development Build",[151,193,194,197],{},[166,195,196],{},"解像度",[166,198,199],{},"1920×1080 \u002F windowed",[151,201,202,205],{},[166,203,204],{},"VSync",[166,206,207],{},"無効",[151,209,210,213],{},[166,211,212],{},"フレームレート上限",[166,214,215],{},"無制限",[151,217,218,221],{},[166,219,220],{},"バックグラウンド更新",[166,222,223],{},"有効",[151,225,226,229],{},[166,227,228],{},"Entity数",[166,230,231],{},"1,000 \u002F 2,000 \u002F 3,000 \u002F 4,000 \u002F 5,000",[151,233,234,237],{},[166,235,236],{},"seed",[166,238,239],{},"固定",[151,241,242,245],{},[166,243,244],{},"固定ステップ",[166,246,247],{},"60 Hz",[151,249,250,253],{},[166,251,252],{},"ウォームアップ",[166,254,255],{},"10秒",[151,257,258,261],{},[166,259,260],{},"計測時間",[166,262,263],{},"30秒",[151,265,266,269],{},[166,267,268],{},"回数",[166,270,271],{},"各Entity数で3回、合計15回",[18,273,274],{},"計測したPCは、Core i7-13700H、GeForce RTX 4060 Laptop GPU、RAM 32 GB、Windows 11のノートPCです。絶対値はハードウェア、電源設定、温度、常駐処理、描画内容によって変わるため、異なる環境の値を同じ表で比較しません。",[18,276,277],{},"実行順は、1回目を1,000→5,000体、2回目を5,000→1,000体、3回目を1,000→5,000体としました。増加順だけを繰り返さず、時間経過や温度変化とEntity数が常に同じ向きにならないようにしています。",[14,279,280],{"id":280},"高レベル指標だけを取得する",[18,282,283],{},"各フレームで、次の値を取得しました。",[28,285,286,291,296,301],{},[31,287,288],{},[52,289,290],{},"FrameTiming.cpuMainThreadFrameTime",[31,292,293],{},[52,294,295],{},"FrameTiming.cpuRenderThreadFrameTime",[31,297,298],{},[52,299,300],{},"FrameTiming.gpuFrameTime",[31,302,303],{},[52,304,305],{},"Profiler.GetTotalReservedMemoryLong()",[18,307,308,311,312,315,316,319],{},[52,309,310],{},"FrameTimingManager.CaptureFrameTimings()","の後に、完了済みの最新フレームを",[52,313,314],{},"GetLatestTimings()","から取得します。プラットフォームによって取得できないフレームがあるため、戻り値が0の場合は集計しません。GPU値も",[52,317,318],{},"gpuFrameTime > 0","のサンプルだけを平均します。",[321,322,327],"pre",{"className":323,"code":324,"language":325,"meta":326,"style":326},"language-csharp shiki shiki-themes github-light github-dark","private readonly FrameTiming[] frameTimings = new FrameTiming[1];\n\nprivate void Update()\n{\n    FrameTimingManager.CaptureFrameTimings();\n\n    if (FrameTimingManager.GetLatestTimings(1, frameTimings) == 0)\n    {\n        return;\n    }\n\n    var timing = frameTimings[0];\n    cpuMainTotal += timing.cpuMainThreadFrameTime;\n    cpuRenderTotal += timing.cpuRenderThreadFrameTime;\n\n    if (timing.gpuFrameTime > 0d)\n    {\n        gpuTotal += timing.gpuFrameTime;\n        gpuSampleCount++;\n    }\n\n    var reservedMemoryBytes = Profiler.GetTotalReservedMemoryLong();\n    memoryTotal += reservedMemoryBytes;\n    memoryPeak = Math.Max(memoryPeak, reservedMemoryBytes);\n    sampleCount++;\n}\n","csharp","",[52,328,329,337,344,350,356,362,367,373,379,385,391,396,402,408,414,419,425,430,436,442,447,452,458,464,470,476],{"__ignoreMap":326},[330,331,334],"span",{"class":332,"line":333},"line",1,[330,335,336],{},"private readonly FrameTiming[] frameTimings = new FrameTiming[1];\n",[330,338,340],{"class":332,"line":339},2,[330,341,343],{"emptyLinePlaceholder":342},true,"\n",[330,345,347],{"class":332,"line":346},3,[330,348,349],{},"private void Update()\n",[330,351,353],{"class":332,"line":352},4,[330,354,355],{},"{\n",[330,357,359],{"class":332,"line":358},5,[330,360,361],{},"    FrameTimingManager.CaptureFrameTimings();\n",[330,363,365],{"class":332,"line":364},6,[330,366,343],{"emptyLinePlaceholder":342},[330,368,370],{"class":332,"line":369},7,[330,371,372],{},"    if (FrameTimingManager.GetLatestTimings(1, frameTimings) == 0)\n",[330,374,376],{"class":332,"line":375},8,[330,377,378],{},"    {\n",[330,380,382],{"class":332,"line":381},9,[330,383,384],{},"        return;\n",[330,386,388],{"class":332,"line":387},10,[330,389,390],{},"    }\n",[330,392,394],{"class":332,"line":393},11,[330,395,343],{"emptyLinePlaceholder":342},[330,397,399],{"class":332,"line":398},12,[330,400,401],{},"    var timing = frameTimings[0];\n",[330,403,405],{"class":332,"line":404},13,[330,406,407],{},"    cpuMainTotal += timing.cpuMainThreadFrameTime;\n",[330,409,411],{"class":332,"line":410},14,[330,412,413],{},"    cpuRenderTotal += timing.cpuRenderThreadFrameTime;\n",[330,415,417],{"class":332,"line":416},15,[330,418,343],{"emptyLinePlaceholder":342},[330,420,422],{"class":332,"line":421},16,[330,423,424],{},"    if (timing.gpuFrameTime > 0d)\n",[330,426,428],{"class":332,"line":427},17,[330,429,378],{},[330,431,433],{"class":332,"line":432},18,[330,434,435],{},"        gpuTotal += timing.gpuFrameTime;\n",[330,437,439],{"class":332,"line":438},19,[330,440,441],{},"        gpuSampleCount++;\n",[330,443,445],{"class":332,"line":444},20,[330,446,390],{},[330,448,450],{"class":332,"line":449},21,[330,451,343],{"emptyLinePlaceholder":342},[330,453,455],{"class":332,"line":454},22,[330,456,457],{},"    var reservedMemoryBytes = Profiler.GetTotalReservedMemoryLong();\n",[330,459,461],{"class":332,"line":460},23,[330,462,463],{},"    memoryTotal += reservedMemoryBytes;\n",[330,465,467],{"class":332,"line":466},24,[330,468,469],{},"    memoryPeak = Math.Max(memoryPeak, reservedMemoryBytes);\n",[330,471,473],{"class":332,"line":472},25,[330,474,475],{},"    sampleCount++;\n",[330,477,479],{"class":332,"line":478},26,[330,480,481],{},"}\n",[18,483,484,485,492],{},"Unityの",[128,486,489],{"href":487,"rel":488},"https:\u002F\u002Fdocs.unity3d.com\u002F6000.0\u002FDocumentation\u002FScriptReference\u002FFrameTiming.html",[132],[52,490,491],{},"FrameTiming","では、CPU Main、CPU Render、GPUの各値は、それぞれの処理区間として定義されています。これらは互いに並行して進むことがあり、単純に足した値が総フレーム時間になるわけではありません。",[18,494,495,497,498,503],{},[52,496,305],{},"が返すのは、Unityが現在と将来の割り当て用に予約したメモリです。OSのprocess working setや、実際に使用中のメモリとは異なります。値の意味は",[128,499,502],{"href":500,"rel":501},"https:\u002F\u002Fdocs.unity3d.com\u002F6000.0\u002FDocumentation\u002FScriptReference\u002FProfiling.Profiler.GetTotalReservedMemoryLong.html",[132],"UnityのScripting API","で確認できます。",[14,505,507],{"id":506},"playerを段階実行する","Playerを段階実行する",[18,509,510,511,514],{},"計測用Sceneだけを含めるWindows Development Playerのビルド処理を",[52,512,513],{},"BuildPipeline.BuildPlayer","で用意し、Editor実行ファイルをバッチモードで一度だけ起動しました。",[321,516,520],{"className":517,"code":518,"language":519,"meta":326,"style":326},"language-powershell shiki shiki-themes github-light github-dark","& $unityEditor `\n  -batchmode `\n  -nographics `\n  -projectPath $projectPath `\n  -buildTarget win64 `\n  -executeMethod '\u003Cプロジェクトのビルドメソッド>' `\n  -quit `\n  -logFile $buildLogPath\n","powershell",[52,521,522,527,532,537,542,547,552,557],{"__ignoreMap":326},[330,523,524],{"class":332,"line":333},[330,525,526],{},"& $unityEditor `\n",[330,528,529],{"class":332,"line":339},[330,530,531],{},"  -batchmode `\n",[330,533,534],{"class":332,"line":346},[330,535,536],{},"  -nographics `\n",[330,538,539],{"class":332,"line":352},[330,540,541],{},"  -projectPath $projectPath `\n",[330,543,544],{"class":332,"line":358},[330,545,546],{},"  -buildTarget win64 `\n",[330,548,549],{"class":332,"line":364},[330,550,551],{},"  -executeMethod '\u003Cプロジェクトのビルドメソッド>' `\n",[330,553,554],{"class":332,"line":369},[330,555,556],{},"  -quit `\n",[330,558,559],{"class":332,"line":375},[330,560,561],{},"  -logFile $buildLogPath\n",[18,563,564,565,568,569,572],{},"ビルドログの終了コードだけでなく、",[52,566,567],{},"BuildReport.summary.result","が",[52,570,571],{},"Succeeded","であることと、Player実行ファイルが生成されたことを確認します。",[18,574,575],{},"Player側には、Entity数、計測モード、ログの保存先を受け取る独自の起動引数を用意しました。PowerShellでは、Entity数と実行順だけを変え、同じPlayerを15回起動します。",[321,577,579],{"className":517,"code":578,"language":519,"meta":326,"style":326},"$orders = @(\n  @(1000, 2000, 3000, 4000, 5000),\n  @(5000, 4000, 3000, 2000, 1000),\n  @(1000, 2000, 3000, 4000, 5000)\n)\n\nfor ($run = 0; $run -lt $orders.Count; $run++) {\n  foreach ($entityCount in $orders[$run]) {\n    $logPath = Join-Path $resultRoot \"$entityCount\u002Frun-$($run + 1).log\"\n    $argumentList = \"-entityCount $entityCount -measure -logFile `\"$logPath`\"\"\n\n    $process = Start-Process `\n      -FilePath $playerPath `\n      -ArgumentList $argumentList `\n      -PassThru `\n      -Wait\n\n    if ($process.ExitCode -ne 0) {\n      throw \"Measurement failed: count=$entityCount run=$($run + 1)\"\n    }\n  }\n}\n",[52,580,581,586,591,596,601,606,610,615,620,625,630,634,639,644,649,654,659,663,668,673,677,682],{"__ignoreMap":326},[330,582,583],{"class":332,"line":333},[330,584,585],{},"$orders = @(\n",[330,587,588],{"class":332,"line":339},[330,589,590],{},"  @(1000, 2000, 3000, 4000, 5000),\n",[330,592,593],{"class":332,"line":346},[330,594,595],{},"  @(5000, 4000, 3000, 2000, 1000),\n",[330,597,598],{"class":332,"line":352},[330,599,600],{},"  @(1000, 2000, 3000, 4000, 5000)\n",[330,602,603],{"class":332,"line":358},[330,604,605],{},")\n",[330,607,608],{"class":332,"line":364},[330,609,343],{"emptyLinePlaceholder":342},[330,611,612],{"class":332,"line":369},[330,613,614],{},"for ($run = 0; $run -lt $orders.Count; $run++) {\n",[330,616,617],{"class":332,"line":375},[330,618,619],{},"  foreach ($entityCount in $orders[$run]) {\n",[330,621,622],{"class":332,"line":381},[330,623,624],{},"    $logPath = Join-Path $resultRoot \"$entityCount\u002Frun-$($run + 1).log\"\n",[330,626,627],{"class":332,"line":387},[330,628,629],{},"    $argumentList = \"-entityCount $entityCount -measure -logFile `\"$logPath`\"\"\n",[330,631,632],{"class":332,"line":393},[330,633,343],{"emptyLinePlaceholder":342},[330,635,636],{"class":332,"line":398},[330,637,638],{},"    $process = Start-Process `\n",[330,640,641],{"class":332,"line":404},[330,642,643],{},"      -FilePath $playerPath `\n",[330,645,646],{"class":332,"line":410},[330,647,648],{},"      -ArgumentList $argumentList `\n",[330,650,651],{"class":332,"line":416},[330,652,653],{},"      -PassThru `\n",[330,655,656],{"class":332,"line":421},[330,657,658],{},"      -Wait\n",[330,660,661],{"class":332,"line":427},[330,662,343],{"emptyLinePlaceholder":342},[330,664,665],{"class":332,"line":432},[330,666,667],{},"    if ($process.ExitCode -ne 0) {\n",[330,669,670],{"class":332,"line":438},[330,671,672],{},"      throw \"Measurement failed: count=$entityCount run=$($run + 1)\"\n",[330,674,675],{"class":332,"line":444},[330,676,390],{},[330,678,679],{"class":332,"line":449},[330,680,681],{},"  }\n",[330,683,684],{"class":332,"line":454},[330,685,481],{},[18,687,688,691],{},[52,689,690],{},"Start-Process -ArgumentList","は渡した配列を空白区切りの文字列へ結合するため、空白を含み得るログパスは引用符で保護します。実際の引数名はプロジェクト側の実装に合わせます。重要なのは、Sceneや設定ファイルを書き換えず、同じPlayer、seed、解像度、ウォームアップ時間、計測時間を維持したままEntity数だけを変えることです。",[18,693,694],{},"各実行の最後には、条件、サンプル数、平均値、peakを1行のJSONとしてログへ出力しました。生ログは環境固有の情報や絶対パスを含む可能性があるため公開せず、比較に必要な集計値だけを残します。",[14,696,698],{"id":697},"_10005000体の結果","1,000〜5,000体の結果",[18,700,701],{},"次の表は各Entity数の3回平均です。",[145,703,704,726],{},[148,705,706],{},[151,707,708,711,714,717,720,723],{},[154,709,228],{"align":710},"right",[154,712,713],{"align":710},"参考FPS",[154,715,716],{"align":710},"CPU Main",[154,718,719],{"align":710},"CPU Render",[154,721,722],{"align":710},"GPU Frame",[154,724,725],{"align":710},"Total Reserved Memory 平均 \u002F peak",[161,727,728,746,766,785,805],{},[151,729,730,733,736,738,741,743],{},[166,731,732],{"align":710},"1,000",[166,734,735],{"align":710},"737.3",[166,737,54],{"align":710},[166,739,740],{"align":710},"0.319 ms",[166,742,65],{"align":710},[166,744,745],{"align":710},"440.86 \u002F 441.53 MiB",[151,747,748,751,754,757,760,763],{},[166,749,750],{"align":710},"2,000",[166,752,753],{"align":710},"718.3",[166,755,756],{"align":710},"0.736 ms",[166,758,759],{"align":710},"0.315 ms",[166,761,762],{"align":710},"0.357 ms",[166,764,765],{"align":710},"440.20 \u002F 441.53 MiB",[151,767,768,771,774,777,780,783],{},[166,769,770],{"align":710},"3,000",[166,772,773],{"align":710},"693.7",[166,775,776],{"align":710},"0.751 ms",[166,778,779],{"align":710},"0.309 ms",[166,781,782],{"align":710},"0.396 ms",[166,784,745],{"align":710},[151,786,787,790,793,796,799,802],{},[166,788,789],{"align":710},"4,000",[166,791,792],{"align":710},"670.9",[166,794,795],{"align":710},"0.755 ms",[166,797,798],{"align":710},"0.312 ms",[166,800,801],{"align":710},"0.434 ms",[166,803,804],{"align":710},"441.53 \u002F 441.53 MiB",[151,806,807,810,813,815,817,819],{},[166,808,809],{"align":710},"5,000",[166,811,812],{"align":710},"641.0",[166,814,58],{"align":710},[166,816,779],{"align":710},[166,818,68],{"align":710},[166,820,745],{"align":710},[18,822,823],{},"参考FPSは30秒間の取得フレーム数から算出した処理量の目安であり、モニターに表示されたリフレッシュレートではありません。",[18,825,826],{},"結果は次のように読みました。",[828,829,830,839,842,850],"ol",{},[31,831,832,833,835,836,838],{},"CPU Main Threadは、1,000体で",[52,834,54],{},"、5,000体で",[52,837,58],{},"でした。Run間の変動に比べて増加傾向が小さく、今回の単純なBurst移動は体数増加による影響が目立ちませんでした。",[31,840,841],{},"CPU Render ThreadとTotal Reserved Memoryは、1,000〜5,000体でほぼ横ばいでした。",[31,843,844,845,55,847,849],{},"GPU Frameは",[52,846,65],{},[52,848,68],{},"へ増え、Entity数に対して最も一貫した変化を示しました。",[31,851,852],{},"5,000体時点の絶対時間はCPU Main Threadの方が長いため、現状の最初の制約候補はCPU Main Threadです。一方、今後さらに描画数を増やす場合の感度はGPU側にあります。",[18,854,855],{},"平均値だけでは一時的なスパイクやフレーム分布を判断できません。ゲームループが増えた段階ではpercentileや短時間のProfiler captureも必要ですが、最初の段階比較にはこの軽量な平均値を使います。",[14,857,859],{"id":858},"生profiler-captureが肥大化した失敗","生Profiler captureが肥大化した失敗",[18,861,862,863,866],{},"最初は、Player起動時から",[52,864,865],{},"-profiler-log-file","で生Profilerデータを保存しようとしました。しかし、VSyncとフレームレート上限を外した状態で全データを流し続けた結果、captureは約4.59 GBまで増え、実行ログに512 MBのProfiler送信バッファ上限到達が記録され、収集が停止しました。",[18,868,484,869,876,877,884],{},[128,870,873],{"href":871,"rel":872},"https:\u002F\u002Fdocs.unity3d.com\u002F6000.0\u002FDocumentation\u002FScriptReference\u002FProfiling.Profiler-logFile.html",[132],[52,874,875],{},"Profiler.logFile","には、出力が追いつかない場合にフレームをスキップすることが記載されています。また、",[128,878,881],{"href":879,"rel":880},"https:\u002F\u002Fdocs.unity3d.com\u002F6000.0\u002FDocumentation\u002FScriptReference\u002FProfiling.Profiler-maxUsedMemory.html",[132],[52,882,883],{},"Profiler.maxUsedMemory","は、Profilerが書き出しより速くデータを収集した場合、バッファ上限へ達すると収集を停止すると説明しています。",[18,886,887],{},"バッファを増やせば停止までの時間は延ばせますが、段階計測で毎回数GBのファイルを作る問題は残ります。そのため、用途を次のように分けました。",[145,889,890,900],{},[148,891,892],{},[151,893,894,897],{},[154,895,896],{},"用途",[154,898,899],{},"手段",[161,901,902,910,918],{},[151,903,904,907],{},[166,905,906],{},"Entity数ごとの傾向比較",[166,908,909],{},"FrameTimingと予約メモリの軽量ログ",[151,911,912,915],{},[166,913,914],{},"特定Systemの原因調査",[166,916,917],{},"Profiler markerを使った短時間capture",[151,919,920,923],{},[166,921,922],{},"フレームスパイクの詳細調査",[166,924,925],{},"対象時間とProfiler areaを絞ったcapture",[18,927,928],{},"大量の生データを常に保存するのではなく、まず軽量なカウンターで変化を見つけ、必要な箇所だけ詳細に掘る方が扱いやすい結果になりました。",[14,930,931],{"id":931},"次の計測で変えないもの",[18,933,934],{},"次は、Uniform spatial cellsと距離二乗による近傍候補の抽出を追加する予定です。比較を成立させるため、次の条件は変えません。",[28,936,937,940,943,946,949,952],{},[31,938,939],{},"同じPlayer種別と解像度",[31,941,942],{},"同じEntity数とseed",[31,944,945],{},"同じ固定ステップ",[31,947,948],{},"同じウォームアップ時間と計測時間",[31,950,951],{},"同じ3回の実行順",[31,953,954],{},"同じ集計方法",[18,956,957],{},"変更するのは、候補抽出Systemの有無と処理内容です。比較対象以外を固定することで、新しい処理がCPU Main Threadや描画へ与えた影響を判断できます。",[14,959,960],{"id":960},"注意点",[28,962,963,966,969,972,975,978],{},[31,964,965],{},"この結果は、一台のPCと単純なMesh・Materialを使ったプロトタイプの値です。",[31,967,968],{},"Development Buildのため、最終的なRelease Build性能を示すものではありません。",[31,970,971],{},"5,000体で問題がなかったことは、戦闘や索敵を含む5,000体のゲームが問題なく動くことを意味しません。",[31,973,974],{},"平均値はフレームスパイクを隠すため、操作感や安定性の確認には別の指標が必要です。",[31,976,977],{},"GPU timingはプラットフォームやGraphics APIによって取得できない場合があります。計測開始時に機能の有効性と有効サンプル数を確認します。",[31,979,980],{},"ログを公開するときは、絶対パス、ユーザー名、プロジェクト名、ライセンスや認証に関する情報を除去します。",[14,982,983],{"id":983},"関連資料",[28,985,986,992,997,1004,1010,1015,1020],{},[31,987,988],{},[128,989,991],{"href":130,"rel":990},[132],"Unityでアプリケーションをプロファイリングする",[31,993,994],{},[128,995,491],{"href":487,"rel":996},[132],[31,998,999],{},[128,1000,1003],{"href":1001,"rel":1002},"https:\u002F\u002Fdocs.unity3d.com\u002F6000.0\u002FDocumentation\u002FScriptReference\u002FFrameTimingManager.GetLatestTimings.html",[132],"FrameTimingManager.GetLatestTimings",[31,1005,1006],{},[128,1007,1009],{"href":500,"rel":1008},[132],"Profiler.GetTotalReservedMemoryLong",[31,1011,1012],{},[128,1013,875],{"href":871,"rel":1014},[132],[31,1016,1017],{},[128,1018,883],{"href":879,"rel":1019},[132],[31,1021,1022],{},[128,1023,1025],{"href":1024},"\u002Fknowledge\u002Fgame\u002Funity\u002Funity-cli-minimal-validation","Unity CLIで最小プロジェクトとEdit Modeテストを検証する",[1027,1028,1029],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":326,"searchDepth":339,"depth":339,"links":1031},[1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043],{"id":16,"depth":339,"text":16},{"id":42,"depth":339,"text":42},{"id":96,"depth":339,"text":96},{"id":122,"depth":339,"text":123},{"id":143,"depth":339,"text":143},{"id":280,"depth":339,"text":280},{"id":506,"depth":339,"text":507},{"id":697,"depth":339,"text":698},{"id":858,"depth":339,"text":859},{"id":931,"depth":339,"text":931},{"id":960,"depth":339,"text":960},{"id":983,"depth":339,"text":983},"Unity ECSの最小プロトタイプをWindows Playerで15回計測し、軽量な性能比較へ切り替えた手順と結果の読み方をまとめます。","md",{},"\u002Fknowledge\u002Fgame\u002Funity\u002Fecs-windows-player-performance-baseline","2026-08-16",{"title":5,"description":1044},"published","knowledge\u002Fgame\u002Funity\u002Fecs-windows-player-performance-baseline",[1053,1054,1055,1056],"ecs","performance","profiling","windows-player",[92],"t-RHxvjwjKOEqvekXuNsPkBwR2z-LHleHQaS2g8awYo",{"ja":342,"en":1060},false,1791891818604]