CPU manager: user-defined
invoke consume(long c)
Per-thread accounting objects: fixed structure
increment consumption invoke triggerConsume()
Multi-threaded Java component (resource-aware or legacy code): transformed for CPU accounting and control
Figure 1. Runtime Organization of a CPU-Managed Component.
individual CPU accounting objects by incrementing an integer field called consumption.
The CPU accounting scheme of J-RAF2 does not rely on a dedi- cated supervisor thread. Instead, the execution of management tasks is distributed among all threads in the system. Periodically, each thread invokes triggerConsume(), which itself calls consume(long c) on the CPU Manager (if any), in order to aggregate the collected informa- tion concerning its own CPU consumption within an account that is shared by all threads of the same software component. While inside consume(long c), each thread has the opportunity to execute manage- ment code, such as scheduling decisions, to ensure that a given resource quota is not exceeded. E.g., the thread may terminate the component if there is a hard limit on the total number of bytecode instructions it may execute, or it may delay itself (i.e., put itself to sleep) in order to meet a restriction placed on the execution rate.
We call our approach self-accounting, because each thread accounts for its own CPU consumption. Self-accounting is essential for the porta- bility of management code, since its activation does not rely on the under-specified scheduling of the JVM. Moreover, when a thread man- ages itself, we avoid many deadlocking and access rights issues that arise with a dedicated supervisor thread, since the consume(long c) invocation is synchronous (i.e., blocking), and executed directly by the thread to which the policy applies.