src/share/vm/gc_implementation/shared/gcTimer.cpp

Thu, 13 Feb 2014 17:44:39 +0100

author
stefank
date
Thu, 13 Feb 2014 17:44:39 +0100
changeset 6971
7426d8d76305
parent 6131
86e6d691f2e1
child 6876
710a3c8b516e
child 9858
b985cbb00e68
permissions
-rw-r--r--

8034761: Remove the do_code_roots parameter from process_strong_roots
Reviewed-by: tschatzl, mgerdin, jmasa

     1 /*
     2  * Copyright (c) 2012, 2013, Oracle and/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  */
    25 #include "precompiled.hpp"
    26 #include "gc_implementation/shared/gcTimer.hpp"
    27 #include "utilities/growableArray.hpp"
    28 #include "utilities/ticks.inline.hpp"
    30 // the "time" parameter for most functions
    31 // has a default value set by Ticks::now()
    33 void GCTimer::register_gc_start(const Ticks& time) {
    34   _time_partitions.clear();
    35   _gc_start = time;
    36 }
    38 void GCTimer::register_gc_end(const Ticks& time) {
    39   assert(!_time_partitions.has_active_phases(),
    40       "We should have ended all started phases, before ending the GC");
    42   _gc_end = time;
    43 }
    45 void GCTimer::register_gc_pause_start(const char* name, const Ticks& time) {
    46   _time_partitions.report_gc_phase_start(name, time);
    47 }
    49 void GCTimer::register_gc_pause_end(const Ticks& time) {
    50   _time_partitions.report_gc_phase_end(time);
    51 }
    53 void GCTimer::register_gc_phase_start(const char* name, const Ticks& time) {
    54   _time_partitions.report_gc_phase_start(name, time);
    55 }
    57 void GCTimer::register_gc_phase_end(const Ticks& time) {
    58   _time_partitions.report_gc_phase_end(time);
    59 }
    61 void STWGCTimer::register_gc_start(const Ticks& time) {
    62   GCTimer::register_gc_start(time);
    63   register_gc_pause_start("GC Pause", time);
    64 }
    66 void STWGCTimer::register_gc_end(const Ticks& time) {
    67   register_gc_pause_end(time);
    68   GCTimer::register_gc_end(time);
    69 }
    71 void ConcurrentGCTimer::register_gc_pause_start(const char* name) {
    72   GCTimer::register_gc_pause_start(name);
    73 }
    75 void ConcurrentGCTimer::register_gc_pause_end() {
    76   GCTimer::register_gc_pause_end();
    77 }
    79 void PhasesStack::clear() {
    80   _next_phase_level = 0;
    81 }
    83 void PhasesStack::push(int phase_index) {
    84   assert(_next_phase_level < PHASE_LEVELS, "Overflow");
    86   _phase_indices[_next_phase_level] = phase_index;
    88   _next_phase_level++;
    89 }
    91 int PhasesStack::pop() {
    92   assert(_next_phase_level > 0, "Underflow");
    94   _next_phase_level--;
    96   return _phase_indices[_next_phase_level];
    97 }
    99 int PhasesStack::count() const {
   100   return _next_phase_level;
   101 }
   104 TimePartitions::TimePartitions() {
   105   _phases = new (ResourceObj::C_HEAP, mtGC) GrowableArray<PausePhase>(INITIAL_CAPACITY, true, mtGC);
   106   clear();
   107 }
   109 TimePartitions::~TimePartitions() {
   110   delete _phases;
   111   _phases = NULL;
   112 }
   114 void TimePartitions::clear() {
   115   _phases->clear();
   116   _active_phases.clear();
   117   _sum_of_pauses = Tickspan();
   118   _longest_pause = Tickspan();
   119 }
   121 void TimePartitions::report_gc_phase_start(const char* name, const Ticks& time) {
   122   assert(_phases->length() <= 1000, "Too many recored phases?");
   124   int level = _active_phases.count();
   126   PausePhase phase;
   127   phase.set_level(level);
   128   phase.set_name(name);
   129   phase.set_start(time);
   131   int index = _phases->append(phase);
   133   _active_phases.push(index);
   134 }
   136 void TimePartitions::update_statistics(GCPhase* phase) {
   137   // FIXME: This should only be done for pause phases
   138   if (phase->level() == 0) {
   139     const Tickspan pause = phase->end() - phase->start();
   140     _sum_of_pauses += pause;
   141     _longest_pause = MAX2(pause, _longest_pause);
   142   }
   143 }
   145 void TimePartitions::report_gc_phase_end(const Ticks& time) {
   146   int phase_index = _active_phases.pop();
   147   GCPhase* phase = _phases->adr_at(phase_index);
   148   phase->set_end(time);
   149   update_statistics(phase);
   150 }
   152 int TimePartitions::num_phases() const {
   153   return _phases->length();
   154 }
   156 GCPhase* TimePartitions::phase_at(int index) const {
   157   assert(index >= 0, "Out of bounds");
   158   assert(index < _phases->length(), "Out of bounds");
   160   return _phases->adr_at(index);
   161 }
   163 bool TimePartitions::has_active_phases() {
   164   return _active_phases.count() > 0;
   165 }
   167 bool TimePartitionPhasesIterator::has_next() {
   168   return _next < _time_partitions->num_phases();
   169 }
   171 GCPhase* TimePartitionPhasesIterator::next() {
   172   assert(has_next(), "Must have phases left");
   173   return _time_partitions->phase_at(_next++);
   174 }
   177 /////////////// Unit tests ///////////////
   179 #ifndef PRODUCT
   181 class TimePartitionPhasesIteratorTest {
   182  public:
   183   static void all() {
   184     one_pause();
   185     two_pauses();
   186     one_sub_pause_phase();
   187     many_sub_pause_phases();
   188     many_sub_pause_phases2();
   189     max_nested_pause_phases();
   190   }
   192   static void validate_pause_phase(GCPhase* phase, int level, const char* name, const Ticks& start, const Ticks& end) {
   193     assert(phase->level() == level, "Incorrect level");
   194     assert(strcmp(phase->name(), name) == 0, "Incorrect name");
   195     assert(phase->start() == start, "Incorrect start");
   196     assert(phase->end() == end, "Incorrect end");
   197   }
   199   static void one_pause() {
   200     TimePartitions time_partitions;
   201     time_partitions.report_gc_phase_start("PausePhase", 2);
   202     time_partitions.report_gc_phase_end(8);
   204     TimePartitionPhasesIterator iter(&time_partitions);
   206     validate_pause_phase(iter.next(), 0, "PausePhase", 2, 8);
   207     assert(time_partitions.sum_of_pauses() == Ticks(8) - Ticks(2), "Incorrect");
   208     assert(time_partitions.longest_pause() == Ticks(8) - Ticks(2), "Incorrect");
   210     assert(!iter.has_next(), "Too many elements");
   211   }
   213   static void two_pauses() {
   214     TimePartitions time_partitions;
   215     time_partitions.report_gc_phase_start("PausePhase1", 2);
   216     time_partitions.report_gc_phase_end(3);
   217     time_partitions.report_gc_phase_start("PausePhase2", 4);
   218     time_partitions.report_gc_phase_end(6);
   220     TimePartitionPhasesIterator iter(&time_partitions);
   222     validate_pause_phase(iter.next(), 0, "PausePhase1", 2, 3);
   223     validate_pause_phase(iter.next(), 0, "PausePhase2", 4, 6);
   225     assert(time_partitions.sum_of_pauses() == Ticks(3) - Ticks(0), "Incorrect");
   226     assert(time_partitions.longest_pause() == Ticks(2) - Ticks(0), "Incorrect");
   228     assert(!iter.has_next(), "Too many elements");
   229   }
   231   static void one_sub_pause_phase() {
   232     TimePartitions time_partitions;
   233     time_partitions.report_gc_phase_start("PausePhase", 2);
   234     time_partitions.report_gc_phase_start("SubPhase", 3);
   235     time_partitions.report_gc_phase_end(4);
   236     time_partitions.report_gc_phase_end(5);
   238     TimePartitionPhasesIterator iter(&time_partitions);
   240     validate_pause_phase(iter.next(), 0, "PausePhase", 2, 5);
   241     validate_pause_phase(iter.next(), 1, "SubPhase", 3, 4);
   243     assert(time_partitions.sum_of_pauses() == Ticks(3) - Ticks(0), "Incorrect");
   244     assert(time_partitions.longest_pause() == Ticks(3) - Ticks(0), "Incorrect");
   246     assert(!iter.has_next(), "Too many elements");
   247   }
   249   static void max_nested_pause_phases() {
   250     TimePartitions time_partitions;
   251     time_partitions.report_gc_phase_start("PausePhase", 2);
   252     time_partitions.report_gc_phase_start("SubPhase1", 3);
   253     time_partitions.report_gc_phase_start("SubPhase2", 4);
   254     time_partitions.report_gc_phase_start("SubPhase3", 5);
   255     time_partitions.report_gc_phase_end(6);
   256     time_partitions.report_gc_phase_end(7);
   257     time_partitions.report_gc_phase_end(8);
   258     time_partitions.report_gc_phase_end(9);
   260     TimePartitionPhasesIterator iter(&time_partitions);
   262     validate_pause_phase(iter.next(), 0, "PausePhase", 2, 9);
   263     validate_pause_phase(iter.next(), 1, "SubPhase1", 3, 8);
   264     validate_pause_phase(iter.next(), 2, "SubPhase2", 4, 7);
   265     validate_pause_phase(iter.next(), 3, "SubPhase3", 5, 6);
   267     assert(time_partitions.sum_of_pauses() == Ticks(7) - Ticks(0), "Incorrect");
   268     assert(time_partitions.longest_pause() == Ticks(7) - Ticks(0), "Incorrect");
   270     assert(!iter.has_next(), "Too many elements");
   271   }
   273   static void many_sub_pause_phases() {
   274     TimePartitions time_partitions;
   275     time_partitions.report_gc_phase_start("PausePhase", 2);
   277     time_partitions.report_gc_phase_start("SubPhase1", 3);
   278     time_partitions.report_gc_phase_end(4);
   279     time_partitions.report_gc_phase_start("SubPhase2", 5);
   280     time_partitions.report_gc_phase_end(6);
   281     time_partitions.report_gc_phase_start("SubPhase3", 7);
   282     time_partitions.report_gc_phase_end(8);
   283     time_partitions.report_gc_phase_start("SubPhase4", 9);
   284     time_partitions.report_gc_phase_end(10);
   286     time_partitions.report_gc_phase_end(11);
   288     TimePartitionPhasesIterator iter(&time_partitions);
   290     validate_pause_phase(iter.next(), 0, "PausePhase", 2, 11);
   291     validate_pause_phase(iter.next(), 1, "SubPhase1", 3, 4);
   292     validate_pause_phase(iter.next(), 1, "SubPhase2", 5, 6);
   293     validate_pause_phase(iter.next(), 1, "SubPhase3", 7, 8);
   294     validate_pause_phase(iter.next(), 1, "SubPhase4", 9, 10);
   296     assert(time_partitions.sum_of_pauses() == Ticks(9) - Ticks(0), "Incorrect");
   297     assert(time_partitions.longest_pause() == Ticks(9) - Ticks(0), "Incorrect");
   299     assert(!iter.has_next(), "Too many elements");
   300   }
   302   static void many_sub_pause_phases2() {
   303     TimePartitions time_partitions;
   304     time_partitions.report_gc_phase_start("PausePhase", 2);
   306     time_partitions.report_gc_phase_start("SubPhase1", 3);
   307     time_partitions.report_gc_phase_start("SubPhase11", 4);
   308     time_partitions.report_gc_phase_end(5);
   309     time_partitions.report_gc_phase_start("SubPhase12", 6);
   310     time_partitions.report_gc_phase_end(7);
   311     time_partitions.report_gc_phase_end(8);
   312     time_partitions.report_gc_phase_start("SubPhase2", 9);
   313     time_partitions.report_gc_phase_start("SubPhase21", 10);
   314     time_partitions.report_gc_phase_end(11);
   315     time_partitions.report_gc_phase_start("SubPhase22", 12);
   316     time_partitions.report_gc_phase_end(13);
   317     time_partitions.report_gc_phase_end(14);
   318     time_partitions.report_gc_phase_start("SubPhase3", 15);
   319     time_partitions.report_gc_phase_end(16);
   321     time_partitions.report_gc_phase_end(17);
   323     TimePartitionPhasesIterator iter(&time_partitions);
   325     validate_pause_phase(iter.next(), 0, "PausePhase", 2, 17);
   326     validate_pause_phase(iter.next(), 1, "SubPhase1", 3, 8);
   327     validate_pause_phase(iter.next(), 2, "SubPhase11", 4, 5);
   328     validate_pause_phase(iter.next(), 2, "SubPhase12", 6, 7);
   329     validate_pause_phase(iter.next(), 1, "SubPhase2", 9, 14);
   330     validate_pause_phase(iter.next(), 2, "SubPhase21", 10, 11);
   331     validate_pause_phase(iter.next(), 2, "SubPhase22", 12, 13);
   332     validate_pause_phase(iter.next(), 1, "SubPhase3", 15, 16);
   334     assert(time_partitions.sum_of_pauses() == Ticks(15) - Ticks(0), "Incorrect");
   335     assert(time_partitions.longest_pause() == Ticks(15) - Ticks(0), "Incorrect");
   337     assert(!iter.has_next(), "Too many elements");
   338   }
   339 };
   341 class GCTimerTest {
   342 public:
   343   static void all() {
   344     gc_start();
   345     gc_end();
   346   }
   348   static void gc_start() {
   349     GCTimer gc_timer;
   350     gc_timer.register_gc_start(1);
   352     assert(gc_timer.gc_start() == 1, "Incorrect");
   353   }
   355   static void gc_end() {
   356     GCTimer gc_timer;
   357     gc_timer.register_gc_start(1);
   358     gc_timer.register_gc_end(2);
   360     assert(gc_timer.gc_end() == 2, "Incorrect");
   361   }
   362 };
   364 void GCTimerAllTest::all() {
   365   GCTimerTest::all();
   366   TimePartitionPhasesIteratorTest::all();
   367 }
   369 #endif

mercurial