Closed ThomWright closed 3 years ago
@ThomWright have you considered relying on memoizee/profile
?
@ThomWright have you considered relying on
memoizee/profile
?
Blimey that was quick :smile:
I saw it, but also saw:
Mind also that running profile module affects performance, it's best not to use it in production environment
I would like to run this in a production environment :wink:
@ThomWright I think main part that affects performance in profiler is generation of the stack traces (so profile stats show were memoized function was invoked)
I think there are two ways you can avoid that
memoizee
). Introduce an extra option for profilre, to provide more basic statistics, without stack traces, and also we need to update it, so gathered data is accessible programmatically (currently only log
function is exposd which returns human readable summary)set
and get
events as here: https://github.com/medikoo/memoizee/blob/cd7cc2738c183fd00f7e8bf5ba6a96935f2b3dab/profile.js#L37-L38 And afaik it's all you need to gather needed data. To attach to those events you need to access conf
object, which is not expose on memoized function, but is exposed to eventual extensions. While unfortunately there's no perfect documentation, on how to create extension, you may take an inspiration on how extension can be configured by inspecting those prepared here: https://github.com/medikoo/memoizee/tree/cd7cc2738c183fd00f7e8bf5ba6a96935f2b3dab/extGreat, thank you. I'll have a look at the extensions.
That solution seems to work, thanks. For reference, here is what I did:
const memoizeeExtensions = require("memoizee/lib/registered-extensions")
memoizeeExtensions.metrics = function(
_: unknown,
conf: EventEmitter,
options: memoizee.Options<Parse>,
) {
const postfix =
(options.async && memoizeeExtensions.async) ||
(options.promise && memoizeeExtensions.promise)
? "async"
: ""
conf.on("set" + postfix, (id: string) => {
queryCounter.inc()
})
conf.on("get" + postfix, (id: string) => {
queryCounter.inc()
hitsCounter.inc()
})
conf.on("delete" + postfix, (id: string) => {
evictionCounter.inc()
})
}
return memoizee(parse, {
primitive: true,
max: 250,
metrics: true,
})
To get the types to work I also did this:
// typings/memoizee/index.d.ts
import "memoizee"
declare module "memoizee" {
export interface Options<F extends (...args: any[]) => any> {
// To turn on our own extension
metrics?: boolean
}
}
I'm trying to add Prometheus metrics around my cache use. The metrics I'd like are:
Hit rate can then be
hits / accesses
, and eviction rateevictions / accesses
.This is what I have now;
Having another callback, in addition to
dispose
which gets called after every access and has(hit: boolean)
as the parameter would be really useful.For example: