[心情] 💢 分享一段性能只有原生1/15的addons
void Tools::Upxcore(Handle<Value>& value,std::string& str){
if(value->IsArray()){
str += "[";
Array* arr = Array::Cast(*value);
int len = arr->Length();
for( int a = 0; a < len; a = a + 1 )
{
Handle<Value>nvalue = arr->Get(a);
Upxcore(nvalue,str);
if(a != len-1){
str += ',';
}
}
str +="]";
}else if(value->IsObject()){
str += "{";
Local<Object> obj = value->ToObject();
Local<Array> key_arr = obj->GetPropertyNames();
int len = key_arr->Length();
for( int a = 0; a < len; a = a + 1 )
{
Handle<Value>nkey = key_arr->Get(a);
Handle<Value>nvalue = obj->Get(nkey);
Upxcore(nkey,str);
str += ":";
Upxcore(nvalue,str);
if(a != len-1){
str += ',';
}
}
str += "}";
}else if(value->IsString()){
String::Utf8Value keyUtf8Value(value);
std::string keyString = std::string(*keyUtf8Value);
str += "\""+keyString+"\"";
}
return;
}
看到这段代码的时候我已经在改汇编了- -
7 回复
这样的代码,效率高就奇怪了,问题出在str+上面,这样做字符串拷贝神仙也救不了啊,无谓的内存分配,内存拷贝。 为了说明低效的原因,我们假设str一开始预分配了16字节的内存,往里面加内容,加到超过16字节,再分配一个32字节的,将原来的那个拷贝过来,继续往里面加,再超过,再分配48字节,继续拷贝原来的,如此循环下去,碰到不够的地方就要做无谓的内存分配,释放和拷贝,这样的程序效率能高么?
你这种情况简单的优化是估算出字符串大小,然后直接分配一个大内存,直接往里拷贝数据,这样就避免的无谓的内存分配,释放和拷贝。C++虽然效率很高,但是内存分配和拷贝代价是很大的,CPU的运算速度是访问内存速度的10几倍啊。
能用原生的就不要自己造了,方法不对,汇编也救不了你。
@MiguelValentine 建议先看下v8的string_builder实现
他的内存开始是32字节,然后每次翻倍,还做个分块处理,每块最大16×1024
源代码下无秘密,自己实现一个string_builder效率就上去了。但还是建议用原生的,原生的考虑的比较周全,尤其在安全上面。原生的也基本都是C++代码了,效率上可提升的有限。学原理玩玩可以,工程上还是现实点。
你蛮喜欢折腾的嘛,我现在有个自己的项目,lua和libuv实现形式同步,有兴趣可以来一起完善,交流。