diff --git a/examples/example.js b/examples/example.js index 2977577..56e1de6 100644 --- a/examples/example.js +++ b/examples/example.js @@ -1,18 +1,22 @@ import Memory from '../src/memory.js' -const mem = new Memory({db:0}) +const mem = new Memory({db:0}) // no debounce -// let text -// mem.watch(console.log) - -mem.watch() +// mem.watch(console.dir) +// mem.watch() +mem.watch( (stats) => { + // console.log(stats) + console.log('remaining heap after garbage collection>>>',mem.subtract(stats.after.heapSizeLimit,stats.after.usedHeapSize)) +}) setInterval(()=> mem.emit('tick') ,5000) mem.on('tick',()=> { - mem.log({msg:'testing'}) + // mem.clog({msg:'testing', props:'all', str:true}) + // console.dir(mem.snapshot()) + console.log('remaining heap at snapshot@@@@',mem.snapshot().remaining) let text for (let i = 0; i < 1000000; i++) { text += 'a' diff --git a/package.json b/package.json index 76d9081..f6cfa2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@uci-utils/memory", - "version": "0.1.5", + "version": "0.1.6", "description": "memory logger and watcher", "main": "src/memory.js", "scripts": { diff --git a/readme.md b/readme.md index 270b475..5eba170 100644 --- a/readme.md +++ b/readme.md @@ -1,18 +1 @@ -# uCOMmandIt Reactive Class - -A Great Class to Extend! It has built in support to make reactive any/all class properties and their nested leaves. - -## Why? - -To have reactivity similar to vue and react but in any backend object? -This allow a backend app to maintain app settings and allow "clients" to get updated values when the app changes state. Essentially will create a 'mini' state event bus. - -## Features - -Will both emit and allow subscriptions to any property 'path' that has been made reactive. - -Allows custom registration of unlimited state change event hooks. - -Allows additional rxjs operators for the pipe the observer for each property. - -See Examples folder +# uCOMmandIt Memory Logging Utility diff --git a/src/memory.js b/src/memory.js index e3f2bc9..8eafc10 100644 --- a/src/memory.js +++ b/src/memory.js @@ -25,14 +25,13 @@ const PROPS = Object.keys(STATS) class Memory extends EventEmitter { constructor(opts={}) { super() - this._props = Object.keys(this.stats) this._diff = {} PROPS.forEach(prop=>this._diff[prop]={}) this._current = this.get() - this.db = opts.db || 3000 + this.db = opts.db || 3000 // debounce for gc watch this.reset() this.last = this.first - this.gc = gc() + this._watcher = false } get stats () { @@ -40,7 +39,7 @@ class Memory extends EventEmitter { } sizeof (obj, u='M') { - return mb(sizeof(obj)) + return this.mb(sizeof(obj)) } reset() { @@ -50,12 +49,12 @@ class Memory extends EventEmitter { get() { const mem = this.stats PROPS.forEach(prop => { - if (STATS[prop] === 'byte') mem[prop] = mb(mem[prop],2) + if (STATS[prop] === 'byte') mem[prop] = this.mb(mem[prop],2) }) return mem } - snapshot() { + snapshot(props,str) { this.last=Object.assign({},this._current) this._current=this.get() this.remaining = _.sub(this._current.heap_size_limit,this._current.used_heap_size) @@ -65,28 +64,46 @@ class Memory extends EventEmitter { this._diff[prop].overall=_.sub(this._current[prop],this.first[prop]) } }) - return { remaining:this.remaining, first:this.first, last:this.last, current:this._current, diff:this._diff } + if (props) { + if (typeof props ==='string') { + if (props === 'all') props = PROPS + else props = [props] + } + const strs = props.map(prop => this.log(prop) +'\n') + return str ? strs.join('') : strs + } + else return { remaining:this.remaining, first:this.first, last:this.last, current:this._current, diff:this._diff } } - log (opts) { - this.snapshot() + clog (opts) { + let props = opts.props + if (!props) props = ['used_heap_size','number_of_native_contexts'] console.log(`============= ${opts.msg||''} =====================`,new Date().toLocaleString()) - console.log(`remaining Heap: ${this.remaining} mb`) - console.log(this._log('used_heap_size')) - console.log(this._log('number_of_native_contexts')) + console.log(`\n remaining Heap: ${this.remaining} mb \n`) + console.log(this.snapshot(props,opts.str)) console.log(`============= ${opts.msg||''} =====================`) } - _log (prop) { + log (prop) { return `${prop} > \ diff:${this._diff[prop].overall}, \ lastdiff:${this._diff[prop].last}, \ current:${this._current[prop]}, \ last:${this.last[prop]}, \ -first:${this.first[prop]}, \ +first:${this.first[prop]} \ ` } + subtract (first,second,raw) { + const diff = _.sub(first,second) + return raw ? diff : this.mb(diff) + } + + mb (val,p=2) { + // console.log(val,val / 1024 / 1024, _.round(val / 1024 / 1024, -p) ) + return _.round(val / 1024 / 1024, -p) + } + // totalHeapSize: 17911808, // totalHeapExecutableSize: 573440, // usedHeapSize: 13410032, @@ -99,6 +116,10 @@ first:${this.first[prop]}, \ // numberOfDetachedContexts: 0 watch (handler) { + if (this._watcher) { + console.log('already watching, unwatch first to reset a handler') + return + } gc().on('stats', dbfn( stats => { const diff = _.sub(stats.after.heapSizeLimit,stats.after.usedHeapSize) @@ -106,10 +127,10 @@ first:${this.first[prop]}, \ if (!handler) { console.log(stats.gctype,'----------- Heap at GC ------------',new Date().toLocaleString()) console.log(`Heap> \ -remaining: ${mb(diff)} mb \ -before:${mb(stats.before.usedHeapSize)}, \ -after:${mb(stats.after.usedHeapSize)} mb, \ -diff:${mb(stats.diff.usedHeapSize)} mb \ +remaining: ${this.mb(diff)} mb \ +before:${this.mb(stats.before.usedHeapSize)}, \ +after:${this.mb(stats.after.usedHeapSize)} mb, \ +diff:${this.mb(stats.diff.usedHeapSize)} mb \ `) console.log('-----------------------') } @@ -117,15 +138,20 @@ diff:${mb(stats.diff.usedHeapSize)} mb \ }}, {wait:this.db} ) - )} + ) + this._watcher = true + } + + + unwatch() { + gc().removeAllListeners('stats') + this._watcher = false + } } // end class -function mb (val,p=2) { - // console.log(val,val / 1024 / 1024, _.round(val / 1024 / 1024, -p) ) - return _.round(val / 1024 / 1024, -p) -} + export default Memory export { Memory }