질문/조언팁/리소스 공유

array안에 데이터를 찾을때 보통 이런 방식을 만이들 씁니다.

 

$array = array('a', 'b', 'c')

if(in_array('a', $array)) ~~~

 

이렇게 많이들 사용 하시는데 이제 이렇게 쓰지 마세요.

 

array에 해당되는 변수를 직접 설정이 가능하고, 비교할 부분이 in_array 일 경우 Lookup Table 을 만드는 것이 훨신 빠릅니다.

 

lookup테이블이랑 array배열 속 key값과 value 값이 동시에 존재하는 배열을 뜻합니다.

 

이 룩업테이블을 만들지 않고 in_array를 사용한다면 해당 배열속에 있는 데이터들을 모두 찾아보느라 실제로 많이 느려질 수 밖에 없습니다. 다양한 타입으로 여러방면으로 검사하게 되거든요.

 

하지만 in_array를 거치지 않고 똑같이 다음과 같이 구현하면 아주 쉽습니다.

 

위에처럼 $array 값의 키가 없이 지정하는 것보다 lookup테이블을 만들면 아주 간단해집니다.

 

$array = array(

'a' => true,

'b' => true,

'c' => true

);

$stringKey = 'a';

 

if($array[$stringKey])

 

이렇게 사용할 수 있습니다. true, 혹은 null이므로 값이 있을 경우 해당 if문 안으로 들어가게 되겟지요. 여기서 $stringKey값이 가변으로 변한다면요.

 

XE에서 다음과 같이 활용이 가능합니다.

 

붙여넣은_이미지_2021_7_20_오후_6_29.png

 

triggerAfterContentView 라는 메소드는 moduleObject.proc 의 after트리거를 호출하는 메소드입니다.

$oModule->act 라는 곳은 현재 실행되는 action 값이 호출되는데요 disp로시작하거나 proc으로 시작되는 값들이 "문자열"로 나오게 됩니다.

 

위의 코드에서 특정 액션(글읽기 글쓰기)에서만 해당 메소드를 실행하고 싶을때 보통은 이렇게 다들 쓰실겁니다.

if(is_array($oModule->act) && in_array($oModule->act, $enable_action))

 

근데 이렇게 쓰신다면 $enable_action 에 할당되는 메모리 + in_array에서 비교를 위해 사용되는 메모리에 비교 if연산자에 성능이 매우 느립니다.

 

붙여넣은_이미지_2021_7_20_오후_6_39.png

 

다음과 같은 코드를 만들었는데 10000 번정도 반복하니 별로 둘의 성능이 비교가 안되더군요.

 

그래서 1000000 번으로 늘려서 테스트해봤습니다.

 

붙여넣은_이미지_2021_7_20_오후_6_41.png

 

in_array보다 lookup_table 만드는 것이 거의 3배 가까이 평균적으로 더 빠릅니다.

 

즉, 데이터가 방대한 $output->data 쿼리 이후 비교문을 만들경우 왼만하면 $lookup_Table 만들어서 in_array() 보단 실제로 index를 가져오는게 더 빠르다는 것입니다.

 

이게 왜 이렇게 빠르냐면 위에 설명 드렸다 시피 in_array는 비교할때 내부적으로도 이게 어떤 타입의 데이터인지 C언어에서 여러 if else 거치면서 검사하지만 lookup테이블은 그냥 어딘가 메모리에 저장해둔 테이블에서 특정 키값을 콕 집어 가져오기 때문입니다. 그리고 C나 C++에서 반복문 안에 if문 쓰지말라는 말이 있을 정도록 if문 자체가 애초에 좀 느립니다.

(실제 PHP의 C언어 코드에서 in_array처리할때 코드 https://github.com/php/php-src/blob/master/ext/standard/array.c#L1496 게다가 모든 데이터중에 해다 값이 있는지 찾아볼려고 ZEND_HASH_FOREACH_KEY_VAL 라는 코드로 반복문을...ㄷ )

 

그래서 보통 게임 랜더링 엔지니어들은 lookup테이블을 많이 쓰라고 권고 합니다.

 

다만 스위치문도 lookup테이블을 만들 수 있는데 스위치문에서는 lookup테이블을 쓰지말고 그냥 스위치문 쓰시는게 더 빠릅니다.

 

붙여넣은_이미지_2021_7_20_오후_6_50.png

위 함수와 아래 함수는 모든 동작이 100프로 일치하는 코드입니다.

 

이 경우 똑같이 두개의 동작은 똑같지만 성능을 본다면 lookup테이블으로 호출하는것이 약 0.25배 느립니다.

 

붙여넣은_이미지_2021_7_20_오후_6_56.png

 

똑같은 비교방법으로 테스트할 때 결과값이 이렇게 나왔습니다.

 

따라서 일반 배열안에서 in_array는 룩업테이블 만들어서 쓰시고, 스위치문을 쓰실땐 스위치문 쓰세요.

 

아마 스위치문이 자체적으로 C내에서 lookup table 만들어서 실행되는게 아닌가 생각합니다.

 

실제로 C++에서 최적화 하는 방법에서 lookup테이블 없이 swtich 문을 사용한다면 성능이 좋다는 이야기가 많이 있습니다.

 

이 문서 참고해서 다들 좋은 코드들이 양성되었으면 좋겠네요!!

글쓴이 람보

profile
람보입니다.

Email : [email protected]

포트폴리오 : https://bjrambo.com/portfolio
작업의뢰 신청 : https://bjrambo.com/request
  • profile

    추가 결과값

     

    붙여넣은_이미지_2021_7_20_오후_7_16.png

     

    제일 마지막에 테스트한 코드에서 만약 key값이 없는 다른 문자열을 입력하여 넣을경우 속도가 또 다르게 나타나네요.

     

    isset영향을 약간 포함하여 0.25초 추가됬다고 판단해보면 0.235초로 증가한 속도값을 생각해본다면 약간 switch 에 병목이 훨신 좀 클 수 있다는 생각이 듭니다.

  • profile
    감사합니다.
    공부하는데 많은 도움을 받습니다.