[Unity]FindOfjectsOfType<T> と SceneのRootGameObjectsに対してGetComponents<T>するのではどちらが早いのか？

#結果　
###rootからさらった方が早い
Editor

| メソッド | 平均処理時間(ms) |
|:-----------|------------:|
| FindObjectOfType | 10.0 | 
| FindObjectsOfType | 11 .0| 
| RootGameObject | 3.5 | 
| RootGameObject(Listに追加) | 3.0 | 

![findobject vs rootgameobject editor.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253279/667c035a-9ea2-5edc-1e73-d580ba191e55.jpeg)



standaloneでdevelopmentbuild + Autoconnect profiler

| メソッド | 平均処理時間(ms) |
|:-----------|------------:|
| FindObjectOfType | 6.5 | 
| FindObjectsOfType | 6.9 | 
| RootGameObject | 2.7 | 
| RootGameObject(Listに追加) | 2.7 | 

![findobject vs rootgameobject mono.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253279/6ac0411d-b4f6-d254-300a-39db706d81ff.jpeg)

###大雑把な環境
windows7
Unity 2018.4.5f1
.net 4.x 
.net standard 2.0
mono

#計測コード
```C#:profile.cs
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
public class NewBehaviourScript : MonoBehaviour
{
	const string ROOT_GAMEOBJECT_NO_BUFFERED = "rootGameObjects no buffered";
	const string ROOT_GAMEOBJECT_BUFFERED = "root game object buffered";
	const string FIND_OBJECTS_TYPE = "find object's of type";
	const string FIND_OBJECT_TYPE = "find object of type";

	// Start is called before the first frame update
	void Start()
	{
		for (int i = 0; i < 1000; i++)
		{
			var go = new GameObject($"number {i}");
			for (int y = 0; y < 20; y++)
			{
				go.AddComponent<Type1>();
				go.AddComponent<Type2>();
			}
		}
	}

	private List<Type1> _Type1s = new List<Type1>();
	private List<GameObject> GameObjects = new List<GameObject>();
	private List<Type1> _Type1sBuffer = new List<Type1>();
	// Update is called once per frame
	void Update()
	{
		GC.Collect();
		{
			Profiler.BeginSample(ROOT_GAMEOBJECT_NO_BUFFERED);
			var rootGameObjects = gameObject.scene.GetRootGameObjects();
			Type1[][] type1s = new Type1[rootGameObjects.Length][];
			for (int i = 0; i < rootGameObjects.Length; i++)
			{
				type1s[i] = rootGameObjects[i].GetComponentsInChildren<Type1>();
			}
			Profiler.EndSample();
		}
		GC.Collect();
		{
			Profiler.BeginSample(ROOT_GAMEOBJECT_BUFFERED);
			gameObject.scene.GetRootGameObjects(GameObjects);
			for (int i = 0; i < GameObjects.Count; i++)
			{
				GameObjects[i].GetComponentsInChildren(_Type1sBuffer);
				_Type1s.AddRange(_Type1sBuffer);
			}
			Profiler.EndSample();
			_Type1sBuffer.Clear();
			_Type1s.Clear();
			GameObjects.Clear();
		}
		GC.Collect();
		{
			Profiler.BeginSample(FIND_OBJECTS_TYPE);
			var type1s = GameObject.FindObjectsOfType<Type1>();
			Profiler.EndSample();
		}
		GC.Collect();
		{
			Profiler.BeginSample(FIND_OBJECT_TYPE);
			var type1 = GameObject.FindObjectOfType<Type1>();
			Profiler.EndSample();
		}
	}
}

//別ファイルで定義
public class Type1 : MonoBehaviour
{
}
public class Type2 : MonoBehaviour
{
}
```
#感想
最初typoで単体のコンポーネントを拾ってくるFindObjectOfType()をつかってて
それですらRootのGameObjectを全部さらってGetComponentsInChildren<T>()したやつより遅かったので
両方計測した結果FindObjectOfType()とFindObject<strong><font color="Red">s</font></strong>OfType()が速度的に大差ないという驚きの結果を偶然得ることができました
FindObject<strong><font color="Red">s</font></strong>OfType()を処理した結果の先頭を返してるっぽい挙動

重いと言うのは知ってましたが
単体の方ですら初期化でも使うのを躊躇うほどの処理負荷がかかるとは思ってませんでした

SceneからGameObject全部とってきてGetComponentsする方が一見すると重そうなのに
中でどういう実装が行われているのか知りませんが
似たような速度になるならともかく、どうしてこんなに差がでるほど遅いのか本当に謎ですね