On 2010.01.04., at 14:19, Daryl Stultz wrote: > On Mon, Jan 4, 2010 at 7:13 AM, Attila Szegedi <[email protected]> wrote: > >> In my other project, FreeMarker, I implemented optional caching of >> wrappers. By default, it is turned off. I heard of some people that >> turned it on, but in most use cases, there are no noticeable >> performance differences. >> >> While you should test every performance hypothesis with a profiler, >> the common presumption these days is that these objects are >> sufficiently light to create that their repeated creation and >> collection (they'll likely not even survive the first eden space >> collection) is too insignificant burden to the GC to justify keeping >> them around. >> >> They're simply too light to cache. >> >> > My concern was not memory use but the expense of method lookups via > reflection. I imagine Rhino does a lot of caching of the lookups, then?
Caching is performed once per class and top-level scope, and results stored in an instance of ClassCache that is associated with the topmost scope. As an implication, if you use a new top-level scope for every script execution (which you normally do), you'll end up with the cache being recreated on a per-scope basis. If you use a shared-prototype top-level scope, you'll avoid this (but then you have to use shared-prototype top-level scope pattern, which I generally dislike). The problem is that every Java method needs to be exposed as a JavaScript Function, and as such it needs to have its internal "prototype" property set to the Function() constructor, which is found in a properly initialized (initStandardObjects) top-level scope. Hence, the created and cached reflective data depends upon a Function constructor instance in a standardly-initialized scope. Your choices are basically: a) use one non-shared top-level scope per script execution, suffer from repeated reflection lookups between script executions b) use one shared scope per script execution as a prototype of non-shared per-execution scopes. Drawbacks: need to use dynamic scoping (nonstandard JS), and scripts have shared state *that is mutable*. c) have one ClassCache and assign it to every scope you create - see ClassCache#associate() and ClassCache#get- you'll have to do it on the scope *before* calling initStandardObjects() as it'll install an empty new ClassCache into it. Drawback: Java methods and constructors mirrored into your scope will use Function prototype from another scope (the one ClassCache was first associated with) - I'm not sure if this can cause any problems (aside from never releasing that first scope from memory, which is a minor, fixed size memory usage increase), it might actually work in your scenario. Attila. -- home: http://www.szegedi.org twitter: http://twitter.com/szegedi weblog: http://constc.blogspot.com > > -- > Daryl Stultz > _____________________________________ > 6 Degrees Software and Consulting, Inc. > http://www.6degrees.com > mailto:[email protected] _______________________________________________ dev-tech-js-engine-rhino mailing list [email protected] https://lists.mozilla.org/listinfo/dev-tech-js-engine-rhino
