Code Review: C11

tfpt review “/shelveset:C11;REDMOND\tomat”

Adds ToReverseArray to CollectionUtils.


Implements constant access caching. We use a single per-runtime constant
access version (CAV) which increases each time any constant is assigned,
module is included into another module/class or any other operation that
can potentially change value returned from any constant read site. Each
constant read site holds on a cache object that holds on the last value
that the constant resolved to and the snapshot of the CAV for which the
value is valid. We collapse chained constant accesses (A::b::C…) into
a single site if possible. If any constant in the chain is missing
(const_missing is invoked) or the result is not cached. To not leak
significant amount of memory we need to hold on the constant values via
weak references. Since there are usually much more constant reads than
constant writes we create a weak reference on write, store it constant
table and reuse it in all read sites. We avoid creating weak references
for boxed primitive numeric types and Boolean to make access to these
constants faster and to reduce the amount of weak references created. To
ensure cross-runtime safety and keep the implementation simple we don’t
cache constant chains whose elements are from different runtimes (e.g.
A::b::C, where module A is from runtime 1 and module A::B from runtime

Also implements optimization of defined?(constant) construct. MRI
returns a fresh instance of string “constant” each time
defined?(constant) executes with success and nil if it fails to resolve
the constant. In most cases the result of defined? is used in a Boolean
expression thus immediately converted to Boolean. Since we can
statically determine whether a value is being read in a context of a
Boolean expression we don’t need to allocate the string if it is.

The implemented optimizations significantly improve throughput of
constant read intensive benchmarks:

W/o optimizations:

Ruby 1.9: 5.359/5.369
IronRuby: 2.695/2.597 -> 2.064x faster
Ruby 1.9: 1.674/1.556
IronRuby: 5.139/4.971 -> 3.194x SLOWER
Ruby 1.9: 5.210/5.208
IronRuby: 4.578/4.521 -> 1.152x faster

With constant access caching and defined? optimization:

Ruby 1.9: 5.362/5.365
IronRuby: 1.081/0.942 -> 5.691x faster
Ruby 1.9: 1.674/1.553
IronRuby: 1.281/1.103 -> 1.408x faster
Ruby 1.9: 5.204/5.204
IronRuby: 2.264/2.144 -> 2.427x faster