/* * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. * */ package gcparser; import java.util.regex.*; public class CMSGCParser extends GCParser { public CMSGCParser(GCStats gcstats, boolean verbose) { super(gcstats, verbose); // _debug = System.err; // XXX // debug(_cms_imark_pattern.pattern()); debug(); // debug(_cms_rmark_pattern.pattern()); debug(); // debug(_cms_concurrent_phase_pattern.pattern()); debug(); } /* ** Would like to have values for og_used_end, og_commit_end, ** th_used_end, and th_commit at the end of the cms cycle (end of ** reset), but they're not available. */ public boolean parse(String filename, int line, String s) { Matcher m; m = _cms_phase_beg_pattern.matcher(s); if (m.find()) { _cms_phase_beg_matcher = m; _cms_phase_beg_timestamp = get_ts(m, _cms_phase_beg_timestamp_grp); return true; } m = _cms_concurrent_phase_pattern.matcher(s); if (m.find()) { save_match_state(filename, line, s); concurrent_phase_end(m); return true; } m = _cms_imark_pattern.matcher(s); if (m.find()) { save_match_state(filename, line, s); debug_imark(s, m); // These values are available at the start of the cms // cycle (initial mark), but not at the end (reset). // Recording them here makes the stats confusing, so // they are skipped. // add_sz(GCMetric.og_used_beg, m, // _cms_imark_og_used_beg_grp); // add_sz(GCMetric.th_used_beg, m, // _cms_imark_th_used_beg_grp); double timestamp = get_ts(m, _cms_imark_timestamp_grp); String str = m.group(_cms_imark_time_grp); double pause_time = Double.parseDouble(str); add_pt(GCMetric.cms_im_time, timestamp, pause_time); if (!gcstats().has_generated_timestamps()) { TimingWindowData tw = gcstats().timing_window(); tw.add_pause_time(timestamp, pause_time); } return true; } m = _cms_rmark_pattern.matcher(s); if (m.find()) { save_match_state(filename, line, s); // add_sz(GCMetric.og_used_beg, m, // _cms_rmark_og_used_beg_grp); // add_sz(GCMetric.th_used_beg, m, // _cms_rmark_th_used_beg_grp); double timestamp = get_ts(m, _cms_rmark_timestamp_grp); String str = m.group(_cms_rmark_time_grp); double pause_time = Double.parseDouble(str); add_pt(GCMetric.cms_rm_time, timestamp, pause_time); if (!gcstats().has_generated_timestamps()) { TimingWindowData tw = gcstats().timing_window(); tw.add_pause_time(timestamp, pause_time); } return true; } return false; } private void concurrent_phase_end(Matcher m) { boolean is_reset = false; // debug(_text); debug(); // debug(m, _cms_concurrent_phase_name_grp, "phase"); // debug(" "); // debug(m, _cms_concurrent_phase_active_time_grp, "a"); // debug(" "); // debug(m, _cms_concurrent_phase_elapsed_time_grp, "e"); // debug(); GCMetric active_metric = null; GCMetric elapsed_metric = null; String phase = m.group(_cms_concurrent_phase_name_grp); if (phase.equals("mark")) { active_metric = GCMetric.cms_cm_a_time; elapsed_metric = GCMetric.cms_cm_e_time; } else if (phase.indexOf("preclean") >= 0) { active_metric = GCMetric.cms_cp_a_time; elapsed_metric = GCMetric.cms_cp_e_time; } else if (phase.equals("sweep")) { active_metric = GCMetric.cms_cs_a_time; elapsed_metric = GCMetric.cms_cs_e_time; } else if (phase.equals("reset")) { is_reset = true; active_metric = GCMetric.cms_cr_a_time; elapsed_metric = GCMetric.cms_cr_e_time; } double active_time = Double.parseDouble( m.group(_cms_concurrent_phase_active_time_grp)); add_dp(active_metric, active_time); add_dp(elapsed_metric, m, _cms_concurrent_phase_elapsed_time_grp); if (_cms_phase_beg_matcher == null) return; // Add just one timestamp even though there are two // metrics (active and elapsed) since the underlying // timestamp list is shared. double timestamp_end = get_ts(m, _cms_concurrent_phase_timestamp_grp); add_ts(active_metric, _cms_phase_beg_timestamp, timestamp_end); if (gcstats().has_generated_timestamps()) return; TimingWindowData tw = gcstats().timing_window(); tw.add_concurrent_time(timestamp_end, active_time, 1); if (is_reset) { final double th_alloc_sum = gcstats().stats(GCMetric.th_alloc).sum(); final double alloc = th_alloc_sum - tw.th_alloc(); add_dp(GCMetric.th_alloc_cpu, alloc / tw.elapsed_cpu_time()); add_dp(GCMetric.th_alloc_mut, alloc / tw.mutator_cpu_time()); // Add a timestamp to just one of the metrics since the // underlying list is shared. add_ts(GCMetric.th_alloc_cpu, _cms_phase_beg_timestamp, timestamp_end); tw.reset(timestamp_end, th_alloc_sum); } } private void debug_imark(String s, Matcher m) { if (_debug == null) return; debug(s); debug(); debug(m, _cms_imark_og_used_beg_grp, GCMetric.og_used_beg); debug(" "); debug(m, _cms_imark_th_used_beg_grp, GCMetric.th_used_beg); debug(" "); debug(m, _cms_imark_time_grp, GCMetric.cms_im_time); debug(); } private Matcher _cms_phase_beg_matcher; private double _cms_phase_beg_timestamp; private static Pattern _cms_imark_pattern = Pattern.compile( timestamp_re + "\\[GC \\[1 (AS)?CMS-initial-mark: " + cms_heap_size_re + "\\] " + cms_heap_report_re + "\\]"); private static final int _cms_imark_timestamp_grp = timestamp_re_time_group; private static final int _cms_imark_og_used_beg_grp = timestamp_re_groups + 2; private static final int _cms_imark_og_commit_end_grp = _cms_imark_og_used_beg_grp + heap_size_re_groups; private static final int _cms_imark_th_used_beg_grp = _cms_imark_og_commit_end_grp + heap_size_paren_re_groups; private static final int _cms_imark_th_commit_end_grp = _cms_imark_th_used_beg_grp + heap_size_re_groups; private static final int _cms_imark_time_grp = timestamp_re_groups + 1 + cms_heap_size_re_groups + cms_heap_report_re_groups - 1; private static Pattern _cms_rmark_pattern = Pattern.compile( timestamp_re + "\\[GC.*\\[1 (AS)?CMS-remark: " + cms_heap_size_re + "\\] " + cms_heap_report_re + "\\]"); private static final int _cms_rmark_timestamp_grp = timestamp_re_time_group; private static final int _cms_rmark_time_grp = timestamp_re_groups + 1 + cms_heap_size_re_groups + cms_heap_report_re_groups - 1; private static Pattern _cms_phase_beg_pattern = Pattern.compile( timestamp_re + "\\[" + cms_concurrent_phase_name_re + "-start\\]"); private static int _cms_phase_beg_timestamp_grp = timestamp_re_time_group; private static Pattern _cms_concurrent_phase_pattern = Pattern.compile( timestamp_re + "\\[" + cms_concurrent_phase_name_re + ": " + gc_time_re + "/" + gc_time_secs_re + "\\]"); private static final int _cms_concurrent_phase_timestamp_grp = timestamp_re_time_group; private static final int _cms_concurrent_phase_name_grp = timestamp_re_groups + cms_concurrent_phase_name_group; private static final int _cms_concurrent_phase_active_time_grp = timestamp_re_groups + cms_concurrent_phase_name_re_groups + 1; private static final int _cms_concurrent_phase_elapsed_time_grp = timestamp_re_groups + cms_concurrent_phase_name_re_groups + gc_time_re_groups + gc_time_secs_re_time_group; }