GetComponentの負荷検証
気になる内容の記事があったので検証してみました
qiita.com
気になる点
- Dictionaryのインデクサを使用している←TryGetValueを使用しないと負荷が高い(ソースは忘れた…)
- transform.Rotationの実装次第ではあまり検証になっていない…気がする
ちょっと修正版作成
コードそのままお借りしてます+無理やり適当な名前で追加してすみません
極力transform取得の処理負荷が出るようにlocalPositionにしています
public class PerformanceTest : MonoBehaviour { private readonly Dictionary<Type, object> _componentCache = new Dictionary<Type, object>(); public new T GetComponent<T>() where T : Component { var type = typeof(T); if (_componentCache.ContainsKey(type) == false) { var component = base.GetComponent<T>(); if (component == null) component = gameObject.AddComponent<T>(); _componentCache.Add(type, component); } return (T) _componentCache[type]; } private readonly Dictionary<Type, Component> _componentCacheFast = new Dictionary<Type, Component>(); public T GetComponentFast<T>() where T : Component { var type = typeof(T); Component component = null; if (_componentCacheFast.TryGetValue(type, out component) == false) { component = base.GetComponent<T>(); if (component == null) component = gameObject.AddComponent<T>(); _componentCacheFast.Add(type, component); } return (T) component; } private readonly int max = 10000; private CustomSampler samplerNormal; private CustomSampler samplerDefaultGetComponent; private CustomSampler samplerOverrideGetComponent; private CustomSampler samplerGetComponentFast; private CustomSampler samplerCache; private Transform cacheTransform; private void Awake() { samplerNormal = CustomSampler.Create("transform"); samplerDefaultGetComponent = CustomSampler.Create("base.GetComponent"); samplerOverrideGetComponent = CustomSampler.Create("GetComponent"); samplerGetComponentFast = CustomSampler.Create ("GetComponentFast"); samplerCache = CustomSampler.Create("cacheTransform"); cacheTransform = base.GetComponent<Transform>(); } private void Update() { Vector3 pos; //普通の使い方 samplerNormal.Begin(); for (var i = 0; i < max; ++i) pos = transform.localPosition; samplerNormal.End(); //GetComponentおじさん samplerDefaultGetComponent.Begin(); for (var i = 0; i < max; ++i) pos = base.GetComponent<Transform> ().localPosition; samplerDefaultGetComponent.End(); //貼るだけで速くなるコード(?) samplerOverrideGetComponent.Begin(); for (var i = 0; i < max; ++i) pos = GetComponent<Transform> ().localPosition; samplerOverrideGetComponent.End(); //貼るだけで速くなるコードTryGetValue版 samplerGetComponentFast.Begin(); for (var i = 0; i < max; ++i) pos = GetComponentFast<Transform> ().localPosition; samplerGetComponentFast.End(); //メンバ変数でキャッシュ samplerCache.Begin(); for (var i = 0; i < max; ++i) pos = cacheTransform.localPosition; samplerCache.End(); } }
結果
丁度2018が正式リリースされていたので2018.1.0f2で検証
transform | 0.58ms |
GetComponent | 0.846ms |
DictionaryIndexer | 3.17ms |
DictionaryTryGetValue | 2.06ms |
transformCache | 0.399ms |
TryGetValueにするだけで約65%軽減(どっちにしろ重いけど、、)
キャッシュとの違いは10倍近く
結論
何が言いたいかというとキャッシュはしたほうがいいよ
Dictionaryのインデクサは使わないほうがいいよ
という話でした