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

Reply via email to