Path: blob/master/src/hotspot/share/gc/g1/g1BatchedGangTask.hpp
40961 views
/*1* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_GC_G1_G1BATCHEDGANGTASK_HPP25#define SHARE_GC_G1_G1BATCHEDGANGTASK_HPP2627#include "gc/g1/g1GCPhaseTimes.hpp"28#include "gc/shared/workgroup.hpp"29#include "memory/allocation.hpp"3031template <typename E, MEMFLAGS F>32class GrowableArrayCHeap;3334// G1AbstractSubTask represents a task to be performed either within a35// G1BatchedGangTask running on a single worker ("serially") or multiple workers36// ("in parallel"). A G1AbstractSubTask is always associated with a phase tag37// that is used to automatically store timing information.38//39// A "serial" task is some piece of work that either can not be parallelized40// easily, or is typically so short that parallelization is not worth the effort.41// Current examples would be summarizing per worker thread information gathered42// during garbage collection (e.g. Merge PSS work).43//44// A "parallel" task could be some large amount of work that typically naturally45// splits across the heap in some way. Current examples would be clearing the46// card table.47//48// See G1BatchedGangTask for information on execution.49class G1AbstractSubTask : public CHeapObj<mtGC> {50G1GCPhaseTimes::GCParPhases _tag;5152NONCOPYABLE(G1AbstractSubTask);5354protected:55// Record work item for this tag in G1GCPhaseTimes.56void record_work_item(uint worker_id, uint index, size_t count);5758public:59// Worker cost for "almost no work" to be done.60static constexpr double AlmostNoWork = 0.01;6162G1AbstractSubTask(G1GCPhaseTimes::GCParPhases tag) : _tag(tag) { }63virtual ~G1AbstractSubTask() { }6465// How many workers (threads) would this task be able to keep busy for at least66// as long as to amortize worker startup costs.67// Called by G1BatchedGangTask to determine total number of workers.68virtual double worker_cost() const = 0;6970// Called by G1BatchedGangTask to provide information about the the maximum71// number of workers for all subtasks after it has been determined.72virtual void set_max_workers(uint max_workers) { }7374// Perform the actual work. Gets the worker id it is run on passed in.75virtual void do_work(uint worker_id) = 0;7677// Tag for this G1AbstractSubTask.78G1GCPhaseTimes::GCParPhases tag() const { return _tag; }79// Human readable name derived from the tag.80const char* name() const;81};8283// G1BatchedGangTask runs a set of G1AbstractSubTask using a work gang.84//85// Subclasses of this class add their G1AbstractSubTasks into either the list86// of "serial" or the list of "parallel" tasks. They are supposed to be the owners87// of the G1AbstractSubTasks.88//89// Eg. the constructor contains code like the following:90//91// add_serial_task(new SomeSubTask());92// [...]93// add_parallel_task(new SomeOtherSubTask());94// [...]95//96// During execution in the work gang, this class will make sure that the "serial"97// tasks are executed by a single worker exactly once, but different "serial"98// tasks may be executed in parallel using different workers. "Parallel" tasks'99// do_work() method may be called by different workers passing a different100// worker_id at the same time, but at most once per given worker_id.101//102// There is also no guarantee that G1AbstractSubTasks::do_work() of different tasks103// are actually run in parallel.104//105// The current implementation assumes that constructors and destructors of the106// G1AbstractSubTasks can executed in the constructor/destructor of an instance107// of this class.108//109// The constructor, destructor and the do_work() methods from different110// G1AbstractSubTasks may run in any order so they must not have any111// dependencies at all.112//113// For a given G1AbstractSubTask T call order of its methods are as follows:114//115// 1) T()116// 2) T::thread_usage()117// 3) T::set_max_workers()118// 4) T::do_work() // potentially in parallel with any other registered G1AbstractSubTask119// 5) ~T()120//121class G1BatchedGangTask : public AbstractGangTask {122volatile int _num_serial_tasks_done;123G1GCPhaseTimes* _phase_times;124125bool try_claim_serial_task(int& task);126127NONCOPYABLE(G1BatchedGangTask);128129GrowableArrayCHeap<G1AbstractSubTask*, mtGC> _serial_tasks;130GrowableArrayCHeap<G1AbstractSubTask*, mtGC> _parallel_tasks;131132protected:133void add_serial_task(G1AbstractSubTask* task);134void add_parallel_task(G1AbstractSubTask* task);135136G1BatchedGangTask(const char* name, G1GCPhaseTimes* phase_times);137138public:139void work(uint worker_id) override;140141// How many workers can this gang task keep busy and should be started for142// "optimal" performance.143uint num_workers_estimate() const;144// Informs the G1AbstractSubTasks about that we will start execution with the145// given number of workers.146void set_max_workers(uint max_workers);147148~G1BatchedGangTask();149};150151#endif // SHARE_GC_G1_G1BATCHEDGANGTASK_HPP152153