Local<Value>iterator_to_value(Isolate* isolate, const bson_iter_t* iter){ switch (bson_iter_type(iter)) { case BSON_TYPE_INT32: return Number::New(isolate, bson_iter_int32(iter)); break; case BSON_TYPE_INT64: return Number::New(isolate, bson_iter_int64(iter)); break; case BSON_TYPE_DOUBLE: return Number::New(isolate, bson_iter_double(iter)); break; case BSON_TYPE_DOCUMENT: { bson_iter_t sub_iter; bson_iter_recurse(iter, &sub_iter);
Local<Object> obj = Object::New(isolate); while (bson_iter_next(&sub_iter)) { const char* key = bson_iter_key(&sub_iter);
obj->Set( String::NewFromUtf8(isolate, key), iterator_to_value(isolate, &sub_iter) ); }
return obj; } break; case BSON_TYPE_ARRAY: { bson_iter_t sub_iter; uint32_t length; const uint8_t* array_data;
bson_iter_array(iter, &length, &array_data); bson_iter_recurse(iter, &sub_iter);
Local<Array> array = Array::New(isolate); int i = 0;
while (bson_iter_next(&sub_iter)) { array->Set(i++, iterator_to_value(isolate, &sub_iter)); }
return array; } break; case BSON_TYPE_OID: { const bson_oid_t* oid = bson_iter_oid(iter); char oid_buffer[25];
bson_oid_to_string(oid, oid_buffer);
return String::NewFromOneByte(isolate, (uint8_t*)oid_buffer); } break; case BSON_TYPE_UTF8: { uint32_t length; return String::NewFromUtf8(isolate, bson_iter_utf8(iter, &length)); } break; }
return Null(isolate); }
Local<Value>fill_object(Isolate* isolate, Local<Object>& obj, const bson_t* document){ bson_iter_t iter; if (bson_iter_init(&iter, document)) { while (bson_iter_next(&iter)) { const char* key = bson_iter_key(&iter);
obj->Set( String::NewFromUtf8(isolate, key), iterator_to_value(isolate, &iter) ); } }
return obj;}var array = [];for (var i = 0; i < 25000; ++i){ array.push({ "_id": { "$oid": "5a00bad8f759511811e030ba" }, "attributes": [ { "key": "smartshape.scene.node.path|default", "value": "/scene/Lot444.scene", "type": "imported" }, { "key": "max x", "value": 196.5773162841797, "type": "computed" }, { "key": "max y", "value": 18.55002021789551, "type": "computed" }, { "key": "max z", "value": 22.87815856933594, "type": "computed" }, { "key": "min x", "value": 149.9346771240234, "type": "computed" }, { "key": "min y", "value": 18.54999732971191, "type": "computed" }, { "key": "min z", "value": -23.35353088378906, "type": "computed" }, { "key": "box radius", "value": 23.32131958007814, "type": "computed" }, { "key": "center x", "value": 173.25599670410156, "type": "computed" }, { "key": "center y", "value": 18.55000877380371, "type": "computed" }, { "key": "center z", "value": -0.23768615722655895, "type": "computed" }, { "key": "width", "value": 46.64263916015628, "type": "computed" }, { "key": "height", "value": 2.2888183600855427e-05, "type": "computed" }, { "key": "depth", "value": 46.231689453125, "type": "computed" }, { "key": "box volume", "value": 0.04935534689932106, "type": "computed" }, { "key": "box surface", "value": 4312.740269302394, "type": "computed" } ], "name": "default1161", "uuid": "70bf7d72-1fa9-5c8f-21ff-03ef209d4404", "surfaces": [ "6f5201a2-31a7-14d0-6b2a-5130007d2a51" ], "aabb": [ 196.5773162841797, 18.55002021789551, 22.87815856933594, 149.9346771240234, 18.54999732971191, -23.35353088378906 ], "position": null, "scale": null, "rotation": null, "parents": [ "18497b66-3f32-6e98-1899-2998203e6397", null ], "file": "5a00b9a4aa5d2517d32d03da", "numChildren": 0, "sceneTreeIndices": [ 0 ] });}--
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups "v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
var array = [];var input = { "_id": { "$oid": "5a00bad8f759511811e030ba" },};
function process(value) { if (typeof value === "number") { return value; } else if (typeof value === "string") { return value; } else if (Array.isArray(value)) { var array = [];
for (var item of value) { array.push(process(item)); }
return array; } else if (typeof value === "object") {
if (!value) { return value; }
var obj = {}; for (var key of Object.keys(value)) { obj[key] = process(value[key]); }
return obj; } else { return value; }
return value;}
for (var i = 0; i < 26000; ++i) { var obj = process(input);
array.push(obj);}
using a constructor function and just filling in the values should be faster than assembling them one property at a time.
Now it takes 30ms. That's still 5x faster than the native code.
You received this message because you are subscribed to a topic in the Google Groups "v8-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/v8-users/aVeevQcHJ2c/unsubscribe.
To unsubscribe from this group and all its topics, send an email to v8-users+unsubscribe@googlegroups.com.
voidgetter(Local<Name> property, const PropertyCallbackInfo<Value>& info){ Isolate* isolate = info.GetIsolate();
const bson_t* document = reinterpret_cast<bson_t*>(
info.This() ->Get(String::NewFromUtf8(isolate, "__bson_document_ptr")) ->ToInt32()->Value() );
char key[255]; property->ToString(isolate)->WriteUtf8(key, 255);
bson_iter_t iter; bson_iter_init(&iter, document); // FIXME: index the property so we don't have to find it bson_iter_find(&iter, key);
// FIXME: replace the accessor with the deserialized value
info.GetReturnValue().Set(iterator_to_value(isolate, &iter));}
Local<Value>fill_object(Isolate* isolate, Local<Object>& obj, const bson_t* document){ obj->Set( String::NewFromUtf8(isolate, "__bson_document_ptr"), Int32::New(isolate, reinterpret_cast<intptr_t>(document)) );
bson_iter_t iter; if (bson_iter_init(&iter, document)) { while (bson_iter_next(&iter)) { const char* key = bson_iter_key(&iter);
if (!obj->Has(String::NewFromUtf8(isolate, key)))
{ obj->SetAccessor( isolate->GetCurrentContext(), String::NewFromUtf8(isolate, key), &getter ); } }
}
}--
You received this message because you are subscribed to the Google Groups "v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+unsubscribe@googlegroups.com.
I assume you're storing references to the objects as Persistent?
You received this message because you are subscribed to a topic in the Google Groups "v8-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/v8-users/aVeevQcHJ2c/unsubscribe.
To unsubscribe from this group and all its topics, send an email to v8-users+unsubscribe@googlegroups.com.
I assume you're storing references to the objects as Persistent?Nope. You've got the whole code up there.So if I understand correctly:
- the objects I need to keep track of the lifecycle should be made Persistent ;
- all the other values can be set as Local ;
- I should set the weak callback using MakeWeak ;
- callback will be called when such object is GCed and I can free my C/C++ memory then.
Is that correct ?
Node offers a C++ Clss extention ObjectWrap
class BSONObject : public node::ObjectWrap
{
private:
bson_t* _bson;
public:
BSONObject(bson_t* bson, Local<ObjectTemplate> tpl) :
_bson(bson)
{
Local<Object> obj = tpl->NewInstance();
initialize(v8::Isolate::GetCurrent(), obj, bson);
Wrap(obj);
}
~BSONObject()
{
std::cout << "~BSONObject()" << std::endl;
bson_destroy(_bson);
}
static
Local<ObjectTemplate>
create_template(Isolate* isolate, const bson_t* document)
{
Local<ObjectTemplate> tpl = ObjectTemplate::New(isolate);
tpl->SetInternalFieldCount(1);
void
insert(const FunctionCallbackInfo<Value>& args)
{
Isolate* isolate = args.GetIsolate();
db->insert(
json_stringify(isolate, args[0]),
[&args, isolate](const bson_t* document)
{
if (!args[1]->IsUndefined())
{
Local<Function> callback = Local<Function>::Cast(args[1]);
Local<Object> obj = Object::New(isolate);
Local<Value> argv[] = { (new BSONObject(bson_copy(document)))->handle(isolate) };
callback->Call(isolate->GetCurrentContext()->Global(), 1, argv);
}
}
);
}
My assumption is that my test app terminates before the GC has a chance to run.To test this:
- I run node with the --expose-gc option
- I call global.gc() at the end of my test app
In this case, the destructor of my ObjectWrap is indeed called.So it seams the GC doesn't simply "collect everything" when the app terminates.Why is that?It sounds like a pretty bad things to do: some behaviors might expect the destructor to be called in order to close a socket, etc...