<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>パフォーマンス on Wuyukwi's Notebook</title><link>https://wuyukwi.duckdns.org/tags/%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9/</link><description>Recent content in パフォーマンス on Wuyukwi's Notebook</description><generator>Hugo</generator><language>ja</language><lastBuildDate>Wed, 01 Apr 2026 12:47:15 +0900</lastBuildDate><atom:link href="https://wuyukwi.duckdns.org/tags/%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9/index.xml" rel="self" type="application/rss+xml"/><item><title>🧊 【Unity】10万オブジェクトを回転させたらどこがボトルネックになるのか（後編：ISystemで一桁msへ）</title><link>https://wuyukwi.duckdns.org/posts/zenn-8577fbf1074840/</link><pubDate>Wed, 01 Apr 2026 12:47:15 +0900</pubDate><guid>https://wuyukwi.duckdns.org/posts/zenn-8577fbf1074840/</guid><description>&lt;blockquote&gt;
&lt;p&gt;📌 &lt;em&gt;この記事は &lt;a href="https://zenn.dev/wuyukwi/articles/8577fbf1074840"&gt;Zenn&lt;/a&gt; に投稿した内容のアーカイブです。&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="はじめに"&gt;はじめに&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://zenn.dev/wuyukwi/articles/88800f31f667f3"&gt;前回&lt;/a&gt;は、Job System + Burst を使って&lt;br&gt;
&lt;strong&gt;10万オブジェクトの回転処理（46ms → 3.5ms）&lt;/strong&gt; まで最適化しました。&lt;/p&gt;
&lt;p&gt;ただしその時点でも、フレーム全体としてはまだ重く、&lt;br&gt;
ボトルネックはレンダリング側に残っていました。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="なぜjob-systemだけでは不十分だったのか"&gt;なぜJob Systemだけでは不十分だったのか&lt;/h2&gt;
&lt;p&gt;前回の時点で回転処理自体はかなり軽くなっていましたが、&lt;br&gt;
それでもフレーム全体としては大きな負荷が残っていました。&lt;/p&gt;
&lt;p&gt;原因は、描画周りの処理です。&lt;/p&gt;
&lt;p&gt;たとえロジック（Job）が高速でも、メインスレッド側では依然として&lt;br&gt;
10万個の &lt;code&gt;MeshRenderer&lt;/code&gt; を個別に処理する必要があります。&lt;/p&gt;
&lt;p&gt;具体的には以下のような処理です：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Culling（可視判定）&lt;/li&gt;
&lt;li&gt;Bounding Volume（バウンディング更新）&lt;/li&gt;
&lt;li&gt;RenderQueue（描画順の整理）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これらがすべて「オブジェクト単位」で実行されるため、&lt;br&gt;
結果として大きなCPU負荷になっていました。&lt;/p&gt;
&lt;p&gt;この問題に対するアプローチが、Entities Graphicsです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;目標：&lt;br&gt;
→ GameObjectベースのオブジェクトをEntityに変換する&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;仕組み：&lt;br&gt;
→ 変換後は、これらの処理を &lt;code&gt;Entities Graphics&lt;/code&gt; が内部的に管理し、&lt;br&gt;
&lt;code&gt;BatchRendererGroup&lt;/code&gt; を利用して描画処理をまとめて実行します。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;その結果：&lt;/p&gt;
&lt;p&gt;数万〜数十万単位のオブジェクトでも、&lt;br&gt;
ごく少数のバッチとして扱えるようになります。&lt;/p&gt;
&lt;h2 id="-結果"&gt;■ 結果&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://static.zenn.studio/user-upload/8eac221c088d-20260401.gif"&gt;&lt;br&gt;
今回は DOTS（Entities + Entities Graphics）に移行した結果：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;フレーム時間：約120ms → 約9ms&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;110FPS前後で安定&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ほぼ別物レベルまで改善しています。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="-比較"&gt;■ 比較&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;指標&lt;/th&gt;
&lt;th&gt;改造前（GameObject）&lt;/th&gt;
&lt;th&gt;改造後（Pure DOTS）&lt;/th&gt;
&lt;th&gt;改善&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Batches&lt;/td&gt;
&lt;td&gt;~120,000&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;74&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;約1486倍削減&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SetPass Calls&lt;/td&gt;
&lt;td&gt;56&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;26&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;約2.1倍改善&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tris / Verts&lt;/td&gt;
&lt;td&gt;不安定&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;安定&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;描画の一貫性向上&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frame Time&lt;/td&gt;
&lt;td&gt;120ms（8FPS）&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;9ms（110FPS）&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;約13倍高速化&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="-profilerを見ると何が起きているか"&gt;■ Profilerを見ると何が起きているか&lt;/h2&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://static.zenn.studio/user-upload/561808254336-20260401.png"&gt;&lt;br&gt;
&lt;img loading="lazy" src="https://static.zenn.studio/user-upload/d2021f89924c-20260401.png"&gt;&lt;br&gt;
Profilerを確認すると：&lt;/p&gt;</description></item><item><title>🧊 【Unity】10万オブジェクトを回転させたらどこがボトルネックになるのか（前編：LateUpdateとJob System）</title><link>https://wuyukwi.duckdns.org/posts/zenn-88800f31f667f3/</link><pubDate>Tue, 31 Mar 2026 17:31:45 +0900</pubDate><guid>https://wuyukwi.duckdns.org/posts/zenn-88800f31f667f3/</guid><description>&lt;blockquote&gt;
&lt;p&gt;📌 &lt;em&gt;この記事は &lt;a href="https://zenn.dev/wuyukwi/articles/88800f31f667f3"&gt;Zenn&lt;/a&gt; に投稿した内容のアーカイブです。&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;最近、DOTS（Data-Oriented Tech Stack）が実際どのくらい効果があるのか気になっていたので、&lt;br&gt;
簡単な検証を兼ねて触ってみることにしました。&lt;/p&gt;
&lt;p&gt;せっかくなので「大量のオブジェクトを動かした場合にどこがボトルネックになるのか？」も含めて、&lt;br&gt;
段階的に確認していこうと思います。&lt;/p&gt;
&lt;p&gt;この記事ではまず、LateUpdateでの回転処理のボトルネックと、&lt;br&gt;
Job Systemによる最適化の効果にフォーカスします。&lt;/p&gt;
&lt;p&gt;レンダリング周り（CullingやDrawCall）については、次回以降で触れる予定です。&lt;/p&gt;
&lt;h2 id="-検証環境"&gt;■ 検証環境&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CPU：i7-12700K&lt;/li&gt;
&lt;li&gt;GPU：RTX 3070&lt;/li&gt;
&lt;li&gt;Unity：URPの新規プロジェクト&lt;/li&gt;
&lt;li&gt;オブジェクト数：10万（Cube）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="-テスト内容"&gt;■ テスト内容&lt;/h2&gt;
&lt;p&gt;シンプルに「10万個のCubeを生成して回転させるだけ」です。&lt;br&gt;
&lt;img loading="lazy" src="https://static.zenn.studio/user-upload/96aecb2d5f9f-20260331.gif"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;BoxColliderは削除&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ランダム位置に配置&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;各オブジェクトにランダムな回転軸&lt;/p&gt;
&lt;p&gt;void Start()
{
var root = new GameObject(&amp;ldquo;CubeRoot&amp;rdquo;).transform;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (int i = 0; i &amp;lt; spawnCount; i++)
{
var go = Instantiate(prefab, Random.insideUnitSphere * 50f, Quaternion.identity, root);
transforms.Add(go.transform);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;void LateUpdate()
{
float dt = Time.deltaTime;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (int i = 0; i &amp;lt; transforms.Count; i++)
{
transforms[i].Rotate(rotationAxes[i], 100f * dt);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;</description></item></channel></rss>