equals 2개
Post
null 체크를 하기위해서 다양한 방법들을 알아보았습니다.
그러던 중 신기한 것을 발견하였죠.
바로 같은역할을 하는 친구들이 모두 속도가 다르단 것입니다!
is, Equals ,==
(ReferenceEquals의 경우에는 is와 속도가 거의 같아서 is로 대체하였습니다.)
테스트 코드
void Start()
{
Stopwatch sw = new Stopwatch();
sw.Start();
Test test1= TestClass1;
for (int i=0;i<100000000;i++)
{
if ( test1 == null);
}
sw.Stop();
UnityEngine.Debug.Log("Object == null : " + sw.Elapsed);
}
일단 앞선 게시물에서 is가 ==보다는 왜 빠른지 알았습니다.
근데 Equals(object,object).. 이 친구는 ==보다는 빠른데, is보다는 느립니다..
어떤 원리일까요? 좀 더 안전하게 속도를 빨리 할 수 있는걸까요?
일단 FakeNull을 체크할 수 있는 지 확인해봅시다.
IEnumerator Start()
{
GameObject test = new GameObject();
yield return null;
Destroy(test);
yield return null;
Debug.Log("UnityEngine Null check : " + NullCheckUnityEngine(test));
Debug.Log("System Null check : " + NullCheckSystem(test));
}
string NullCheckUnityEngine(Object obj)
{
if (obj == null)
return "true";
else
return "false";
}
string NullCheckSystem(object obj)
{
if (obj == null)
return "true";
else
return "false";
}
일단, ==은 fake null체크를 진행합니다. 그 결과 true, false로 나오죠.
Equals(,)의 경우에는 어떨까요?
IEnumerator Start()
{
GameObject test = new GameObject();
yield return null;
Destroy(test);
yield return null;
Debug.Log("UnityEngine Null check : " + NullCheckUnityEngine(test));
Debug.Log("System Null check : " + NullCheckSystem(test));
}
string NullCheckUnityEngine(Object obj)
{
if (Equals(obj, null))
return "true";
else
return "false";
}
string NullCheckSystem(object obj)
{
if (Equals(obj, null))
return "true";
else
return "false";
}
이런.. fake null까지 체크하진 않군요.
실제 찾아보니 ==의 경우에는 UnityEngine.Object와 정의가 연결되어 있고
Equals나 ReferenceEquals 등 fakenull 을 체크하지 않는 친구들은 System.Object에 정의되어있습니다.
Equals(object, null)같은 경우는 fakenull을 체크하지 않아 연산에서 좀 더 시간이 빠르단걸 알게되었습니다.
그럼 왜 is나 ReferenceEquals보다는 느린걸까요??
둘다 시스템 상 null만 체크하는건 동일하지만
Reference.Equals(object, object)의 경우에는 두 개체의 참조만을 비교합니다.
참조만을 비교하니 서로 가리키는 것이 무엇인지만 파악하면 되기에 속도가 빠른것같습니다.
object is null의 경우에는 상수 또는 Null만을 비교함으로써
두가지의 경우만 있기에 좀 더 속도가 빠르게 진행되는것같습니다.
Equals(object,null) 의 경우에는 두개의 값 모두 null인지를 먼저 체크 한 다음에 값의 비교를 진행합니다
null인지도 체크하고, 그 다음에 값이 같은지까지 체크하니 좀 더 속도가 걸리는것같습니다.
그래서 결론적으로 속도차이는
object.Reference.Equals(object,null) = object is null > Equals(object,null) > object == null
이렇게 결론이 나게됩니다.
자세한 함수의 코드는 잘 모르지만 나와있는 문서의 정보라던가 사람들의 이야기를 들어보고 정리한 결과,
해당 함수가 어떤 기능을 수행하는지를 알게되어 속도가 왜 차이가 나는지에 대해서도 어느정도 이해가 되었습니다.
하지만 무조건 제 말이 옳은건 아닙니다.
저도 단지 원리를 보고 파악하는것이기때문에 피드백이 있다면 언제든지 환영입니다!
이걸로 null에 대한 여정 끝!
참고자료
https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/operators/is
'STUDY > 유니티' 카테고리의 다른 글
[C#] null을 비교하기위한 여정2, is 와 FakeNull (0) | 2023.01.21 |
---|---|
[C#] null을 비교하기위한 여정1, ==와 Equals() (0) | 2023.01.18 |
[Unity] 메지카복셀에서 내가 만든 캐릭터 유니티로 불러오기 (0) | 2022.09.10 |
[Unity] C# 문자열보간 (0) | 2022.08.02 |
[UniRx] UniRx에 대해서 알아보기 (0) | 2022.08.02 |
Post
if (instance == null)
{
instance = this;
}
else if (instance != this)
Destroy(gameObject);
싱글톤 코드를 작성하면서 들었던 의문이 있었습니다.
==대신에 Equals()를 써서 null인지를 체크할 수는 없을까?
Equals로 인한 비교는 총 두가지 방법이 있습니다.
매개변수를 1개 쓰는것과 2개쓰는것
신기하게도
instance.Equals(null)를 쓰면 에러가 뜨지만
Equals(instance,null)을 쓰면 에러가 뜨지 않았습니다.
이유는 일단 instance는 null인 상태입니다.
그리고 그 null인 instance를 참조할려고하니 NullReferenceException 오류가 뜨는건 당연했죠.
하지만 instance.Equals(null)은 Null인 오브젝트의 값을 확인한다음,
매개변수의 값을 비교해야하기때문에 NULL값을 참조할려고해서 바로 에러가 뜨는거였고
Equals(instance,null)같은 경우는 마이크로소프트 .NET7 설명서에 따르면
매개변수 두개 다 NULL일경우 TRUE를 반환하여 오류가 발생하지 않는것이었습니다.
그렇다면 매개변수를 하나만 쓰는 Equals보다 매개변수 두개를 쓰는 Equals는
NULL값 참조라는 검증이 빠지기때문에 좀 더 빠르지 않을까? 란 생각이 들었습니다.
바로 검증해보죠
void Start()
{
Stopwatch sw = new Stopwatch();
sw.Start();
Test test1= TestClass1;
Test test2= TestClass1;
for (int i=0;i<100000000;i++)
{
if (Equals(test1, test2));
}
sw.Stop();
UnityEngine.Debug.Log("Equals(object,object) : " + sw.Elapsed);
}
void Start()
{
Stopwatch sw = new Stopwatch();
sw.Start();
Test test1= TestClass1;
Test test2= TestClass1;
for (int i=0;i<100000000;i++)
{
if (test1.Equals(test2));
}
sw.Stop();
UnityEngine.Debug.Log("Object.Equals(object) : " + sw.Elapsed);
}
코드는 매개변수가 두개인 Equals함수와 매개변수가 하나인 Equals함수가
동작하는 시간을 재는 코드입니다.
예상과 동일하게 객체의 값을 참조하고 난 다음에 값을 비교하는것보다
두개의 객체를 한번에 올려놓고 비교하는것이 훨씬 더 빠릅니다.
물론 횟수자체를 많이하여 극단적이긴하지만
같은 기능을 수행한다면 Equals(object,object)가 훨씬 빠르단걸 알게되었습니다.
하지만, Null값을 참조한다는 경고를 하지 않는단건 분명 수행도중에 null이 되었을 경우
나도 모르게 그냥 넘어갈 수 있다는 점입니다. 이 점만 유의한다면 속도향상에 좋을것같습니다.
.
.
.
.
실제 Equals 코드가 어떻게 구현되어있고 다른지를 보지 못해서 아쉽지만,
== 대신 Equals(object,object)를 사용하여 null체크를 할 수 있고,
Equals(object,object)가 Object.Equals(object)보다 속도가 빠르단걸 알 수 있게되었습니다.
그리고 마지막에 ==을 이용해 똑같이 검증을 해본 결과, Equals(object,object)보다 속도가 느린것으로 나왔습니다.
최종적으로 Equals(object,object)> object==object > object.Equals(object)순으로
속도가 빠르네요.
이와 관련해서는 또 자료를 찾아본 뒤 글을 적도록하겠습니다.
'STUDY > 유니티' 카테고리의 다른 글
[C#] null을 비교하기위한 여정3, ==과 is 그리고 Equals(,) 속도 (1) | 2023.01.22 |
---|---|
[C#] null을 비교하기위한 여정2, is 와 FakeNull (0) | 2023.01.21 |
[Unity] 메지카복셀에서 내가 만든 캐릭터 유니티로 불러오기 (0) | 2022.09.10 |
[Unity] C# 문자열보간 (0) | 2022.08.02 |
[UniRx] UniRx에 대해서 알아보기 (0) | 2022.08.02 |