표준 라이브러리.. 따라잡기...
글쓴이: philossh / 작성시간: 일, 2005/08/21 - 12:47오후
int asmstrlen(const char* ch)
{
__asm
{
mov edi, dword ptr [ebp+8];
xor al, al;
mov ecx, -1;
repne scasb;
xor eax, eax;
mov eax, -2;
sub eax, ecx;
}
}
표준라이브러리의 strlen() 함수를 따라잡아보려고..
거의 모르는 어셈까지 써가며 해봤는데..
결과는 처참하네요..
(똑바로된 어셈을 작성할 능력이 없어서 그런지는 몰라도.. :oops:)
for루프를 약 1000만번 돌리니..
표준 : 약 250 ms
허접한어셈: 약 850 ms
아래처럼하면.. 약 2300 ms 정도..
int mystrlen(const char* ch)
{
int i=0;
while (*ch++) i++;
return i;
}
흠.. TC++PL 6장연습문제에서 한번 만들어봐라고 해서 만들어 봤다가..
흠.. 역시나.. 미숙한 나로서는..
책의 의도대로 표준라이브러리에 대한 의심을 버리는게.. 흐흐.. :roll:
Forums:


다음은 glibc 2.3.5의 코드입니다.[code:1]size_t
다음은 glibc 2.3.5의 코드입니다.
size_t strlen (const char *str) { int cnt; asm("cld\n" /* Search forward. */ /* Some old versions of gas need `repne' instead of `repnz'. */ "repnz\n" /* Look for a zero byte. */ "scasb" /* %0, %1, %3 */ : "=c" (cnt) : "D" (str), "0" (-1), "a" (0)); return -2 - cnt; }전 어셈을 잘 몰라서 정확히 해석할 순 없지만 i386에 서치하는 인스트럭션이 있는가봅니다
그것보다, strstr의 glibc 코드에는 다음과 같은 코멘트가 달려있죠.
흑흑
제가 간단히 아는 ㅇ명령어로만 해봤는데 결과가 아주 비참하군요!!
셀러론 1Ghz 입니다.
__declspec(naked) int mmojz_strlen(const char* s) { __asm { push ebp mov ebp, esp } __asm { push ecx push esi mov ecx, -1 mov esi, dword ptr[ebp+8]; cld l: lodsb inc ecx cmp al, 0 jne l mov eax, ecx pop esi pop ecx } __asm { pop ebp ret } } int mmojz2_strlen(const char* ch) { int i=0; while (*ch++) i++; return i; } int main() { unsigned int t; t = timeGetTime(); for(volatile unsigned int i=0; i<10000000; i++) { strlen("345349534583495834958589358938595"); } printf("라이브러리 : %d\n", timeGetTime()-t); t = timeGetTime(); for(volatile unsigned int i=0; i<10000000; i++) { mmojz_strlen("345349534583495834958589358938595"); } printf("허접 어셈 : %d\n", timeGetTime()-t); t = timeGetTime(); for(volatile unsigned int i=0; i<10000000; i++) { mmojz2_strlen("345349534583495834958589358938595"); } printf("C언어 : %d\n", timeGetTime()-t); return 0; }debug 버전에서는
라이브러리 : 1065
허접 어셈 : 2658
C언어 : 6016
Release 버전에서는
라이브러리 : 89
허접 어셈 : 2625
C언어 : 941
비참...
덧
은 Release 버전에서는 작동하지 않습니다. (.NET 2003 입니다.)
Re: 표준 라이브러리.. 따라잡기...
philossh 님께서 올리신 코드는 eungkyu 님께서 올리신 glibc 코드와 본질적으로 같은 의미 같습니다. 그런데도 속도 차이가 그렇게 난다면, 마이크로소프트에서 제공하는 구현이 무진장 효과적이거나-_- 아니면 외부적인 요인이 작용할 가능성이 높을 것 같네요. (호출 규약을 naked로 하는 것도 한 방법입니다만 저 정도로 차이가 난다면 좀...)
repnz scasb(또는 repne scasb)의 역할이 바로 그것입니다. 일반적으로 많은 메모리를 한꺼번에 초기화하거나, 특정한 값을 찾을 때는 rep 접두사를 쓰는 명령이 가장 빠를 것입니다. (한 명령으로 다 해 먹으니까) mmojz 님의 코드가 느릴 수 밖에 없는 것도 같은 이유죠.
...그냥 표준 라이브러리 그대로 쓰는 게 속 편하죠 암암 -_-;
- 토끼군
[code:1]int foo_strlen(const char* c
int foo_strlen(const char* c) { const char* p = c; while(*p++); return p-1-c; }조금은 나을꺼라고 생각하고 작성했는데 더 느리군요. :sad:
이 포스트의 의도대로 저에 대한 믿음을 버리는게.. 흐흐.. ㅠㅜ
댓글 달기