I switched to a Map which looks like it may have solved the issue. See this: https://jsperf.com/es6-map-vs-object-properties/
And, running Node.js --perf with the code from that jsperf yields the following (on Node v8.9.1 which, according to process.versions, is V8 6.1.534.47): *Map (15.7% in GC)* [Summary]: ticks total nonlib name 903 68.1% 68.4% JavaScript 395 29.8% 29.9% C++ 208 15.7% 15.7% GC 5 0.4% Shared libraries 23 1.7% Unaccounted [C++]: ticks total nonlib name 91 6.9% 6.9% t v8::internal::Scavenger::ScavengeObject(v8:: internal::HeapObject**, v8::internal::HeapObject*) 38 2.9% 2.9% t v8::internal::OrderedHashTable<v8::internal:: OrderedHashMap, 2>::Rehash(v8::internal::Handle<v8::internal::OrderedHashMap >, int) 36 2.7% 2.7% T v8::internal::Runtime_GenerateRandomNumbers(int, v8::internal::Object**, v8::internal::Isolate*) 36 2.7% 2.7% T v8::internal::IncrementalMarking::Step(unsigned long, v8::internal::IncrementalMarking::CompletionAction, v8::internal:: IncrementalMarking::ForceCompletionAction, v8::internal::StepOrigin) 30 2.3% 2.3% T v8::internal::Heap::Scavenge() 25 1.9% 1.9% T v8::internal::Heap::AllocateFixedArrayWithFiller( int, v8::internal::PretenureFlag, v8::internal::Object*) 24 1.8% 1.8% t node::(anonymous namespace)::ContextifyScript:: New(v8::FunctionCallbackInfo<v8::Value> const&) 14 1.1% 1.1% t v8::internal::(anonymous namespace):: GetSimpleHash(v8::internal::Object*) *Object (26.8% in GC)* [Summary]: ticks total nonlib name 698 32.2% 32.2% JavaScript 1417 65.3% 65.4% C++ 581 26.8% 26.8% GC 2 0.1% Shared libraries 53 2.4% Unaccounted [C++]: ticks total nonlib name 269 12.4% 12.4% T v8::internal::IncrementalMarking::Step(unsigned long, v8::internal::IncrementalMarking::CompletionAction, v8::internal:: IncrementalMarking::ForceCompletionAction, v8::internal::StepOrigin) 148 6.8% 6.8% t v8::internal::HashTable<v8::internal:: NameDictionary, v8::internal::NameDictionaryShape>::Rehash(v8::internal:: NameDictionary*) 122 5.6% 5.6% T v8::internal::Heap::Scavenge() 107 4.9% 4.9% t v8::internal::Scavenger::ScavengeObject(v8:: internal::HeapObject**, v8::internal::HeapObject*) 103 4.7% 4.8% T v8::internal::HashTable<v8::internal::StringTable , v8::internal::StringTableShape>::Rehash(v8::internal::StringTable*) 91 4.2% 4.2% T v8::internal::StringTable::LookupKey(v8::internal ::Isolate*, v8::internal::StringTableKey*) 82 3.8% 3.8% t v8::internal::LookupIterator::State v8::internal ::LookupIterator::LookupInRegularHolder<false>(v8::internal::Map*, v8:: internal::JSReceiver*) 48 2.2% 2.2% T v8::internal::Heap::AllocateFixedArrayWithFiller( int, v8::internal::PretenureFlag, v8::internal::Object*) 41 1.9% 1.9% T v8::internal::String::SlowEquals(v8::internal:: String*) If I plot out the actual duration of the add/update operation to either a Map or Object, they're both almost equivalent as N increases, but the memory usage and GC activity *around* that add/update for the Object is much higher. In fact, depending on the length of the random string being created, the Object often maxes out the heap and crashes Node.js. (I experimented with increasing --max_old_space_size up to 10000) There's also a point (random strings of length 5, with N of 8,000,000) where even if your heap is large enough to hold all the strings, the adding/appending to an Object just seizes up (and Map still works). On Thursday, November 23, 2017 at 12:59:06 AM UTC-8, Camillo Bruni wrote: > > Hi Jonathan, > > this seems suspicious. Would it be possible for you to write a standalone > repro? > Without further information it is hard to asses what exactly might be > going wrong here. > > Cheers, > Camillo > > On Wednesday, November 22, 2017 at 1:29:50 AM UTC+1, Jonathan Otto wrote: >> >> I have a plain JavaScript object that looks like: >> >> { >> sha256a: { id, fieldA, fieldB, fieldC }, >> sha256b: { id, fieldA, fieldB, fieldC }, >> ... >> } >> >> and it seems like when I get over ~50,000 sha's then I start to have high >> CPU usage (~3%) when adding a key or changing a value for an existing key - >> note I am adding/changing keys once or twice per second. Naively I'm >> wondering if the GC is traversing the entire object on each addition or >> change and whether there's a cliff where that falls off. >> >> Is there a better way to manage a local store in JavaScript? >> > -- -- v8-users mailing list v8-users@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+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.