我有一个名为Memcached.Js的项目,它是Node.js的Memcached服务器端口。
我一直在玩字符串和缓冲区,比较内存占用和性能。对于内存,毫无疑问缓冲区是正确的选择。
但令我惊讶的是,表演的情况并非如此。执行字符串操作比使用缓冲区更快。这就是我试过的:
// 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);
完整的代码在这里: https://github.com/dalssoft/memcached.js/blob/master/lib/memcached.ascii.commands.js#L72
测试代码:ruby test/from_clients/perf_test.rb
测试显示字符串比缓冲区更快。因为它不是我所期待的,我想我可能做错了什么,但我找不到它究竟是什么。
有人可以帮我吗?
韩国社交协会!
答案 0 :(得分:24)
字符串内置于V8,并在VM中分配内存。添加缓冲区不是为了使所有字符串操作更快,而是表示二进制数据,其中字符串是unicode。
在向套接字写入大量数据时,以二进制格式提供数据效率要高得多,而不必从unicode转换。
所以对于常见的操作,比如concat,我并不感到惊讶。字符串更快。
答案 1 :(得分:13)
Buffer.slice在节点中很昂贵。我发现了这种模式:
buffer.slice(start, end).toString(encoding)
比模式慢10倍:
buffer.toString(encoding, start, end)
即使切片没有分配任何新的缓冲区,它似乎也会产生很大的成本。从粗略看一下代码,我的猜测是将外部分配的缓冲区暴露给v8(通过SetIndexedPropertiesToExternalArrayData)会导致它必须更新其生成的缓冲区对象代码。
创建(或切片)后,缓冲区似乎很快。因此,创建更大的缓冲区而不是许多小缓冲区,并在可能的情况下重用似乎是一种合理的性能策略。
对此有更多想法:http://geochap.wordpress.com/2011/05/03/node-buffers/