Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/shared/gcTimer.cpp
38920 views
/*1* Copyright (c) 2012, 2013, 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#include "precompiled.hpp"25#include "gc_implementation/shared/gcTimer.hpp"26#include "utilities/growableArray.hpp"27#include "utilities/ticks.hpp"2829// the "time" parameter for most functions30// has a default value set by Ticks::now()3132void GCTimer::register_gc_start(const Ticks& time) {33_time_partitions.clear();34_gc_start = time;35}3637void GCTimer::register_gc_end(const Ticks& time) {38assert(!_time_partitions.has_active_phases(),39"We should have ended all started phases, before ending the GC");4041_gc_end = time;42}4344void GCTimer::register_gc_pause_start(const char* name, const Ticks& time) {45_time_partitions.report_gc_phase_start(name, time);46}4748void GCTimer::register_gc_pause_end(const Ticks& time) {49_time_partitions.report_gc_phase_end(time);50}5152void GCTimer::register_gc_phase_start(const char* name, const Ticks& time) {53_time_partitions.report_gc_phase_start(name, time);54}5556void GCTimer::register_gc_phase_end(const Ticks& time) {57_time_partitions.report_gc_phase_end(time);58}5960void STWGCTimer::register_gc_start(const Ticks& time) {61GCTimer::register_gc_start(time);62register_gc_pause_start("GC Pause", time);63}6465void STWGCTimer::register_gc_end(const Ticks& time) {66register_gc_pause_end(time);67GCTimer::register_gc_end(time);68}6970void ConcurrentGCTimer::register_gc_pause_start(const char* name) {71GCTimer::register_gc_pause_start(name);72}7374void ConcurrentGCTimer::register_gc_pause_end() {75GCTimer::register_gc_pause_end();76}7778void PhasesStack::clear() {79_next_phase_level = 0;80}8182void PhasesStack::push(int phase_index) {83assert(_next_phase_level < PHASE_LEVELS, "Overflow");8485_phase_indices[_next_phase_level] = phase_index;8687_next_phase_level++;88}8990int PhasesStack::pop() {91assert(_next_phase_level > 0, "Underflow");9293_next_phase_level--;9495return _phase_indices[_next_phase_level];96}9798int PhasesStack::count() const {99return _next_phase_level;100}101102103TimePartitions::TimePartitions() {104_phases = new (ResourceObj::C_HEAP, mtGC) GrowableArray<PausePhase>(INITIAL_CAPACITY, true, mtGC);105clear();106}107108TimePartitions::~TimePartitions() {109delete _phases;110_phases = NULL;111}112113void TimePartitions::clear() {114_phases->clear();115_active_phases.clear();116_sum_of_pauses = Tickspan();117_longest_pause = Tickspan();118}119120void TimePartitions::report_gc_phase_start(const char* name, const Ticks& time) {121assert(_phases->length() <= 1000, "Too many recored phases?");122123int level = _active_phases.count();124125PausePhase phase;126phase.set_level(level);127phase.set_name(name);128phase.set_start(time);129130int index = _phases->append(phase);131132_active_phases.push(index);133}134135void TimePartitions::update_statistics(GCPhase* phase) {136// FIXME: This should only be done for pause phases137if (phase->level() == 0) {138const Tickspan pause = phase->end() - phase->start();139_sum_of_pauses += pause;140_longest_pause = MAX2(pause, _longest_pause);141}142}143144void TimePartitions::report_gc_phase_end(const Ticks& time) {145int phase_index = _active_phases.pop();146GCPhase* phase = _phases->adr_at(phase_index);147phase->set_end(time);148update_statistics(phase);149}150151int TimePartitions::num_phases() const {152return _phases->length();153}154155GCPhase* TimePartitions::phase_at(int index) const {156assert(index >= 0, "Out of bounds");157assert(index < _phases->length(), "Out of bounds");158159return _phases->adr_at(index);160}161162bool TimePartitions::has_active_phases() {163return _active_phases.count() > 0;164}165166bool TimePartitionPhasesIterator::has_next() {167return _next < _time_partitions->num_phases();168}169170GCPhase* TimePartitionPhasesIterator::next() {171assert(has_next(), "Must have phases left");172return _time_partitions->phase_at(_next++);173}174175176/////////////// Unit tests ///////////////177178#ifndef PRODUCT179180class TimePartitionPhasesIteratorTest {181public:182static void all() {183one_pause();184two_pauses();185one_sub_pause_phase();186many_sub_pause_phases();187many_sub_pause_phases2();188max_nested_pause_phases();189}190191static void validate_pause_phase(GCPhase* phase, int level, const char* name, const Ticks& start, const Ticks& end) {192assert(phase->level() == level, "Incorrect level");193assert(strcmp(phase->name(), name) == 0, "Incorrect name");194assert(phase->start() == start, "Incorrect start");195assert(phase->end() == end, "Incorrect end");196}197198static void one_pause() {199TimePartitions time_partitions;200time_partitions.report_gc_phase_start("PausePhase", 2);201time_partitions.report_gc_phase_end(8);202203TimePartitionPhasesIterator iter(&time_partitions);204205validate_pause_phase(iter.next(), 0, "PausePhase", 2, 8);206assert(time_partitions.sum_of_pauses() == Ticks(8) - Ticks(2), "Incorrect");207assert(time_partitions.longest_pause() == Ticks(8) - Ticks(2), "Incorrect");208209assert(!iter.has_next(), "Too many elements");210}211212static void two_pauses() {213TimePartitions time_partitions;214time_partitions.report_gc_phase_start("PausePhase1", 2);215time_partitions.report_gc_phase_end(3);216time_partitions.report_gc_phase_start("PausePhase2", 4);217time_partitions.report_gc_phase_end(6);218219TimePartitionPhasesIterator iter(&time_partitions);220221validate_pause_phase(iter.next(), 0, "PausePhase1", 2, 3);222validate_pause_phase(iter.next(), 0, "PausePhase2", 4, 6);223224assert(time_partitions.sum_of_pauses() == Ticks(3) - Ticks(0), "Incorrect");225assert(time_partitions.longest_pause() == Ticks(2) - Ticks(0), "Incorrect");226227assert(!iter.has_next(), "Too many elements");228}229230static void one_sub_pause_phase() {231TimePartitions time_partitions;232time_partitions.report_gc_phase_start("PausePhase", 2);233time_partitions.report_gc_phase_start("SubPhase", 3);234time_partitions.report_gc_phase_end(4);235time_partitions.report_gc_phase_end(5);236237TimePartitionPhasesIterator iter(&time_partitions);238239validate_pause_phase(iter.next(), 0, "PausePhase", 2, 5);240validate_pause_phase(iter.next(), 1, "SubPhase", 3, 4);241242assert(time_partitions.sum_of_pauses() == Ticks(3) - Ticks(0), "Incorrect");243assert(time_partitions.longest_pause() == Ticks(3) - Ticks(0), "Incorrect");244245assert(!iter.has_next(), "Too many elements");246}247248static void max_nested_pause_phases() {249TimePartitions time_partitions;250time_partitions.report_gc_phase_start("PausePhase", 2);251time_partitions.report_gc_phase_start("SubPhase1", 3);252time_partitions.report_gc_phase_start("SubPhase2", 4);253time_partitions.report_gc_phase_start("SubPhase3", 5);254time_partitions.report_gc_phase_end(6);255time_partitions.report_gc_phase_end(7);256time_partitions.report_gc_phase_end(8);257time_partitions.report_gc_phase_end(9);258259TimePartitionPhasesIterator iter(&time_partitions);260261validate_pause_phase(iter.next(), 0, "PausePhase", 2, 9);262validate_pause_phase(iter.next(), 1, "SubPhase1", 3, 8);263validate_pause_phase(iter.next(), 2, "SubPhase2", 4, 7);264validate_pause_phase(iter.next(), 3, "SubPhase3", 5, 6);265266assert(time_partitions.sum_of_pauses() == Ticks(7) - Ticks(0), "Incorrect");267assert(time_partitions.longest_pause() == Ticks(7) - Ticks(0), "Incorrect");268269assert(!iter.has_next(), "Too many elements");270}271272static void many_sub_pause_phases() {273TimePartitions time_partitions;274time_partitions.report_gc_phase_start("PausePhase", 2);275276time_partitions.report_gc_phase_start("SubPhase1", 3);277time_partitions.report_gc_phase_end(4);278time_partitions.report_gc_phase_start("SubPhase2", 5);279time_partitions.report_gc_phase_end(6);280time_partitions.report_gc_phase_start("SubPhase3", 7);281time_partitions.report_gc_phase_end(8);282time_partitions.report_gc_phase_start("SubPhase4", 9);283time_partitions.report_gc_phase_end(10);284285time_partitions.report_gc_phase_end(11);286287TimePartitionPhasesIterator iter(&time_partitions);288289validate_pause_phase(iter.next(), 0, "PausePhase", 2, 11);290validate_pause_phase(iter.next(), 1, "SubPhase1", 3, 4);291validate_pause_phase(iter.next(), 1, "SubPhase2", 5, 6);292validate_pause_phase(iter.next(), 1, "SubPhase3", 7, 8);293validate_pause_phase(iter.next(), 1, "SubPhase4", 9, 10);294295assert(time_partitions.sum_of_pauses() == Ticks(9) - Ticks(0), "Incorrect");296assert(time_partitions.longest_pause() == Ticks(9) - Ticks(0), "Incorrect");297298assert(!iter.has_next(), "Too many elements");299}300301static void many_sub_pause_phases2() {302TimePartitions time_partitions;303time_partitions.report_gc_phase_start("PausePhase", 2);304305time_partitions.report_gc_phase_start("SubPhase1", 3);306time_partitions.report_gc_phase_start("SubPhase11", 4);307time_partitions.report_gc_phase_end(5);308time_partitions.report_gc_phase_start("SubPhase12", 6);309time_partitions.report_gc_phase_end(7);310time_partitions.report_gc_phase_end(8);311time_partitions.report_gc_phase_start("SubPhase2", 9);312time_partitions.report_gc_phase_start("SubPhase21", 10);313time_partitions.report_gc_phase_end(11);314time_partitions.report_gc_phase_start("SubPhase22", 12);315time_partitions.report_gc_phase_end(13);316time_partitions.report_gc_phase_end(14);317time_partitions.report_gc_phase_start("SubPhase3", 15);318time_partitions.report_gc_phase_end(16);319320time_partitions.report_gc_phase_end(17);321322TimePartitionPhasesIterator iter(&time_partitions);323324validate_pause_phase(iter.next(), 0, "PausePhase", 2, 17);325validate_pause_phase(iter.next(), 1, "SubPhase1", 3, 8);326validate_pause_phase(iter.next(), 2, "SubPhase11", 4, 5);327validate_pause_phase(iter.next(), 2, "SubPhase12", 6, 7);328validate_pause_phase(iter.next(), 1, "SubPhase2", 9, 14);329validate_pause_phase(iter.next(), 2, "SubPhase21", 10, 11);330validate_pause_phase(iter.next(), 2, "SubPhase22", 12, 13);331validate_pause_phase(iter.next(), 1, "SubPhase3", 15, 16);332333assert(time_partitions.sum_of_pauses() == Ticks(15) - Ticks(0), "Incorrect");334assert(time_partitions.longest_pause() == Ticks(15) - Ticks(0), "Incorrect");335336assert(!iter.has_next(), "Too many elements");337}338};339340class GCTimerTest {341public:342static void all() {343gc_start();344gc_end();345}346347static void gc_start() {348GCTimer gc_timer;349gc_timer.register_gc_start(1);350351assert(gc_timer.gc_start() == Ticks(1), "Incorrect");352}353354static void gc_end() {355GCTimer gc_timer;356gc_timer.register_gc_start(1);357gc_timer.register_gc_end(2);358359assert(gc_timer.gc_end() == Ticks(2), "Incorrect");360}361};362363void GCTimerAllTest::all() {364GCTimerTest::all();365TimePartitionPhasesIteratorTest::all();366}367368#endif369370371