2011-02-04 34 views
16

Tengo este proyecto, llamado Memcached.Js, que es un puerto del servidor de Memcached para Node.js.Buffer vs String speed: ¿Por qué String es más rápido?

He estado jugando arround con cadenas y buffers, comparando la memoria de la huella y el rendimiento. Para la memoria, no hay dudas de que el buffer es la elección correcta.

Pero para mi sorpresa lo mismo no es cierto para el rendimiento. Realizar la manipulación de cadenas es más rápido que usar el buffer. Esto es lo que he intentado:

// Option 1: data.toString() - amazing, but it's the best one 
var commandDataStr = mdata.data.toString().substr(startPos, bytes); 
var commandData = new Buffer(commandDataStr); 

// Option 2: data.slice().toString() - the same as above... What? 
var commandDataStr = mdata.data.slice(startPos, startPos + bytes).toString(); 
var commandData = new Buffer(commandDataStr); 

// Option 3: data.slice() - bad 
var commandData = mdata.data.slice(startPos, startPos + bytes); 

// Option 4: data.copy() - bad as well 
var commandData = new Buffer(bytes); 
mdata.data.copy(commandData, 0, startPos, startPos + bytes); 

El código completo está aquí: https://github.com/dalssoft/memcached.js/blob/master/lib/memcached.ascii.commands.js#L72

Prueba el código: ruby test/from_clients/perf_test.rb

Las pruebas mostraron que las cadenas son más rápidos que búfer. Dado que no es lo que esperaba, creo que probablemente estoy haciendo algo mal, pero no puedo encontrar exactamente lo que es.

¿Alguien me puede ayudar aquí?

¡Tks!

+0

¿Puede reproducir el comportamiento de la velocidad con un pequeño caso de prueba? Si es así, envía un informe de error. – btilly

+0

Estoy revisando el rendimiento con este script: https://github.com/dalssoft/memcached.js/blob/master/test/from_clients/perf_test.rb –

Respuesta

21

Las cadenas están incorporadas en V8 y asignan memoria dentro de la máquina virtual. Los búferes se agregaron para no hacer todas las operaciones de cadena más rápidas, sino para representar datos binarios, mientras que las cadenas son unicode.

Al escribir grandes cantidades de datos en un socket, es mucho más eficiente tener esos datos en formato binario, frente a tener que convertir de unicode.

Por lo tanto, para operaciones comunes, como concat, no me sorprende que las cadenas sean más rápidas.

13

Buffer.slice es caro en el nodo. He encontrado que el patrón:

buffer.slice(start, end).toString(encoding) 

era más de 10 veces más lento que el patrón:

buffer.toString(encoding, start, end) 

A pesar de que la rebanada no asigna ningún nuevo buffer, parece incurrir en un costo significativo . Desde una mirada superficial al código, supongo que al exponer el búfer asignado externamente a v8 (a través de SetIndexedPropertiesToExternalArrayData) hace que tenga que actualizar el código generado para el objeto de búfer.

Una vez creados (o en rodajas), los búferes parecen rápidos. Por lo tanto, la creación de buffers más grandes en lugar de muchos pequeños, y la reutilización cuando sea posible parece una estrategia razonable para el rendimiento.

Más pensamientos sobre esto: http://geochap.wordpress.com/2011/05/03/node-buffers/

Cuestiones relacionadas