Profiling Field Initialisation in Java Stephen Nelson, David J. Pearce & James Noble Victoria University of Wellington New Zealand
Motivation “Favour Immutability”, #13, Effective Java: –"Classes should be immutable unless there's a very good reason to make them mutable....If a class cannot be made immutable, limit its mutability as much as possible.” –“Immutable classes are easier to design, implement, and use than mutable classes” -- Josh Bloch
Motivation “Favour Immutability”, #13, Effective Java: –"Classes should be immutable unless there's a very good reason to make them mutable....If a class cannot be made immutable, limit its mutability as much as possible.” –“Immutable classes are easier to design, implement, and use than mutable classes” -- Josh Bloch Q) How well does Java support this?
Field Initialisation Java provides final fields to prohibit modification and show intent Unfortunately, in this example, cannot declare parent field final abstract class Parent { private final Child child; public Parent(Child c) { this.child = c; } } abstract class Child { private Parent parent; public void set(Parent p) { parent = p; } }
Stationary Fields A field is stationary if, for all objects, every write occurs before first read Unkel & Lam (POPL’08) statically inferred stationary fields –Across corpus of 26 Java Applications, found between 40-60% of fields were stationary WRWR W RWR
More on Stationary Fields Final fields are subset of stationary fields: Distinguish Declared Final and Undeclared Final WRWR CE WRWR WRRR
Rprof – Overview Our Runtime Profiling Tool: –Whole-program, including standard libraries –No sampling, record and analyse every event –Tracks constructor entry/exit and field read/write
Rprof – Map/Reduce Problem: how to handle billions of events? Answer: throw more hardware at it! –Event processing done using Map/Reduce –Events processed in parallel to give more manageable results –Worker threads spread over multiple machines Consequence: less flexibility –Must customise map/reduce procedure for each distinct analysis
Rprof – Map/Reduce Example 1. W #1.f 2. W #2.g 3. W #1.f 4. R #2.g 5. W #2.g 6. R #1.f 1. W #1.f 2. W #2.g 3. W #1.f 4. R #2.g 5. W #2.g 6. R #1.f 1. W #1.f 2. W #2.g 3. W #1.f 4. R #2.g 5. W #2.g 6. R #1.f Reduce LW: 3 FR: 6 LW: 5 FR: 4
Experimental Setup Methodology: –Profile single run of benchmark with default input –OpenJDK ea-b37 was the experimental platform (*) –Opteron 254 (2.8GHz) dual CPU with 4GB was experimental machine Dacapo Benchmark Suite –14 Applications – classes –Non-trivial memory loads –Workloads provided –No User Interaction –Reproduceable Results
Results – Overall Key Observation: 70% -- 80% of fields are stationary
Results – Primitives vs References
Threats to Validity Benchmark Inputs –Cannot generalise program behaviour from a single run! –Better to use a set of inputs – but how to generate them? Benchmark Scope –Unclear whether DeCapo representative of general population Conclusion: –Our results provide upper bound on number of stationary fields –Unkel & Lam provide lower bound on number of stationary fields
Conclusion Unkel & Lam –Static inference of stationary fields –Found 40-60% of fields were stationary –Static analysis conservative -> lower bound Our results –Complement that of Unkel & Lam –Use runtime profiling instead of static inference –Found 70-80% of fields are stationary –Runtime profiling is unsound -> upper bound