Подтвердить что ты не робот

Buffer vs String speed: Почему String быстрее?

У меня есть этот проект, называемый Memcached.Js, который является портом сервера Memcached для Node.js.

Я играл в arround со строками и буферами, сравнивая объем памяти и производительность памяти. Для памяти нет никаких сомнений в правильности выбора буфера.

Но для моего удивления то же самое не относится к performace. Выполнение строковых манипуляций выполняется быстрее, чем использование буфера. Это то, что я пробовал:

// Option 1: data.toString() - amazing, but it 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);

Полный код находится здесь: https://github.com/dalssoft/memcached.js/blob/master/lib/memcached.ascii.commands.js#L72

Тестирование кода: ruby test/from_clients/perf_test.rb

Тесты показали, что строки быстрее Buffer. Поскольку это не то, что я ожидал, я думаю, что, вероятно, я что-то делаю неправильно, но я не могу точно определить, что это такое.

Может ли кто-нибудь помочь мне здесь?

Tks!

4b9b3361

Ответ 1

Строки встроены в V8 и выделяют память внутри виртуальной машины. Буферы добавлены не для того, чтобы сделать все строковые операции быстрее, а для представления двоичных данных, где, поскольку строки являются юникодами.

При записи больших объемов данных в сокет гораздо эффективнее иметь эти данные в двоичном формате, а также конвертировать из unicode.

Итак, для обычных операций, таких как concat, я не удивлен, что строки быстрее.

Ответ 2

Buffer.slice стоит дорого в node. Я обнаружил, что шаблон:

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

было более чем в 10 раз медленнее, чем шаблон:

buffer.toString(encoding, start, end)

Хотя срез не выделяет никакого нового буфера, он, по-видимому, несет значительную стоимость. Из беглого взгляда на код, я предполагаю, что публикация внешнего выделенного буфера на v8 (через SetIndexedPropertiesToExternalArrayData) заставляет его обновлять свой сгенерированный код для объекта-буфера.

После создания (или нарезания) буферы кажутся быстрыми. Поэтому создание больших буферов вместо множества маленьких и повторное использование, когда это возможно, кажется разумной стратегией для производительности.

Другие мысли по этому поводу: http://geochap.wordpress.com/2011/05/03/node-buffers/