Unity-Technologies / Unity-Technologies/com.unity.netcode.gameobjects

Named Messages: Don't allocate a byte array whenever you send a message

オープン
#2,779 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

type:feature
主要言語
C#
スター
2.3k
フォーク
461
平均マージ
3日 16時間
マージ済み PR(30日)
20

説明

Is your feature request related to a problem? Please describe.
Named Messages are a great way to send custom messages that are not tied to a specific game object and/or are more dynamic than standard RPC calls. However, the only way to send these messages (via CustomMessagingManager.SendNamedMessage) is by providing a string which gets then hashed using XXHash.Hash32 or XXHash.Hash64 which then calls Encoding.UTF8.GetBytes(text). This function always allocates a new byte array, containing the string. As far as I can see, there is no other possible way to send a named message.

Describe the solution you'd like
I see two possible solutions:

  • Don't use Encoding.UTF8.GetBytes(text) and instead use one of the overloads where you can specify an existing byte[] or Span. This would allow the use of a pre-alloced buffer (e.g. from a temp alloced NativeArray or an array pool).
  • Add a function overload where I can provide the hash myself (and provide a way to obtain this hash). This would work similar to e.g. Animator.StringToHash or Shader.PropertyToID. However, the HashSize can be 4 bytes or 8 bytes (depending on NetworkManager.NetworkConfig.RpcHashSize) and can even change during the runtime (at least, CustomMessageManager supports this case). Therefore it might be a bit confusing to the user which hash (with which data type) they have to use in this case - unless the GetHash function returns a struct which contains both hashes...which might be a bit weird as well.

Describe alternatives you've considered

  • I can use unnamed messages and just re-implement the logic from named messages, using the solution described above.

Additional context

Example GC Alloc from the profiler:

Size: 41

Call Stack:
mscorlib.dll!System.Text::Encoding.GetBytes()
Unity.Netcode.Runtime.dll!Unity.Netcode::XXHash.Hash32()	./Library/PackageCache/com.unity.netcode.gameobjects@1.5.2/Runtime/Hashing/XXHash.cs:218
Unity.Netcode.Runtime.dll!Unity.Netcode::CustomMessagingManager.SendNamedMessage()	./Library/PackageCache/com.unity.netcode.gameobjects@1.5.2/Runtime/Messaging/CustomMessageManager.cs:296
Unity.Netcode.Runtime.dll!Unity.Netcode::CustomMessagingManager.SendNamedMessageToAll()	./Library/PackageCache/com.unity.netcode.gameobjects@1.5.2/Runtime/Messaging/CustomMessageManager.cs:236

I wouldn't say this is a huge problem (though it depends on how many messages are being sent and how long their name is), and unnamed messages are an easy workaround. However, most of this package seems to focus on allocating as little as possible, and I think that fixing this problem here shouldn't be too hard (otherwise just ignore this issue).

Thanks for your work on this amazing package, I really enjoy using it! I can also provide a PR with a fix mentioned above if you would like me to, I just didn't want to submit something unwanted.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

まず Runtime/Hashing/XXHash.cs と Runtime/Messaging/CustomMessageManager.cs を読み、特に SendNamedMessage の呼び出し経路と、報告された行に記載されているアロケーションを確認します。プロファイラーを使って名前付きメッセージのアロケーションを再現し、その後、設定されたハッシュサイズが変わっても 32 ビットと 64 ビットの両方のハッシュ動作を維持しながら、それを回避する方法を判断します。名前付き送信で名前のバイト配列がアロケートされなくなり、既存の動作が利用可能なテストで引き続きカバーされていれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
csharp, unity
領域
networking, performance
issue の種類
機能追加
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
38/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。