Haszowanie stringa

13 kwietnia 2008

Haszowanie stringów z wykorzystaniem prostego algorytmu Roberta Sedgwicks z książki „Algorithms in C”.
Według testów różnych prostych algorytmów opublikowanych na stronie Hash Function Efficiency, można zauważyć ze właśnie RS jest prostym i małokolizyjnym algorytmem.

Dlatego właśnie go wybrałem do użycia w swoim projekcie, do haszowania nazw funkcji serwisowych eventów, hooków.

Implementacja w C++:

unsigned int RSHash(char* str) {
	unsigned int a = 63689;
	unsigned int b = 378551;
	unsigned int hash = 0;
 
	while (*str) {
		hash = hash * a + static_cast<unsigned char>(*str);
		a = a * b;
		str++;
	}
 
	return hash;
}

W źródłach mirandy, użyty przez nią algorytm znalazłem w wersji C i Asemblera, więc naszła mnie mała ochota, aby mój algorytm również nieco zoptymalizować i przy okazji przypomnieć sobie bebechy asemblera ;)

Tak też zrobiłem i wygenerowany asm przez g++ bez flag optymalizacyjnych doprowadziłem do postaci:

xor	eax, eax
mov	ebx, 63689
mov	esi, [ebp+8]
hL:
imul	eax, ebx
movzx	edx, BYTE PTR [esi]
add	eax, edx
imul	ebx, 378551
inc	esi
cmp	BYTE PTR [esi], 0
jg	hL

Efekt ciekawy, ale założyłem ze str jest różny od NULL, aby nieco ułatwić sprawę i pozbyć się kilku „nadmiarowych” poleceń i skoków.

G++ się postarał z optymalizacją, do porównania wersja z flagą O2:

push	ebx
mov	ecx, DWORD PTR [ebp+8]
mov	ebx, 63689
jmp	L7
.p2align 4,,7
L9:
imul	edx, ebx
movzx	eax, al
imul	ebx, ebx, 378551
inc	ecx
add	edx, eax
L7:
movzx	eax, BYTE PTR [ecx]
test	al, al
jne	L9
pop	ebx
mov	eax, edx

Przy okazji poruszając temat STLa, standard zaleca w make_pair przekazywać elementy przez referencje, a kochane gcc wspomina o tym, ale „robi” przez wartość ;)

Przez co proste dodanie elementu do mapa z wykorzystaniem make_pair w postaci:

std::pair<my_map_type::iterator, bool> ret = my_map.insert(std::make_pair(key, value));

doprowadziło do 4-krotnego kopiowania obiektu.

Zmiana na:

std::pair<my_map_type::iterator, bool> ret = my_map.insert(my_map_type::value_type(key, value));

zredukowała kopiowanie do 2.

Jak to ładnie ktoś rozwinął na pl.comp.lang.c skrót STL do Slow Template Library ;)

Dodano @ 20:49:34

Poprawiłem jeszcze swój kod, porównując go do zoptymalizowanej wersji z gcc. Powinien teraz być wydajniejszy i formalnie poprawniejszy ;)

xor	eax, eax
mov	ebx, 63689
mov	ecx, 378551
mov	esi, DWORD PTR [ebp+8]
jmp	C
L:
imul	eax, ebx
add	eax, edx
imul	ebx, ecx
inc	esi
C:
movzx	edx, BYTE PTR [esi]
test	edx, edx
jnz	L
; porownywanie
test	rej, rej
; jest szybsze od
cmp	rej, 0

W porównaniu do wersji gcc, w pętli mamy 1 instrukcje mniej, oraz wrzuciliśmy do rejestru wartość stałej b, co powinno przyśpieszyć działanie, bo w pętli procesor operuje na samych rejestrach ;)

Podobne notatki:

Może zainteresują Cię również następujące, pododbne notatki:

Nikt jeszcze nie skomentował tego wpisu.
Możesz być pierwszy.

Dodaj swój komentarz

Możesz użyć tych tagów XHTML-a: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Jeśli chcesz wstawić kilku linijkowy fragment kodu, użyj tagów <pre lang="x"></pre> (gdzie x język kodu np. cpp, perl, html). W ten sposób kod zostanie odpowiednio sformatowany i pokolorowany przez system.

Uwaga!

Na tym blogu działa system cache oraz filtr antyspamowy. Twój komentarz może być widoczny na stronie z pewnym opóźnieniem. Proszę o cierpliwość. Jeśli utraciłeś już wszystkie jej zasoby poinformuj mnie o tym, być może system uznał Cię za spamera ;)