re: hash implementation: The hashes are implemented directly for performance. Performance is improved (over using ConcurrentHashMap) in several ways:
- The overhead of segment lookup/reference is eliminated. CHM breaks a hash table into segments (default 16) to reduce write contention. For our purposes, that doesn't buy much; ivar access will typically be single-threaded, and constants (usually) and symbols (always) are write-once (though the symbol table might still benefit from a segmented approach, we can look at that later). - Faster lookups are possible for keys that we know to be interned strings. I don't have any hard numbers on the percentage of gets/sets that pass interned strings, but I'd wager it's better than 90% (probably more like 99%), as every name that comes from an AST node is interned. The performance benefit is significant. - A slightly different lookup algorithm saves one volatile read per lookup (my approach uses reads/writes to the volatile array field itself [not entries, the field!] rather than a volatile size field to trigger memory barriers). - A CHECKCAST is avoided for each read. - Implementing the tables directly rather than as a component provided a significant performance benefit -- somewhat to my surprise. I did originally take the latter approach. The code is in bdortch/attrs/src/org/jruby/runtime/component, in VariableStore (abstract base class) and ConcurrentObjectVariableStore, which may yet find some use (in a somewhat modified form) once we refactor IRubyObject/RubyObject. However, I don't think it's unreasonable to implement these directly for performance (see RubyArray and RubyHash, for instance). re: JMM thread, I'll try to find it, it's been a couple of months since I looked at that stuff. I think it dated to 2004, or possibly late 2003, prior to the release of Java 1.5, but around the time JSR-133 was released. In any case, I'm going to play it safe for now and fall back on the readValueUnderLock technique. re: moving internal/special vars to attrs, that should be a goal, though these are in some cases used only for marshaling. re: IDs, in the abstract I like the idea, need to see what that means in concrete terms, what the overhead would be, etc. In the meantime, I think the rule can be, when in doubt, don't call the "fast" accessors. Maybe I should rename them: scaryFastGetInstanceVariable? -Bill
