1 /*
2 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHMMUTRACKER_HPP
26 #define SHARE_GC_SHENANDOAH_SHENANDOAHMMUTRACKER_HPP
27
28 #include "utilities/numberSeq.hpp"
29
30 class ShenandoahGeneration;
31 class ShenandoahMmuTask;
32
33 /**
34 * This class is responsible for tracking and adjusting the minimum mutator
35 * utilization (MMU). MMU is defined as the percentage of CPU time available
36 * to mutator threads over an arbitrary, fixed interval of time. This interval
37 * defaults to 5 seconds and is configured by GCPauseIntervalMillis. The class
38 * maintains a decaying average of the last 10 values. The MMU is measured
39 * by summing all of the time given to the GC threads and comparing this to
40 * the total CPU time for the process. There are OS APIs to support this on
41 * all major platforms.
42 *
43 * The time spent by GC threads is attributed to the young or old generation.
44 * The time given to the controller and regulator threads is attributed to the
45 * global generation. At the end of every collection, the average MMU is inspected.
46 * If it is below `GCTimeRatio`, this class will attempt to increase the capacity
47 * of the generation that is consuming the most CPU time. The assumption being
48 * that increasing memory will reduce the collection frequency and raise the
49 * MMU.
50 */
51 class ShenandoahMmuTracker {
52 private:
53 // These variables hold recent snapshots of cumulative quantities that are used for calculating
54 // CPU time consumed by GC and mutator threads during each GC cycle.
55 double _most_recent_timestamp;
56 double _most_recent_gc_time;
57 double _most_recent_gcu;
58 double _most_recent_mutator_time;
59 double _most_recent_mu;
60
61 // These variables hold recent snapshots of cumulative quantities that are used for reporting
62 // periodic consumption of CPU time by GC and mutator threads.
63 double _most_recent_periodic_time_stamp;
64 double _most_recent_periodic_gc_time;
65 double _most_recent_periodic_mutator_time;
66
67 size_t _most_recent_gcid;
68 uint _active_processors;
69
70 bool _most_recent_is_full;
71
72 ShenandoahMmuTask* _mmu_periodic_task;
73 TruncatedSeq _mmu_average;
74
75 void update_utilization(size_t gcid, const char* msg);
76 static void fetch_cpu_times(double &gc_time, double &mutator_time);
77
78 public:
79 explicit ShenandoahMmuTracker();
80 ~ShenandoahMmuTracker();
81
82 // This enrolls the periodic task after everything is initialized.
83 void initialize();
84
85 // At completion of each GC cycle (not including interrupted cycles), we invoke one of the following to record the
86 // GC utilization during this cycle. Incremental efforts spent in an interrupted GC cycle will be accumulated into
87 // the CPU time reports for the subsequent completed [degenerated or full] GC cycle.
88 //
89 // We may redundantly record degen and full in the case that a degen upgrades to full. When this happens, we will invoke
90 // both record_full() and record_degenerated() with the same value of gcid. record_full() is called first and the log
91 // reports such a cycle as a FULL cycle.
92 void record_young(size_t gcid);
93 void record_global(size_t gcid);
94 void record_bootstrap(size_t gcid);
95 void record_old_marking_increment(bool old_marking_done);
96 void record_mixed(size_t gcid);
97 void record_full(size_t gcid);
98 void record_degenerated(size_t gcid, bool is_old_boostrap);
99
100 // This is called by the periodic task timer. The interval is defined by
101 // GCPauseIntervalMillis and defaults to 5 seconds. This method computes
102 // the MMU over the elapsed interval and records it in a running average.
103 void report();
104
105 // Unenrolls the periodic task that collects CPU utilization for GC threads. This must happen _before_ the
106 // gc threads are stopped and terminated.
107 void stop() const;
108 };
109
110 #endif //SHARE_GC_SHENANDOAH_SHENANDOAHMMUTRACKER_HPP