0.1.6 improve logging and returns from snapshot, expose subtract and mb as part of class

master
David Kebler 2020-08-01 09:19:33 -07:00
parent cd8dec5927
commit be3611abf2
4 changed files with 61 additions and 48 deletions

View File

@ -1,18 +1,22 @@
import Memory from '../src/memory.js' 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.dir)
// mem.watch(console.log) // mem.watch()
mem.watch( (stats) => {
mem.watch() // console.log(stats)
console.log('remaining heap after garbage collection>>>',mem.subtract(stats.after.heapSizeLimit,stats.after.usedHeapSize))
})
setInterval(()=> setInterval(()=>
mem.emit('tick') mem.emit('tick')
,5000) ,5000)
mem.on('tick',()=> { 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 let text
for (let i = 0; i < 1000000; i++) { for (let i = 0; i < 1000000; i++) {
text += 'a' text += 'a'

View File

@ -1,6 +1,6 @@
{ {
"name": "@uci-utils/memory", "name": "@uci-utils/memory",
"version": "0.1.5", "version": "0.1.6",
"description": "memory logger and watcher", "description": "memory logger and watcher",
"main": "src/memory.js", "main": "src/memory.js",
"scripts": { "scripts": {

View File

@ -1,18 +1 @@
# uCOMmandIt Reactive Class # uCOMmandIt Memory Logging Utility
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

View File

@ -25,14 +25,13 @@ const PROPS = Object.keys(STATS)
class Memory extends EventEmitter { class Memory extends EventEmitter {
constructor(opts={}) { constructor(opts={}) {
super() super()
this._props = Object.keys(this.stats)
this._diff = {} this._diff = {}
PROPS.forEach(prop=>this._diff[prop]={}) PROPS.forEach(prop=>this._diff[prop]={})
this._current = this.get() this._current = this.get()
this.db = opts.db || 3000 this.db = opts.db || 3000 // debounce for gc watch
this.reset() this.reset()
this.last = this.first this.last = this.first
this.gc = gc() this._watcher = false
} }
get stats () { get stats () {
@ -40,7 +39,7 @@ class Memory extends EventEmitter {
} }
sizeof (obj, u='M') { sizeof (obj, u='M') {
return mb(sizeof(obj)) return this.mb(sizeof(obj))
} }
reset() { reset() {
@ -50,12 +49,12 @@ class Memory extends EventEmitter {
get() { get() {
const mem = this.stats const mem = this.stats
PROPS.forEach(prop => { 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 return mem
} }
snapshot() { snapshot(props,str) {
this.last=Object.assign({},this._current) this.last=Object.assign({},this._current)
this._current=this.get() this._current=this.get()
this.remaining = _.sub(this._current.heap_size_limit,this._current.used_heap_size) 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]) 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) { clog (opts) {
this.snapshot() let props = opts.props
if (!props) props = ['used_heap_size','number_of_native_contexts']
console.log(`============= ${opts.msg||''} =====================`,new Date().toLocaleString()) console.log(`============= ${opts.msg||''} =====================`,new Date().toLocaleString())
console.log(`remaining Heap: ${this.remaining} mb`) console.log(`\n remaining Heap: ${this.remaining} mb \n`)
console.log(this._log('used_heap_size')) console.log(this.snapshot(props,opts.str))
console.log(this._log('number_of_native_contexts'))
console.log(`============= ${opts.msg||''} =====================`) console.log(`============= ${opts.msg||''} =====================`)
} }
_log (prop) { log (prop) {
return `${prop} > \ return `${prop} > \
diff:${this._diff[prop].overall}, \ diff:${this._diff[prop].overall}, \
lastdiff:${this._diff[prop].last}, \ lastdiff:${this._diff[prop].last}, \
current:${this._current[prop]}, \ current:${this._current[prop]}, \
last:${this.last[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, // totalHeapSize: 17911808,
// totalHeapExecutableSize: 573440, // totalHeapExecutableSize: 573440,
// usedHeapSize: 13410032, // usedHeapSize: 13410032,
@ -99,6 +116,10 @@ first:${this.first[prop]}, \
// numberOfDetachedContexts: 0 // numberOfDetachedContexts: 0
watch (handler) { watch (handler) {
if (this._watcher) {
console.log('already watching, unwatch first to reset a handler')
return
}
gc().on('stats', dbfn( gc().on('stats', dbfn(
stats => { stats => {
const diff = _.sub(stats.after.heapSizeLimit,stats.after.usedHeapSize) const diff = _.sub(stats.after.heapSizeLimit,stats.after.usedHeapSize)
@ -106,10 +127,10 @@ first:${this.first[prop]}, \
if (!handler) { if (!handler) {
console.log(stats.gctype,'----------- Heap at GC ------------',new Date().toLocaleString()) console.log(stats.gctype,'----------- Heap at GC ------------',new Date().toLocaleString())
console.log(`Heap> \ console.log(`Heap> \
remaining: ${mb(diff)} mb \ remaining: ${this.mb(diff)} mb \
before:${mb(stats.before.usedHeapSize)}, \ before:${this.mb(stats.before.usedHeapSize)}, \
after:${mb(stats.after.usedHeapSize)} mb, \ after:${this.mb(stats.after.usedHeapSize)} mb, \
diff:${mb(stats.diff.usedHeapSize)} mb \ diff:${this.mb(stats.diff.usedHeapSize)} mb \
`) `)
console.log('-----------------------') console.log('-----------------------')
} }
@ -117,15 +138,20 @@ diff:${mb(stats.diff.usedHeapSize)} mb \
}}, }},
{wait:this.db} {wait:this.db}
) )
)} )
this._watcher = true
}
unwatch() {
gc().removeAllListeners('stats')
this._watcher = false
}
} // end class } // 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 default Memory
export { Memory } export { Memory }