缓冲区(Buffer)与字符串(String)速度:为什么字符串更快?

24

我有一个项目,叫做Memcached.Js,这是将Memcached服务器移植到Node.js的版本。

我一直在比较字符串和缓冲区之间的内存占用和性能。对于内存来说,毫无疑问缓冲区是正确的选择。

但出乎我的意料,在性能方面并非如此。执行字符串操作要比使用缓冲区快。这是我尝试过的:

// 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
测试表明,字符串比缓冲区要快。我并没有预料到这点,所以我认为我可能做错了什么,但我无法确定具体是哪里错了。
有人能帮我吗?
谢谢!

你可以用一个小的测试案例重现这个速度问题吗?如果可以,那么请提交一个错误报告。 - btilly
我正在使用此脚本检查性能:https://github.com/dalssoft/memcached.js/blob/master/test/from_clients/perf_test.rb - David Lojudice Sb.
2个回答

32

字符串是内置于V8中的,它们在虚拟机内分配内存。缓冲区的添加并不是为了使所有字符串操作更快,而是为了表示二进制数据,而字符串是Unicode。

当向套接字写入大量数据时,将数据以二进制格式存储比从Unicode转换更有效率。

因此,对于常见操作(如连接),我并不惊讶字符串更快。


15

在Node中,使用Buffer.slice开销很大。我发现了这种模式:

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

比模式要慢10倍以上:

buffer.toString(encoding, start, end)

尽管slice不会分配新的缓冲区,但它似乎会产生显著的成本。从代码的粗略查看来看,我猜测通过SetIndexedPropertiesToExternalArrayData将外部分配的缓冲区暴露给v8会导致其必须更新缓冲区对象的生成代码。

一旦创建(或切片)缓冲区,它们就非常快。因此,创建更大的缓冲区而不是许多小缓冲区,并在可能时重复使用,似乎是一种合理的性能策略。

更多想法请见:http://geochap.wordpress.com/2011/05/03/node-buffers/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接