Thursday, December 4, 2014
M3: Mixed Collection for Simplicity
Tuesday, December 2, 2014
Schism Real-Time Collection
1.1 Abstract
1.1.1 Provides fragmentation tolerance with worst case time/space guarantees
1.1.2 Implementation in the Fiji VM, a JVM for mission-critical systems
Garbage Collection for FPGAs
1.1 Abstract
1.1.1 FPGAs are complex, programming at a higher level of abstraction is desirable
1.1.2 First complete GC in hardware, not hardware-assisted
1.1.3 Reasonable performance
- ever more than %1 of resources on most high-end FPGAs
- Uses completely concurrent snapshot algorithm
- Single-cycle access to hte heap, mutator not stalled for even a single cycle
- Can achieve 100%MMU with heaps as small as 1.01-1.04 absolute minimum
The DieHard Safe Memory Allocator
1 DieHard, Probabilitic Memory for Unsafe Languages
1.1 Intro
- Memory errors such as buffer overflows, use-after-free, and uninitialized memory usage can compromise C/C++ applications
- Tools like valgrind can help track down errors, but only work on errors observed during execution
- Programs which detect error and fail fast can be undesirable if the end user prioritizes uptime
- Failure-oblivious programs which drop illegal writes and give sentinels on illegal reads keep the program running but make no promises about correctness to the progammer.
- Probabilitic memory safety is a suggested solution to this, DieHard is one such implementation
Wednesday, November 19, 2014
Status on the Bug Collector
My last few weeks have been spent working on the DWARF-based root scanner for C and C++ which was proposed in a previous post.
Where have I come, and what I have I learned?
Sunday, November 16, 2014
MMTK today
Thursday, November 13, 2014
Polyhedral GC
Monday, November 10, 2014
Sunday, November 9, 2014
Migration from Conservative GC
Sadly, conservative collection has a fatal flaw: GC things cannot move. If something moved, you would need to update all pointers to that thing — but the conservative scanner can only tell you what might be a pointer, not what definitely is a pointer. Your program might be using an integer whose value happens to look like a pointer to a GC thing that is being moved, and updating that “pointer” will corrupt the value. Or you might have a string whose ASCII or UTF8 encoded values happen to look like a pointer, and updating that pointer will rewrite the string into a devastating personal insult.
So why do we care? Well, being able to move objects is a prerequisite for many advanced memory management facilities such as compacting and generational garbage collection. These techniques can produce dramatic improvements in collection pause times, allocation performance, and memory usage. SpiderMonkey would really like to be able to make use of these techniques. Unfortunately, after years of working with a conservative collector, we have accumulated a large body of code both inside SpiderMonkey and in the Gecko embedding that assumes a conservative scanner: pointers to GC things are littered all over the stack, tucked away in foreign data structures (i.e., data structures not managed by the GC), used as keys in hashtables, tagged with metadata in their lower bits, etc.
Their solution?
Over a year ago, the SpiderMonkey team began an effort to claw our way
back to an exact rooting scheme. The basic approach is to add a layer of
indirection to all GC thing pointer uses: rather than passing around
direct pointers to movable GC things, we pass around pointers to GC
thing pointers (“double pointers”, as in JSObject**). These Handles,
implemented with a C++ Handle<T> template type, introduce a small
cost to accesses since we now have to dereference twice to get to the
actual data rather than once. But it also means that we can update the
GC thing pointers at will, and all subsequent accesses will go to the
right place automatically.
This is an interesting solution to the consistency problem. It would in theory allow a realtime collector to race to copy live data, using some kind of compare-and-set. The problem with this in the context of a C/C++ conservative collector is that it changes the semantics of pointer dereferencing and the type of references returned by malloc. For a language with complete control of the collector usage, it's a nice vindication of the trite adage that "all problems in CS can be handled with another layer of indirection."
Cache locality would suffer, one might think, because the pointer to the indirection object may become quite far away from the data the object points to. Therefore every memory access requires fetching two different locations into the cache in the worst case.
If all references are stored in in a single place, different processors may contend to have the cache line holding all of the entries. This is false sharing, called so because the processors will fight to have memory addresses in their cache line that share bits with the data they actually want. They're sharing the cache line without actually sharing any addresses.
That said, the change was a step toward the runtime and collection optimizations that led to the team's recent massive performance increases and the reduction of the resident memory used by the firefox web browser.
Wednesday, November 5, 2014
Status Report for GC through Self-Introspection through DWARF
Actually getting the value of the pointers requires running a simple state machine. There are a few locations that a variable could be in, and all of the relevant ones require a degree of stack walking.
Tuesday, November 4, 2014
How I know that polishing dwarf-based location finding will take a while
There are many ways that libdwarf can encode variable locations. In fact, it's an entire state machine. That said, C doesn't use most of them. After getting the basic parsing working, this will be something to return to and polish up.
Monday, November 3, 2014
Previous space optimizations of the BDW GC
- Conservative collectors have come in many shapes and sizes. Some track all pointers in heap while others are more conservative.
- Severe space leaks in conservative collectors have been noted in the past.
- Negative performance results associated with collectors likely due to space leakage and associated problems such as increased memory pressure and likelihood of thrashing.
- Removal of low-hanging fruit such as static values which point into heap area can lead to great improvements.
- Only paper(at time of this paper) analyzing pitfalls of conservative GC: http://dl.acm.org/citation.cfm?id=79028
Friday, October 31, 2014
A Great Dwarf 101
http://www.dwarfstd.org/doc/Debugging%20using%20DWARF.pdf
Thursday, October 30, 2014
DWARF resources
http://www.dwarfstd.org/doc/DWARF4.pdf
Parsing dwarf is not very fun. There are two main libraries which will do that for you, libdwarf and libbfd. Because libbfd(binary file descriptor) seems more arcane and more rigidly suited to working with elf/dwarf files external to the current program, I'm electing to use libdwarf. Documentation seemed hard to find, but it appears to be well-documented on sourceforge:
http://sourceforge.net/p/elftoolchain/wiki/libdwarf/
Proposal: Not-So Conservative Collection
I would use the type interface in in their types.h, and would use libbfd or libdwarf to parse the dwarf files.
A caveat would be that casting a pointer to an integer may lead to freeing memory in use. As this is a purposeful defeat of the type system, I’m not sure if there is a way to track this and compensate for it.
In more depth:
Proposal: Static Memory-Management Cost Reasoning in Garbage Collected Languages
Wednesday, October 22, 2014
Read Barrier Elimination Through Concurrency
Table of Contents
- 1. Eliminating Read Barriers through Procrasination and Cleanliness
- 1.1. Abstract
- 1.2. Introduction
- 1.2.1. Use of parallelism and thread-local heaps with single shared heap uses write barriers to enforce
- 1.2.2. Terminology: exporting writes = writes which incur a write barrier and export object to shared heap and set up forwarding pointer.
- 1.2.3. Needs a read barrier because reference might refer to newly-exported object.
- 1.2.4. Read barrier cost is high, but removal is nontrivial.
- 1.2.5. Idea: Delay operation
- 1.2.6. Idea: Avoid stalling using language semantics
- 1.3. Motivation
- 1.3.1. Implementation considered is multimlton.
- 1.3.2. Has userspace concurrency, many green threads mapped to single kernel thread.
- 1.3.3. Each core has local heap, and there's a single shared heap.
- 1.3.4. Max heap set at 3x min heap.
- 1.3.5. Extensive optimization to avoid heap usage
- 1.3.6. On exporting an object, the stack is walked and all references are fixed. Therefore roots never point to forwarding pointer.
- 1.3.7. If object has been moved, read barrier returns new address. Therefore conditional read barrier.
- 1.3.8. Mutator spends ~20% of execution time in read barrier.
- 1.3.9. Brooks-style unconditional barrier would reduce time, but since most objects 3 words or less, forwarding pointer would have significant overhead.
- 1.3.10. Less than 1/100 percent of reads end up being to forwarding pointers. Therefore read barrier significant cost.
- 1.4. GC Design and Implementation
- 1.5. Cleanliness Analysis
- 1.6. Write barrier
- 1.7. Target Architectures
- 1.8. Results
1 Eliminating Read Barriers through Procrasination and Cleanliness
1.1 Abstract
1.1.1 Goal is to avoid need for a read barrier
1.1.2 Use concurrency and stalling to avoid need for immediate copy
1.1.3 Can avoid need to stall, use language semantics to allow references in fromspace or copy when small set of references to object are known
1.2 Introduction
1.2.1 Use of parallelism and thread-local heaps with single shared heap uses write barriers to enforce
1.2.2 Terminology: exporting writes = writes which incur a write barrier and export object to shared heap and set up forwarding pointer.
1.2.3 Needs a read barrier because reference might refer to newly-exported object.
1.2.4 Read barrier cost is high, but removal is nontrivial.
1.2.5 Idea: Delay operation
- Read barriers only need to exist if there are forwarding pointers which exist between move and collection
- Can delay operations that create them
- We can stall threads which need to cause copy to shared heap, procrastinating the move
- GC is informed of these procrasinated operations at start of collection
- As long as there are enough threads, cost of procrastination simply cost of context switch.
1.2.6 Idea: Avoid stalling using language semantics
1.3 Motivation
1.3.1 Implementation considered is multimlton.
1.3.2 Has userspace concurrency, many green threads mapped to single kernel thread.
1.3.3 Each core has local heap, and there's a single shared heap.
1.3.4 Max heap set at 3x min heap.
1.3.5 Extensive optimization to avoid heap usage
1.3.6 On exporting an object, the stack is walked and all references are fixed. Therefore roots never point to forwarding pointer.
1.3.7 If object has been moved, read barrier returns new address. Therefore conditional read barrier.
1.3.8 Mutator spends ~20% of execution time in read barrier.
1.3.9 Brooks-style unconditional barrier would reduce time, but since most objects 3 words or less, forwarding pointer would have significant overhead.
1.3.10 Less than 1/100 percent of reads end up being to forwarding pointers. Therefore read barrier significant cost.
1.4 GC Design and Implementation
1.4.1 Threading system
1.4.2 Baseline collector(stop the world)
1.4.3 Local collector(split heap)
1.4.4 Remembered stacks
1.5 Cleanliness Analysis
1.5.1 Heap Session
1.5.2 Reference count
- We steal 4 bits in each object header to record number of references within the current session.
- 4 bits encode zero, one, localmany, and globalmany
- Zero => Only references from stacks, globalmany => at least one reference outside current session.
- Implemented as part of write barrier. Non-decreasing, so represents a maximum.
1.6 Write barrier
1.6.1 If not primtive, and exporting, and clean, copy transitive closure to shared heap.
1.6.2 Delaying writes
1.6.3 Lifting objects to shared heap
1.6.4 Remote spawns
1.7 Target Architectures
1.7.1 Used 16-core linux machine, 48-core intel single-chip cloud computer, and 864-core azul vega 3.
1.8 Results
1.8.2 Performance
- Ported Bohem-Demers-Weiser conservative GC to test against
- Consecutive tests done by shrinking maximum allowed heap size and recording running time and actual heap utilization.
- Read-barrier-less had better performance, but had higher minimum heap size.
- Stop-the-world gc has faster mutator time than alternatives, but impacted scalability because collection was serial when world stopped.
- Bohem GC slow.
1.8.3 Impact of cleanliness
1.8.4 Impact of Immutability
1.8.5 Impact of heap session
A Control-Theory Approach to Heap Resizing
Table of Contents
1 Heap Sizing
1.1 Control Theory for Principled Heap Sizing
1.1.1 Intro
- Programs frequently have seperate phases with very different memory behavior, no static heuristic acceptable
- Control theory offers more formalism than trying to glue random, effective heuristics together.
- Paper describes the idea of having a GC controller and increasing the heap size until the heap thrashing decreases and a throughput goal is hit.
1.1.2 Sweet spots
1.1.3 Heap sizing in existing VMs.
- Existing VMs tend to increase heap size too optimistically, and decrease it more slowly than could be desired.
- Jikes RVM
- After each GC, manager determines new "resize ratio" based on short term GC overhead (ratio of gc time and time since last GC) and ratio of heap that was live
- Not explicitly goal-oriented in terms of throughput or heap size
- Doesn't take history into account, can flip-flop between states needlessly when live data size fluctuates back and forth quickly.
- There is no evidence that different GC algorithms will match these hard-coded heuristic thresholds
- After each GC, manager determines new "resize ratio" based on short term GC overhead (ratio of gc time and time since last GC) and ratio of heap that was live
- Hotspot
- Has a lot of tunable "ergonomics," and will resize heap to make best-effort to meet all priorities.
- Resizing rate much less flexible, ratio bounded between 0.95 and 1.2. Early on in execution, allows to grow at ratio 2.
- Venegrov has questioned whether the resize policies actually ensure progress towards goals.
- Has a lot of tunable "ergonomics," and will resize heap to make best-effort to meet all priorities.
1.1.4 Heap sizing as a control problem
- Should use control theory
- Formulating the Problem
1.1.5 Designing a Heap Size Controller
- Chose to treat entire GC system as black box, tune using Proportional Integral Derivative controller
- Use a target GC overhead to resize heap
- Only consider resizing after GC to avoid confounding variables in controller training.
- PID Controller
- PID Controller Theory
- Implementation
- Built on Jikes/MMTK
- Uses bytes allocated as time proxy
- Heap growth manager was modified to use the PID controller
- Source: http://sourceforge.net/p/jikesrvm/research-archive/40/
- Built on Jikes/MMTK
- Tuning:
1.1.6 Evauluation
1.1.7 Related work
- Heuristic Approaches
- Mathematical Models
- Control Theory Papers
Page Fault Driven Heap Size
Table of Contents
1 A Page Fault Equation for Dynamic Heap Sizing
http://www.math.nus.edu.sg/~mattyc/HeapSizing.pdf
This is an interesting paper. It more or less presents an equation,
1.1 Introduction
H is the heap size, M is the size of available main memory
1.1.1 Suggested policy out-performs JikesRVM's heap size mamager
1.1.2 The Problem:
- Frequent GC pauses in a small heap leads to significant performance degredation due to cache pollution.
- A large heap faces frequent page faults.
- Tuning intelligently can possibly lead to better performance that manual memory management can provide.
- Heap cannot be static, must be able to scale to very small and very large heaps.
- The number of page faults not simply a function of actual memory and of heap size, includes mutator + collector behavior.
1.1.3 Heap-Aware Page Fault Equation
1.1.4 General Page Fault Equation:
1.1.5 Heap sizing Rule:
- Uses the parameters for the page fault equation to know how to resize.
- Doesn't require OS or hardware modification or costly setup of polling, handlers, and callbacks for stalls and page references.
- Can automatically respond to changes in main memory(cloud hosting?)
- Allows for hotswapping of collectors if parameters found.
1.2 Heap-Aware Page Fault Equation:
1.2.2 Paper describes parameters in general equation
1.2.4 Experimental Validation
1.2.5 Can derive a Hmin, the smallest reasonable heap.
1.3 Heap Sizing
1.3.2 Experiments with static memory size
Wednesday, October 15, 2014
MMTK/Jikes RVM
jikes
MMTK
A garbage collection framework similar to the plai2 framework but less designed as a "toy" is the mmtk(Memory Management Toolkit) for the jikesRVM.
A quick overview of the interaction between the virtual machine and the mmtk framework can be found here: http://jikesrvm.org/Memory+Allocation+in+JikesRVM
Jikes is surprisingly both non-frightening and full-featured. One of the surprising things about MMTK is the presence of such optimizations as thread-local allocation interfaces while still retaining the simplicity of the memory manager interface.
If you're planning on making a collector for jikes, I believe that the best overview of the way that the collector is expected to be structured and how Jikes will use it can be found here: http://jikesrvm.org/Anatomy+of+a+Garbage+Collector
It comes with a large number of garbage collectors. They all satisfy a simple interface which captures the information that a collector needs.
Many of them will implement this interface, so it's worth looking at for the curious: http://jikesrvm.org/docs/api/org/mmtk/plan/Simple.html
There is a fairly straightforward tutorial on adding a simple mark-sweep collector and a quasi-generational hybrid copying/mark-sweep collector here: http://jikesrvm.org/MMTk+Tutorial
And I was glad to see that there was a comprehensive test harness for jikes. One of the most difficult things with plai2 is figuring out how to test things in isolation and together, and how to track test program misbehavior to a specific collector fault. http://jikesrvm.org/The+MMTk+Test+Harness The harness looks to be invaluable.
There's a canonical document here: http://cs.anu.edu.au/~Robin.Garner/mmtk-guide.pdf. While it appears to be unfinished and very empty, it does helpfully explain the naming convention used throughout the API.
Plans
Plans are ways of bring together collection, allocation, and heap policies into something that can be used by the MMTK. A plan is a package with classes for each of these.
Spaces
A collection of regions of memory, each with a given allocation and collection policy.
Barriers
MMTK currently supports write, but not read barriers.
Policies
A policy is a region of memory with a collection and allocation strategy.
Date: 2014-10-16T00:11-0400
Author: Alex Kyte
Org version 7.9.3f with Emacs version 24
Validate XHTML 1.0