|
using System.Collections; |
|
using System.Collections.Generic; |
|
using System.Diagnostics; |
|
using System.Reflection; |
|
using TMPro; |
|
using UnityEngine; |
|
using Debug = UnityEngine.Debug; |
|
|
|
public class ReflectionBenchmark : MonoBehaviour |
|
{ |
|
TextMeshProUGUI label; |
|
|
|
int n = 1000000; |
|
|
|
class Animal |
|
{ |
|
public string habitat; |
|
public string biome; |
|
public bool ambassador; |
|
} |
|
|
|
|
|
IEnumerator Start () |
|
{ |
|
label = GetComponent<TextMeshProUGUI>(); |
|
|
|
yield return new WaitForSeconds(1f); |
|
|
|
Animal instance = new Animal |
|
{ |
|
habitat = "", |
|
ambassador = false, |
|
biome = "", |
|
}; |
|
string[] fieldNames = { "habitat", "ambassador", "biome"}; |
|
|
|
string result = $"n: {n}\n"; |
|
|
|
var watch = new Stopwatch(); |
|
|
|
watch.Start(); |
|
Normal(instance); |
|
result += $"instance.field: {watch.ElapsedMilliseconds}ms\n"; |
|
watch.Restart(); |
|
|
|
SimpleReflection(fieldNames, instance); |
|
result += $"Full refelction: {watch.ElapsedMilliseconds}ms\n"; |
|
watch.Restart(); |
|
|
|
CacheField(fieldNames, instance); |
|
result += $"Cache GetField() in dict: {watch.ElapsedMilliseconds}ms\n"; |
|
watch.Restart(); |
|
|
|
CacheValue(fieldNames, instance); |
|
result += $"Cache GetValue() in dict: {watch.ElapsedMilliseconds}ms\n"; |
|
watch.Restart(); |
|
|
|
CacheValueArray(fieldNames, instance); |
|
result += $"Cache GetValue() in array: {watch.ElapsedMilliseconds}ms\n"; |
|
watch.Stop(); |
|
|
|
label.text = result; |
|
} |
|
|
|
void Normal(Animal instance) |
|
{ |
|
int sumNormal = 0; |
|
for (int i = 0; i < n; i++) |
|
{ |
|
sumNormal += instance.habitat.ToString().Length; |
|
sumNormal += instance.ambassador.ToString().Length; |
|
sumNormal += instance.biome.ToString().Length; |
|
} |
|
|
|
Debug.Log("Control Sum " + sumNormal); |
|
} |
|
|
|
void SimpleReflection(string[] fieldNames, Animal instance) |
|
{ |
|
int sumReflection = 0; |
|
for (int i = 0; i < n; i++) |
|
{ |
|
foreach (var fieldName in fieldNames) |
|
{ |
|
var field = instance.GetType().GetField(fieldName); |
|
sumReflection += field.GetValue(instance).ToString().Length; |
|
} |
|
} |
|
|
|
Debug.Log("Control Sum " + sumReflection); |
|
} |
|
|
|
void CacheField(string[] fieldNames, Animal instance) |
|
{ |
|
int sumCached = 0; |
|
var dict = new Dictionary<string, FieldInfo>(); |
|
|
|
foreach (var fieldName in fieldNames) |
|
dict[fieldName] = instance.GetType().GetField(fieldName); |
|
|
|
for (int i = 0; i < n; i++) |
|
{ |
|
foreach (var fieldName in fieldNames) |
|
sumCached += dict[fieldName].GetValue(instance).ToString().Length; |
|
} |
|
|
|
Debug.Log("Control Sum " + sumCached); |
|
} |
|
|
|
void CacheValue(string[] fieldNames, Animal instance) |
|
{ |
|
int sumCached = 0; |
|
var dict = new Dictionary<string, object>(); |
|
|
|
foreach (var fieldName in fieldNames) |
|
dict[fieldName] = instance.GetType().GetField(fieldName).GetValue(instance); |
|
|
|
for (int i = 0; i < n; i++) |
|
{ |
|
foreach (var fieldName in fieldNames) |
|
sumCached += dict[fieldName].ToString().Length; |
|
} |
|
|
|
Debug.Log("Control Sum " + sumCached); |
|
} |
|
|
|
void CacheValueArray(string[] fieldNames, Animal instance) |
|
{ |
|
int sumCached = 0; |
|
var array = new KeyValuePair<string, object>[fieldNames.Length]; |
|
|
|
for (var i = 0; i < fieldNames.Length; i++) |
|
array[i] = new KeyValuePair<string, object>(fieldNames[i], |
|
instance.GetType().GetField(fieldNames[i]).GetValue(instance)); |
|
|
|
for (int i = 0; i < n; i++) |
|
{ |
|
for (var j = 0; j < fieldNames.Length; j++) |
|
sumCached += array[j].Value.ToString().Length; |
|
} |
|
|
|
Debug.Log("Control Sum " + sumCached); |
|
} |
|
} |