2009-05-13 20 views
13

Si tengo una cadena inmutable, ¿se ejecuta el algoritmo hashing cada vez que llamo hash, o recuerda el valor (dado que la cadena no puede cambiar)?¿Se ha calculado [hash NSString] cada vez?

+1

Bueno, para responder con otra pregunta, ¿por qué te importa? Si le preocupa el rendimiento, es evidente que se está preocupando demasiado pronto, ya que no tiene ningún código para el perfil y descubrirlo por sí mismo. Además, si Apple no documenta este comportamiento, podría cambiar felizmente en el futuro, por lo que no debería confiar en él. –

+18

Quizás estuve interesado? – Ian1971

Respuesta

36

Se vuelve a calcular.

- [NSString hash] es, de hecho, una llamada a - [NSCFString hash] (debido al puente libre de peaje).

Si crea un programa que llama a [NSString hash] en la misma cadena y se intercala entre las llamadas y altera la memoria haciendo una copia de seguridad de la cadena, obtendrá un valor hash recalculado. Esto me dice que no hay almacenamiento en caché.

(gdb) b -[NSCFString hash] 
Breakpoint 1 at 0x3b02fa3 
(gdb) r 
Breakpoint 1, 0x93652fa3 in -[NSCFString hash]() 
(gdb) c 
Continuing. 
2009-05-13 14:23:39.003 a.out[1754:813] Hash: -327163326 

Tenga en cuenta el valor de hash.

Breakpoint 1, 0x93652fa3 in -[NSCFString hash]() 
(gdb) bt   
#0 0x93652fa3 in -[NSCFString hash]() 
#1 0x00001f73 in main() at test.m:10 
(gdb) fra 1 
#1 0x00001f73 in main() at test.m:10 
10  NSLog(@"Hash: %d", [m hash]); 
(gdb) info locals 
pool = (NSAutoreleasePool *) 0x109760 
m = (NSString *) 0x2030 
(gdb) x/20x 0x2030 
0x2030 <dyld__mach_header+32>: 0xa06f54a0 0x000007c8 0x00001fa2 0x00000012 

0xa06f54a0 es el puntero "ISA", 0x00001fa2 es un puntero a la cadena "XXXXXX".

(gdb) set {int}0x1fa2 = 0x59595959 

alteran la cadena "XXXXXX" a "YYYYXXXX", y luego continuar a la segunda llamada de hash

(gdb) c 
Continuing. 
2009-05-13 14:24:35.884 a.out[1754:813] Hash: -246144954 

Nota el valor hash que es diferente en la medida de lo ObjC sabe cadena inmutable.

El programa que he (de) molestó es:

#import <Cocoa/Cocoa.h> 

int main() 
{ 
    NSAutoreleasePool * pool = [NSAutoreleasePool new]; 

    NSString * m = [NSString stringWithString:@"XXXXXXXXXXXXXXXXXX"]; 

    NSLog(@"Hash: %d", [m hash]); 
    NSLog(@"Hash: %d", [m hash]); 

    [pool release]; 
} 
+0

respuesta increíble. Gracias – Ian1971

+0

Muy buena respuesta –

+11

Alternativamente, puede mirar el código fuente de CFStringRef aquí: http://opensource.apple.com/source/CF/CF-476.17/CFString.c Buscar 'CFHashCode __CFStringHash (CFTypeRef cf) 'para la función que se llama. Tenga en cuenta que (a) hace las cosas de manera diferente para los búferes de cadenas de 8 bits y Unicode, y (b) solo tiene hashes hasta un cierto número de caracteres (actualmente 96). Busque '/ * Hash de cadena:' para ver los detalles del algoritmo de hash (s). –

Cuestiones relacionadas