나는 foreach문이 코드가 훨씬 간결해서 선호하는 편인데, 성능 개선이 되었다니..! 이제 맘놓고 써도 되는걸까하는 기대를 가지고 한번 테스트를 해보기로 마음먹었다.
테스트는 GeekCoders님의 블로그 글을 참고하여 진행했다.
GeekCoder님은 유니티 4.6.1 기준으로 테스트했고, 그 결과 For문이 2.2배이상 빠른 것으로 나타났고, Foreach는 GC도 24B정도 남겼다.
Test 1. 프로파일러 모니터링
GeekCoder님의 코드를 그대로 사용했다.
ForUpdate.cs
public class ForUpdate : MonoBehaviour {
List<string> strs = new List<string>();
void Start () {
for (int i = 0; i < Sample.loopCount; i++) {
strs.Add (i.ToString ());
}
}
void Update () {
for (int i = 0; i < strs.Count; i++) {
string str = strs [i];
}
}
}
ForeachUpdate.cs
public class ForEachUpdate : MonoBehaviour {
List<string> strs = new List<string>();
void Start () {
for (int i = 0; i < Sample.loopCount; i++) {
strs.Add (i.ToString ());
}
}
void Update () {
foreach (string s in strs) {
string str = s;
}
}
}
EnumeratorUpdate.cs
public class EnumeratorUpdate : MonoBehaviour {
List<string> strs = new List<string>();
void Start () {
for (int i = 0; i < Sample.loopCount; i++) {
strs.Add (i.ToString ());
}
}
void Update () {
var enumerator = strs.GetEnumerator ();
while (enumerator.MoveNext ()) {
string str = enumerator.Current;
}
}
}
Sample.cs
public class Sample : MonoBehaviour {
public const int loopCount = 100000;
void Start()
{
this.gameObject.AddComponent<ForUpdate> ();
this.gameObject.AddComponent<ForEachUpdate> ();
this.gameObject.AddComponent<EnumeratorUpdate> ();
}
}
결과
For문이 Foreach 보다 약 1.8배 빠른 것으로 나타났다. GeekCoders님의 테스트에서 나타난 2.2배보다 약간 빨라졌다고 하지만 크게 성능이 개선되었다고 볼 수는 없다.
다만 GC를 남기지 않은건 큰 의미가 있다고 본다. 성능 이슈면에서 크게 문제가 되지 않는다면 부분적으로 활용해도 될듯하다.
Test 2. ElapsedTime 테스트
Test 2는 단순히 1억번 실행했을 때 시간이 얼마나 걸리는 지를 테스트해봤다.
Sample2.cs
public class Sample2 : MonoBehaviour {
const int loopCount = 100000000;
List<string> strs = new List<string>();
void Start () {
for (int i = 0; i < Sample2.loopCount; i++) {
strs.Add (i.ToString ());
}
System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew ();
//warmup
ForLoop ();
ForEachLoop ();
EnumeratorLoop ();
//ForLoop()
sw.Reset ();
sw.Start ();
ForLoop ();
sw.Stop ();
Debug.Log (string.Format ("ForLoop() : {0}", sw.ElapsedMilliseconds));
//ForEachLoop()
sw.Reset ();
sw.Start ();
ForEachLoop ();
sw.Stop ();
Debug.Log (string.Format ("ForEachLoop() : {0}", sw.ElapsedMilliseconds));
//EnumeratorLoop()
sw.Reset ();
sw.Start ();
EnumeratorLoop ();
sw.Stop ();
Debug.Log (string.Format ("EnumeratorLoop() : {0}", sw.ElapsedMilliseconds));
}
void ForLoop(){
for (int i = 0; i < strs.Count; i++) {
string str = strs [i];
}
}
void ForEachLoop(){
foreach (string s in strs) {
string str = s;
}
}
void EnumeratorLoop(){
var enumerator = strs.GetEnumerator ();
while (enumerator.MoveNext ()) {
string str = enumerator.Current;
}
}
}
결과
For문이 Foreach 보다 약 1.7배 빠른 것으로 나타났다. 테스트1의 결과랑 거의 비슷하다.
모노나 닷넷 쪽 지식은 거의 전무하기 때문에 결론을 제시할 수는 없지만 결과만 참고하면 좋을듯하다.
'아카이빙 > C#' 카테고리의 다른 글
[C#] this() 생성자 (0) | 2018.06.18 |
---|---|
[C#] 얕은 복사와 깊은 복사 (0) | 2018.06.18 |
[C#] static 필드와 메소드 (0) | 2018.06.18 |
[C#] FieldInfo와 PropertyInfo (0) | 2017.05.06 |
[C#] Activator.CreateInstance와 new 차이 (4) | 2017.04.15 |