Compare commits

...

1 Commits

4 changed files with 61 additions and 48 deletions

View File

@ -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'

View File

@ -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": {

View File

@ -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

View File

@ -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 }