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