z) { int a = x + y; int b = x - y; int c = z + x; return a + b; } int doMath(int x, int y, int z) { int c = z + x; int b = x - y; int a = x + y; return a + b; } Saturday, August 31, 13
int z) { int a = x + y; int b = x - y; int c = z + x; return a + b; } int doMath(int x, int y, int z) { int a = x + y; int b = x - y; return a + b; } Saturday, August 31, 13
= x + y; int b = x - y; int c = z + x; return a + b; } int doMath(int x, int y, int z) { return x + y + x - y; } Values can be propagated Saturday, August 31, 13
(magnitude > 1) ? magnitude : 1; subBucketCount = (int) Math.pow(2, subBucketMagnitude); subBucketMask = subBucketCount - 1; Hard enough to follow as it is No value in “optimizing” human-readable meaning away Compiled code will end up the same anyway. So Why does this matter Saturday, August 31, 13
int distanceAfter = end - a.getX(); return distanceTo/distanceAfter; } int distanceRatio(Object a) { int x = a.getX(); int distanceTo = x - start; int distanceAfter = end - x; return distanceTo/ distanceAfter; } Reads can be cached Saturday, August 31, 13
a. setVisibleValue(0); for (int i = 0; i < 1000000; i++) { a.setInternalValue(i); } a.setVisibleValue(a.getInternalValue()); } void updateDistance(Object a) { a.setInternalValue(1000000); a.setVisibleValue(1000000); } Writes can be eliminated++ Saturday, August 31, 13
off clean design against speed E.g. “final” should be used on methods only when you want to prohibit extension, overriding. Has no effect on speed. E.g. branching can be written “naturally” Saturday, August 31, 13
throwing knives It takes practice and understanding to get it right You can get very good at it, but do you really want to? Will all the code you leverage be as good as yours? Saturday, August 31, 13
is wrong In many cases, it’s much better than you may think GC is extremely efficient. Much more so that malloc() Dead objects cost nothing to collect GC will find all the dead objects (including cyclic graphs) ... In many cases, it’s much worse than you may think Yes, it really does stop for ~1 sec per live GB (in most JVMs). No, GC does not mean you can’t have memory leaks No, those pauses you eliminated from your 20 minute test are not gone ... Saturday, August 31, 13
Concurrent Collector performs garbage collection work concurrently with the application’s own execution A Parallel Collector uses multiple CPUs to perform garbage collection Saturday, August 31, 13
automatic memory management. The garbage collector is the program attempts to reclaim garbage, or memory occupied by objects that are no longer in use by the program. Saturday, August 31, 13
when an object is garbage collected. It is similar in function to a destructor. Finalizers are usually not deterministic. a finalizer is executed when the internal garbage collection system frees the object. Saturday, August 31, 13
to become reachable (that is, not garbage). The garbage collector must determine if the object has been resurrected by the finalizer or risk creating a dangling reference. The JVM will not invoke finalize() method again after resurrection Saturday, August 31, 13
tree-based data structure that satisfies the heap property: If A is a parent node of B then key(A) is ordered with respect to key(B) with the same ordering applying across the heap Saturday, August 31, 13
be only be accessed by references. Objects of reference types cannot be directly embedded into composite objects and are always dynamically allocated. They are usually destroyed automatically after they become unreachable. Saturday, August 31, 13
deep copy semantics. Value type that use the term value type to refer to the types of objects for which assignment has deep copy semantics (as opposed to reference types, which have shallow copy semantics) Saturday, August 31, 13
protects the referred object from collection by a garbage collector. The term is used to distinguish the reference from weak references. Saturday, August 31, 13
not protect the referenced object from collection by a garbage collector; unlike a strong reference. An object referenced only by weak references is considered unreachable (or weakly reachable) and so may be collected at any time. Some garbage-collected languages feature or support various levels of weak references, Saturday, August 31, 13
may be used to solve the problem of circular references if the reference cycles are avoided by using weak references for some of the references within the group. For example, Apple's Cocoa framework recommends this approach, by using strong references for parent-to-child references, and weak references for child- to-parent references, thus avoiding cycles. Weak reference distill Saturday, August 31, 13
are weak and smart pointers are strong; although pointers are not true weak references, as weak references are supposed to know when the object becomes unreachable. Saturday, August 31, 13
including those that appear as primitive types. On the Java platform, all composite and user- defined types are reference types. Only primitive types are value types. The .NET Framework makes a clear distinction between value and reference types, and allows creation of user-defined types for both kinds. Saturday, August 31, 13
is used to handle resource cleanup in runtime environments that use automatic garbage collection. The fundamental problem that the dispose pattern aims to solve is that, because objects in a garbage-collected environment have finalizers rather than destructors, there is no guarantee that an object will be destroyed at any deterministic point in time. The dispose pattern works around this by giving an object a method (usually called Dispose or similar) which frees any resources the object is holding onto. Saturday, August 31, 13
approach is that it requires the programmer to explicitly add cleanup code in a finally block. This leads to code size bloat, and failure to do so will lead to resource leakage in the program. Saturday, August 31, 13
work concurrently with the application’s own execution A Parallel Collector uses multiple CPUs to perform garbage collection A Stop-the-World collector performs garbage collection while the application is completely stopped An Incremental collector performs a garbage collection operation or phase as a series of smaller discrete operations with (potentially long) gaps in between Mostly means sometimes it isn’t (usually means a different fall back mechanism exists) Saturday, August 31, 13
is unaware of some object references at collection time, or is unsure about whether a field is a reference or not A Collector is Precise if it can fully identify and process all object references at the time of collection A collector MUST be precise in order to move objects The COMPILERS need to produce a lot of information (oopmaps) All commercial server JVMs use precise collectors All commercial server JVMs use some form of a moving collector Saturday, August 31, 13
is actually collected can be unpredictable, resulting in stalls scattered throughout a session. that is STW. Non-deterministic GC is incompatible with RAII based management of non GCed resources. As a result, the need for explicit manual resource management (release/close) for non-GCed resources becomes transitive to composition. Garbage collection is rarely used on embedded or real- time systems because of the perceived need for very tight control over the use of limited resources. However, garbage collectors compatible with such limited environments have been developed. Saturday, August 31, 13
with the execution of the user program. Reference counting may therefore be a suitable method if a smoother response time is important. reference count becomes zero can be reclaimed without access to cells in other pages of the heap. Disadvantage is the high processing cost paid to update counters to maintain the reference count invariant. Saturday, August 31, 13
it needs a strategy to avoid memory leaks as well as the use of freed memory. The chosen method is called reference counting. The principle is simple: every object contains a counter, which is incremented when a reference to the object is stored somewhere, and which is decremented when a reference to it is deleted. When the counter reaches zero, the last reference to the object has been deleted and the object is freed. Saturday, August 31, 13
Py_DECREF(x), Py_DECREF() also frees the object when the count reaches zero. For flexibility, it doesn't call free() directly -- rather, it makes a call through a function pointer in the object's type object. For this purpose (and others), every object also contains a pointer to its type object. http:/ /docs.python.org/release/2.5.2/ext/refcounts.html Saturday, August 31, 13
can own a reference to an object. An object's reference count is now defined as the number of owned references to it. The owner of a reference is responsible for calling Py_DECREF() when the reference is no longer needed. Ownership of a reference can be transferred. There are three ways to dispose of an owned reference: pass it on, store it, or call Py_DECREF(). Forgetting to dispose of an owned reference creates a memory leak. Saturday, August 31, 13
"Paint" anything you can reach as “live” At the end of a mark pass: all reachable objects will be marked "live" all non-reachable objects will be marked "dead" (aka "non-live"). Note: work is generally linear to "live set" Saturday, August 31, 13
bookkeeping in systems programs is memory management. We feel it's critical to eliminate that programmer overhead, and advances in garbage collection technology in the last few years give us confidence that we can implement it with low enough overhead and no significant latency. http:/ /golang.org/doc/faq#garbage_collection Saturday, August 31, 13
a "from" space to a "to" space & reclaims "from" space At start of copy, all objects are in "from" space and all references point to "from" space. Start from "root" references, copy any reachable object to "to" space, correcting references as we go At end of copy, all objects are in "to" space, and all references point to "to" space Note: work generally linear to "live set". Saturday, August 31, 13
efforts on young generation: Use a moving collector: work is linear to the live set The live set in the young generation is a small % of the space Promote objects that live long enough to older generations Only collect older generations as they fill up “Generational filter” reduces rate of allocation into older generations Tends to be (order of magnitude) more efficient Great way to keep up with high allocation rate Practical necessity for keeping up with processor throughput Saturday, August 31, 13
which) To compact a single region, only need to scan regions that point into it to remap all potential references identify regions sets that fit in limited time Each such set of regions is a Stop-the-World increment Safe to run application between (but not within) increments Note: work can grow with the square of the heap size The number of regions pointing into a single region is generally linear to the heap size (the number of regions in the heap) Saturday, August 31, 13
code (IA-32, x86-64, ARM, or MIPS CPUs)[3][6] before executing it, instead of more traditional techniques such as executing bytecode or interpreting it. Optimization techniques used include inlining, elision of expensive runtime properties, and inline caching, among many others. The garbage collector of V8 is a generational incremental collector Saturday, August 31, 13
reliable Mark/Compact [typically] requires 2x the max. live set in order to fully recover garbage in each cycle Mark/Sweep/Compact only requires 1x (plus some) Copy and Mark/Compact are linear only to live set Mark/Sweep/Compact linear (in sweep) to heap size Mark/Sweep/(Compact) may be able to avoid some moving work Copying is [typically] "monolithic". Saturday, August 31, 13
at all times, the collector would have to work “very hard”, and GC would take 100% of the CPU time If we had infinite empty memory, we would never have to collect, and GC would take 0% of the CPU time GC CPU % will follow a rough 1/x curve between these two limit points, dropping as the amount of memory increases. Saturday, August 31, 13
of empty memory in the heap is the dominant factor controlling the amount of GC work For both Copy and Mark/Compact collectors, the amount of work per cycle is linear to live set The amount of memory recovered per cycle is equal to the amount of unused memory (heap size) - (live set) The collector has to perform a GC cycle when the empty memory runs out A Copy or Mark/Compact collector’s efficiency doubles with every doubling of the empty memory Saturday, August 31, 13
collector work needed per amount of application work performed) Empty memory controls the frequency of pauses (if the collector performs any Stop-the-world operations) Empty memory DOES NOT control pause times (only their frequency) In Mark/Sweep/Compact collectors that pause for sweeping, more empty memory means less frequent but LARGER pauses Saturday, August 31, 13
marker Mostly concurrent marking. Stop-the-world to catch up on mutations, ref processing, etc. Tracks inter-region relationships in remembered sets Stop-the-world mostly incremental compacting old gen Objective: “Avoid, as much as possible, having a Full GC...” Compact sets of regions that can be scanned in limited time Delay compaction of popular objects, popular regions Fallback to Full Collection ( Monolithic Stop the world). Used for compacting popular objects, popular regions, etc. Saturday, August 31, 13