Mercurial > hg > graal-jvmci-8
comparison src/share/vm/utilities/workgroup.hpp @ 4095:bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
Summary: Select number of GC threads dynamically based on heap usage and number of Java threads
Reviewed-by: johnc, ysr, jcoomes
author | jmasa |
---|---|
date | Tue, 09 Aug 2011 10:16:01 -0700 |
parents | f08d439fab8c |
children | 441e946dc1af |
comparison
equal
deleted
inserted
replaced
4094:3a298e04d914 | 4095:bca17e38de00 |
---|---|
94 // ??? Or can the run method adjust priority as needed? | 94 // ??? Or can the run method adjust priority as needed? |
95 int _counter; | 95 int _counter; |
96 | 96 |
97 protected: | 97 protected: |
98 // Constructor and desctructor: only construct subclasses. | 98 // Constructor and desctructor: only construct subclasses. |
99 AbstractGangTask(const char* name) { | 99 AbstractGangTask(const char* name) |
100 { | |
100 NOT_PRODUCT(_name = name); | 101 NOT_PRODUCT(_name = name); |
101 _counter = 0; | 102 _counter = 0; |
102 } | 103 } |
103 virtual ~AbstractGangTask() { } | 104 virtual ~AbstractGangTask() { } |
105 | |
106 public: | |
104 }; | 107 }; |
105 | 108 |
106 class AbstractGangTaskWOopQueues : public AbstractGangTask { | 109 class AbstractGangTaskWOopQueues : public AbstractGangTask { |
107 OopTaskQueueSet* _queues; | 110 OopTaskQueueSet* _queues; |
108 ParallelTaskTerminator _terminator; | 111 ParallelTaskTerminator _terminator; |
114 terminator()->reset_for_reuse(active_workers); | 117 terminator()->reset_for_reuse(active_workers); |
115 } | 118 } |
116 OopTaskQueueSet* queues() { return _queues; } | 119 OopTaskQueueSet* queues() { return _queues; } |
117 }; | 120 }; |
118 | 121 |
122 | |
119 // Class AbstractWorkGang: | 123 // Class AbstractWorkGang: |
120 // An abstract class representing a gang of workers. | 124 // An abstract class representing a gang of workers. |
121 // You subclass this to supply an implementation of run_task(). | 125 // You subclass this to supply an implementation of run_task(). |
122 class AbstractWorkGang: public CHeapObj { | 126 class AbstractWorkGang: public CHeapObj { |
123 // Here's the public interface to this class. | 127 // Here's the public interface to this class. |
128 ~AbstractWorkGang(); | 132 ~AbstractWorkGang(); |
129 // Run a task, returns when the task is done (or terminated). | 133 // Run a task, returns when the task is done (or terminated). |
130 virtual void run_task(AbstractGangTask* task) = 0; | 134 virtual void run_task(AbstractGangTask* task) = 0; |
131 // Stop and terminate all workers. | 135 // Stop and terminate all workers. |
132 virtual void stop(); | 136 virtual void stop(); |
137 // Return true if more workers should be applied to the task. | |
138 virtual bool needs_more_workers() const { return true; } | |
133 public: | 139 public: |
134 // Debugging. | 140 // Debugging. |
135 const char* name() const; | 141 const char* name() const; |
136 protected: | 142 protected: |
137 // Initialize only instance data. | 143 // Initialize only instance data. |
285 | 291 |
286 public: | 292 public: |
287 AbstractWorkGang* gang() const { return _gang; } | 293 AbstractWorkGang* gang() const { return _gang; } |
288 }; | 294 }; |
289 | 295 |
296 // Dynamic number of worker threads | |
297 // | |
298 // This type of work gang is used to run different numbers of | |
299 // worker threads at different times. The | |
300 // number of workers run for a task is "_active_workers" | |
301 // instead of "_total_workers" in a WorkGang. The method | |
302 // "needs_more_workers()" returns true until "_active_workers" | |
303 // have been started and returns false afterwards. The | |
304 // implementation of "needs_more_workers()" in WorkGang always | |
305 // returns true so that all workers are started. The method | |
306 // "loop()" in GangWorker was modified to ask "needs_more_workers()" | |
307 // in its loop to decide if it should start working on a task. | |
308 // A worker in "loop()" waits for notification on the WorkGang | |
309 // monitor and execution of each worker as it checks for work | |
310 // is serialized via the same monitor. The "needs_more_workers()" | |
311 // call is serialized and additionally the calculation for the | |
312 // "part" (effectively the worker id for executing the task) is | |
313 // serialized to give each worker a unique "part". Workers that | |
314 // are not needed for this tasks (i.e., "_active_workers" have | |
315 // been started before it, continue to wait for work. | |
316 | |
290 class FlexibleWorkGang: public WorkGang { | 317 class FlexibleWorkGang: public WorkGang { |
318 // The currently active workers in this gang. | |
319 // This is a number that is dynamically adjusted | |
320 // and checked in the run_task() method at each invocation. | |
321 // As described above _active_workers determines the number | |
322 // of threads started on a task. It must also be used to | |
323 // determine completion. | |
324 | |
291 protected: | 325 protected: |
292 int _active_workers; | 326 int _active_workers; |
293 public: | 327 public: |
294 // Constructor and destructor. | 328 // Constructor and destructor. |
329 // Initialize active_workers to a minimum value. Setting it to | |
330 // the parameter "workers" will initialize it to a maximum | |
331 // value which is not desirable. | |
295 FlexibleWorkGang(const char* name, int workers, | 332 FlexibleWorkGang(const char* name, int workers, |
296 bool are_GC_task_threads, | 333 bool are_GC_task_threads, |
297 bool are_ConcurrentGC_threads) : | 334 bool are_ConcurrentGC_threads) : |
298 WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads) { | 335 WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads), |
299 _active_workers = ParallelGCThreads; | 336 _active_workers(UseDynamicNumberOfGCThreads ? 1 : ParallelGCThreads) {}; |
300 }; | |
301 // Accessors for fields | 337 // Accessors for fields |
302 virtual int active_workers() const { return _active_workers; } | 338 virtual int active_workers() const { return _active_workers; } |
303 void set_active_workers(int v) { _active_workers = v; } | 339 void set_active_workers(int v) { |
340 assert(v <= _total_workers, | |
341 "Trying to set more workers active than there are"); | |
342 _active_workers = MIN2(v, _total_workers); | |
343 assert(v != 0, "Trying to set active workers to 0"); | |
344 _active_workers = MAX2(1, _active_workers); | |
345 assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers, | |
346 "Unless dynamic should use total workers"); | |
347 } | |
348 virtual void run_task(AbstractGangTask* task); | |
349 virtual bool needs_more_workers() const { | |
350 return _started_workers < _active_workers; | |
351 } | |
304 }; | 352 }; |
305 | 353 |
306 // Work gangs in garbage collectors: 2009-06-10 | 354 // Work gangs in garbage collectors: 2009-06-10 |
307 // | 355 // |
308 // SharedHeap - work gang for stop-the-world parallel collection. | 356 // SharedHeap - work gang for stop-the-world parallel collection. |
355 // enumeration type. | 403 // enumeration type. |
356 | 404 |
357 class SubTasksDone: public CHeapObj { | 405 class SubTasksDone: public CHeapObj { |
358 jint* _tasks; | 406 jint* _tasks; |
359 int _n_tasks; | 407 int _n_tasks; |
408 // _n_threads is used to determine when a sub task is done. | |
409 // It does not control how many threads will execute the subtask | |
410 // but must be initialized to the number that do execute the task | |
411 // in order to correctly decide when the subtask is done (all the | |
412 // threads working on the task have finished). | |
360 int _n_threads; | 413 int _n_threads; |
361 jint _threads_completed; | 414 jint _threads_completed; |
362 #ifdef ASSERT | 415 #ifdef ASSERT |
363 volatile jint _claimed; | 416 volatile jint _claimed; |
364 #endif | 417 #endif |