Skip to content

Commit fd8210f

Browse files
committed
Improve iterator by making the object templates just once
- also remove the use of 'auto'
1 parent d550b5c commit fd8210f

File tree

5 files changed

+81
-39
lines changed

5 files changed

+81
-39
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hashtable",
3-
"version": "0.4.3",
3+
"version": "0.5.0",
44
"description": "Native HashTable and ES6 compatible Map for Node.js",
55
"main": "./index.js",
66
"keywords": [

src/hashtable.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ void HashTable::init(Handle<Object> exports) {
1313
map_constructor->SetClassName(String::NewSymbol("NodeMap"));
1414
map_constructor->InstanceTemplate()->SetInternalFieldCount(1);
1515

16-
auto ht_prototype = ht_constructor->PrototypeTemplate();
16+
Local<ObjectTemplate> ht_prototype = ht_constructor->PrototypeTemplate();
1717
ht_prototype->Set("put", FunctionTemplate::New(Put)->GetFunction());
1818
ht_prototype->Set("get", FunctionTemplate::New(Get)->GetFunction());
1919
ht_prototype->Set("has", FunctionTemplate::New(Has)->GetFunction());
@@ -26,7 +26,7 @@ void HashTable::init(Handle<Object> exports) {
2626
ht_prototype->Set("max_load_factor", FunctionTemplate::New(MaxLoadFactor)->GetFunction());
2727
ht_prototype->Set("forEach", FunctionTemplate::New(ForEach)->GetFunction());
2828

29-
auto map_prototype = map_constructor->PrototypeTemplate();
29+
Local<ObjectTemplate> map_prototype = map_constructor->PrototypeTemplate();
3030
map_prototype->Set("set", FunctionTemplate::New(Put)->GetFunction());
3131
map_prototype->Set("get", FunctionTemplate::New(Get)->GetFunction());
3232
map_prototype->Set("has", FunctionTemplate::New(Has)->GetFunction());
@@ -42,14 +42,16 @@ void HashTable::init(Handle<Object> exports) {
4242

4343
exports->Set(String::NewSymbol("HashTable"), Persistent<Function>::New(ht_constructor->GetFunction()));
4444
exports->Set(String::NewSymbol("NodeMap"), Persistent<Function>::New(map_constructor->GetFunction()));
45+
46+
PairNodeIterator::init();
4547
}
4648

4749
HashTable::HashTable() {}
4850

4951
HashTable::HashTable(size_t buckets) : map(buckets) {}
5052

5153
HashTable::~HashTable() {
52-
for(auto itr = this->map.begin(); itr != this->map.end(); ) {
54+
for(MapType::const_iterator itr = this->map.begin(); itr != this->map.end(); ) {
5355
Persistent<Value> value = itr->second;
5456
value.Dispose();
5557

@@ -167,7 +169,7 @@ Handle<Value> HashTable::Keys(const Arguments& args) {
167169
Local<Array> array = Array::New();
168170

169171
int i = 0;
170-
for(auto itr = obj->map.begin(); itr != obj->map.end(); ++itr, ++i) {
172+
for(MapType::const_iterator itr = obj->map.begin(); itr != obj->map.end(); ++itr, ++i) {
171173
array->Set(Integer::New(i), itr->first);
172174
}
173175

@@ -179,7 +181,7 @@ Handle<Value> HashTable::MapEntries(const Arguments& args) {
179181

180182
HashTable *obj = ObjectWrap::Unwrap<HashTable>(args.This());
181183

182-
Local<Object> iter = PairNodeIterator::init(PairNodeIterator::KEY_TYPE | PairNodeIterator::VALUE_TYPE, obj->map.begin(), obj->map.end());
184+
Local<Object> iter = PairNodeIterator::New(PairNodeIterator::KEY_TYPE | PairNodeIterator::VALUE_TYPE, obj->map.begin(), obj->map.end());
183185

184186
return scope.Close(iter);
185187
}
@@ -189,7 +191,7 @@ Handle<Value> HashTable::MapKeys(const Arguments& args) {
189191

190192
HashTable *obj = ObjectWrap::Unwrap<HashTable>(args.This());
191193

192-
Local<Object> iter = PairNodeIterator::init(PairNodeIterator::KEY_TYPE, obj->map.begin(), obj->map.end());
194+
Local<Object> iter = PairNodeIterator::New(PairNodeIterator::KEY_TYPE, obj->map.begin(), obj->map.end());
193195

194196
return scope.Close(iter);
195197
}
@@ -199,7 +201,7 @@ Handle<Value> HashTable::MapValues(const Arguments& args) {
199201

200202
HashTable *obj = ObjectWrap::Unwrap<HashTable>(args.This());
201203

202-
Local<Object> iter = PairNodeIterator::init(PairNodeIterator::VALUE_TYPE, obj->map.begin(), obj->map.end());
204+
Local<Object> iter = PairNodeIterator::New(PairNodeIterator::VALUE_TYPE, obj->map.begin(), obj->map.end());
203205

204206
return scope.Close(iter);
205207
}
@@ -217,7 +219,7 @@ Handle<Value> HashTable::Remove(const Arguments& args) {
217219

218220
Persistent<Value> key = Persistent<Value>(args[0]);
219221

220-
auto itr = obj->map.find(key);
222+
MapType::const_iterator itr = obj->map.find(key);
221223

222224
if(itr == obj->map.end()) {
223225
return scope.Close(Boolean::New(false)); //do nothing and return false
@@ -236,7 +238,7 @@ Handle<Value> HashTable::Clear(const Arguments& args) {
236238

237239
HashTable *obj = ObjectWrap::Unwrap<HashTable>(args.This());
238240

239-
for(auto itr = obj->map.begin(); itr != obj->map.end(); ) {
241+
for(MapType::const_iterator itr = obj->map.begin(); itr != obj->map.end(); ) {
240242
Persistent<Value> value = itr->second;
241243
value.Dispose();
242244

src/iterator.cpp

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,63 @@
22
#include <iostream>
33

44
using namespace v8;
5+
static Persistent<FunctionTemplate> key_value_tmplt;
6+
static Persistent<FunctionTemplate> key_tmplt;
7+
static Persistent<FunctionTemplate> value_tmplt;
58

6-
Local<Object> PairNodeIterator::init(int type, MapType::iterator new_iter, MapType::iterator new_end) {
7-
Local<ObjectTemplate> tmplt = ObjectTemplate::New();
8-
tmplt->SetInternalFieldCount(1);
9+
void PairNodeIterator::init() {
10+
key_value_tmplt = Persistent<FunctionTemplate>::New(FunctionTemplate::New());
11+
key_tmplt = Persistent<FunctionTemplate>::New(FunctionTemplate::New());
12+
value_tmplt = Persistent<FunctionTemplate>::New(FunctionTemplate::New());
913

10-
PairNodeIterator *iter = new PairNodeIterator(new_iter, new_end);
14+
Handle<ObjectTemplate> key_value_obj_tmplt = key_value_tmplt->InstanceTemplate();
15+
Handle<ObjectTemplate> key_obj_tmplt = key_tmplt->InstanceTemplate();
16+
Handle<ObjectTemplate> value_obj_tmplt = value_tmplt->InstanceTemplate();
1117

12-
if (PairNodeIterator::KEY_TYPE & type) {
13-
tmplt->SetAccessor(String::New("key"), GetKey);
14-
}
18+
key_value_obj_tmplt->SetInternalFieldCount(1);
19+
key_obj_tmplt->SetInternalFieldCount(1);
20+
value_obj_tmplt->SetInternalFieldCount(1);
21+
22+
key_value_obj_tmplt->SetAccessor(String::New("key"), GetKey);
23+
key_obj_tmplt->SetAccessor(String::New("key"), GetKey);
24+
25+
key_value_obj_tmplt->SetAccessor(String::New("value"), GetValue);
26+
value_obj_tmplt->SetAccessor(String::New("value"), GetValue);
27+
28+
key_value_obj_tmplt->SetAccessor(String::New("done"), GetDone);
29+
key_obj_tmplt->SetAccessor(String::New("done"), GetDone);
30+
value_obj_tmplt->SetAccessor(String::New("done"), GetDone);
31+
32+
Local<ObjectTemplate> key_value_prototype = key_value_tmplt->PrototypeTemplate();
33+
Local<ObjectTemplate> key_prototype = key_tmplt->PrototypeTemplate();
34+
Local<ObjectTemplate> value_prototype = value_tmplt->PrototypeTemplate();
1535

16-
if (PairNodeIterator::VALUE_TYPE & type) {
17-
tmplt->SetAccessor(String::New("value"), GetValue);
36+
key_value_prototype->Set(String::New("next"), FunctionTemplate::New(Next)->GetFunction());
37+
key_prototype->Set(String::New("next"), FunctionTemplate::New(Next)->GetFunction());
38+
value_prototype->Set(String::New("next"), FunctionTemplate::New(Next)->GetFunction());
39+
}
40+
41+
Local<Object> PairNodeIterator::New(int type, MapType::const_iterator new_iter, MapType::const_iterator new_end) {
42+
HandleScope scope;
43+
44+
Handle<FunctionTemplate> tmplt;
45+
if ((PairNodeIterator::KEY_TYPE & type) && (PairNodeIterator::VALUE_TYPE & type)) {
46+
tmplt = key_value_tmplt;
47+
} else if (KEY_TYPE & type) {
48+
tmplt = key_tmplt;
49+
} else {
50+
tmplt = value_tmplt;
1851
}
1952

20-
tmplt->SetAccessor(String::New("done"), GetDone);
21-
tmplt->Set(String::New("next"), FunctionTemplate::New(Next)->GetFunction());
22-
Local<Object> obj = tmplt->NewInstance();
53+
Local<Object> obj = tmplt->InstanceTemplate()->NewInstance();
54+
PairNodeIterator *iter = new PairNodeIterator(new_iter, new_end);
2355

2456
iter->Wrap(obj);
25-
return obj;
57+
58+
return scope.Close(obj);
2659
}
2760

28-
PairNodeIterator::PairNodeIterator(MapType::iterator new_iter, MapType::iterator new_end) : iter(new_iter), end(new_end) {}
61+
PairNodeIterator::PairNodeIterator(MapType::const_iterator new_iter, MapType::const_iterator new_end) : iter(new_iter), end(new_end) {}
2962

3063

3164
// iterator.done : boolean

src/iterator.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,18 @@
88

99
class PairNodeIterator : public node::ObjectWrap {
1010
public:
11-
static v8::Local<v8::Object> init(int type, MapType::iterator new_iter, MapType::iterator new_end);
11+
static void init();
12+
static v8::Local<v8::Object> New(int type, MapType::const_iterator new_iter, MapType::const_iterator new_end);
1213

1314
const static int KEY_TYPE = 1;
1415
const static int VALUE_TYPE = 1 << 1;
1516

1617
private:
17-
PairNodeIterator(MapType::iterator new_iter, MapType::iterator new_end);
18+
PairNodeIterator(MapType::const_iterator new_iter, MapType::const_iterator new_end);
1819
//~PairNodeIterator();
1920

20-
MapType::iterator iter;
21-
MapType::iterator end;
21+
MapType::const_iterator iter;
22+
MapType::const_iterator end;
2223

2324
// iterator.done : boolean
2425
static v8::Handle<v8::Value> GetDone(v8::Local<v8::String> property, const v8::AccessorInfo &info);

test/comparison.js

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,17 +161,23 @@ var tests = [
161161
['raw insert and remove 50000', rawInsertAndRemove.bind(null, 50000)],
162162
['raw insert and find 10000', rawInsertAndFind.bind(null, 10000)],
163163
['raw insert and find 20000', rawInsertAndFind.bind(null, 20000)],
164-
['raw insert and find 50000', rawInsertAndFind.bind(null, 50000)],
165-
166-
['ES6 insert 10000', es6Insert.bind(null, 10000)],
167-
['ES6 insert 20000', es6Insert.bind(null, 20000)],
168-
['ES6 insert 50000', es6Insert.bind(null, 50000)],
169-
['ES6 insert and remove 10000', es6InsertAndRemove.bind(null, 10000)],
170-
['ES6 insert and remove 50000', es6InsertAndRemove.bind(null, 50000)],
171-
['ES6 insert and find 10000', es6InsertAndFind.bind(null, 10000)],
172-
['ES6 insert and find 20000', es6InsertAndFind.bind(null, 20000)],
173-
['ES6 insert and find 50000', es6InsertAndFind.bind(null, 50000)],
164+
['raw insert and find 50000', rawInsertAndFind.bind(null, 50000)]
165+
];
174166

167+
if (process.argv.length < 3 || process.argv[2] !== '--no-es6') {
168+
tests.push(
169+
['ES6 insert 10000', es6Insert.bind(null, 10000)],
170+
['ES6 insert 20000', es6Insert.bind(null, 20000)],
171+
['ES6 insert 50000', es6Insert.bind(null, 50000)],
172+
['ES6 insert and remove 10000', es6InsertAndRemove.bind(null, 10000)],
173+
['ES6 insert and remove 50000', es6InsertAndRemove.bind(null, 50000)],
174+
['ES6 insert and find 10000', es6InsertAndFind.bind(null, 10000)],
175+
['ES6 insert and find 20000', es6InsertAndFind.bind(null, 20000)],
176+
['ES6 insert and find 50000', es6InsertAndFind.bind(null, 50000)]
177+
);
178+
}
179+
180+
tests.push(
175181
['HashMap insert 10000', hashInsert.bind(null, 10000)],
176182
['HashMap insert 20000', hashInsert.bind(null, 20000)],
177183
['HashMap insert 50000', hashInsert.bind(null, 50000)],
@@ -180,7 +186,7 @@ var tests = [
180186
['HashMap insert and find 10000', hashInsertAndFind.bind(null, 10000)],
181187
['HashMap insert and find 20000', hashInsertAndFind.bind(null, 20000)],
182188
['HashMap insert and find 50000', hashInsertAndFind.bind(null, 50000)]
183-
];
189+
);
184190

185191
async.mapSeries(tests, function (params, cb) {
186192
return process.stdout.write('running ' + params[0] + ' tests', 'utf8', function () {

0 commit comments

Comments
 (0)