Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8295212: G1: Add wrapper for TruncatedSeqs that need separation by gc phase #10793

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 55 additions & 94 deletions src/hotspot/share/gc/g1/g1Analytics.cpp
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@

#include "precompiled.hpp"
#include "gc/g1/g1Analytics.hpp"
#include "gc/g1/g1AnalyticsSequences.inline.hpp"
#include "gc/g1/g1Predictions.hpp"
#include "gc/shared/gc_globals.hpp"
#include "runtime/globals.hpp"
@@ -36,17 +37,12 @@
// They were chosen by running GCOld and SPECjbb on debris with different
// numbers of GC threads and choosing them based on the results

// all the same
static double rs_length_diff_defaults[] = {
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
};

static double cost_per_logged_card_ms_defaults[] = {
0.01, 0.005, 0.005, 0.003, 0.003, 0.002, 0.002, 0.0015
};

// all the same
static double young_card_merge_to_scan_ratio_defaults[] = {
static double young_card_scan_to_merge_ratio_defaults[] = {
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
};

@@ -78,25 +74,19 @@ G1Analytics::G1Analytics(const G1Predictions* predictor) :
_concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
_alloc_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_prev_collection_pause_end_ms(0.0),
_young_rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_rs_length_diff_seq(new TruncatedSeq(TruncatedSeqLength)),
_concurrent_refine_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_dirtied_cards_rate_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_dirtied_cards_in_thread_buffers_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_card_scan_to_merge_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_card_scan_to_merge_ratio_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_cost_per_card_scan_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_cost_per_card_scan_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_cost_per_card_merge_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_cost_per_card_merge_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_copy_cost_per_byte_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_constant_other_time_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_other_cost_per_region_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_non_young_other_cost_per_region_ms_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_pending_cards_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_pending_cards_seq(new TruncatedSeq(TruncatedSeqLength)),
_young_rs_length_seq(new TruncatedSeq(TruncatedSeqLength)),
_mixed_rs_length_seq(new TruncatedSeq(TruncatedSeqLength)),
_card_scan_to_merge_ratio_seq(TruncatedSeqLength),
_cost_per_card_scan_ms_seq(TruncatedSeqLength),
_cost_per_card_merge_ms_seq(TruncatedSeqLength),
_pending_cards_seq(TruncatedSeqLength),
_rs_length_seq(TruncatedSeqLength),
_rs_length_diff_seq(TruncatedSeqLength),
_copy_cost_per_byte_ms_seq(TruncatedSeqLength),
_constant_other_time_ms_seq(TruncatedSeqLength),
_young_other_cost_per_region_ms_seq(TruncatedSeqLength),
_non_young_other_cost_per_region_ms_seq(TruncatedSeqLength),
_cost_per_byte_ms_during_cm_seq(new TruncatedSeq(TruncatedSeqLength)),
_recent_prev_end_times_for_all_gcs_sec(new TruncatedSeq(NumPrevPausesForHeuristics)),
_long_term_pause_time_ratio(0.0),
@@ -108,25 +98,27 @@ G1Analytics::G1Analytics(const G1Predictions* predictor) :

int index = MIN2(ParallelGCThreads - 1, 7u);

_young_rs_length_diff_seq->add(rs_length_diff_defaults[index]);
// Start with inverse of maximum STW cost.
_concurrent_refine_rate_ms_seq->add(1/cost_per_logged_card_ms_defaults[0]);
// Some applications have very low rates for logging cards.
_dirtied_cards_rate_ms_seq->add(0.0);
_young_card_scan_to_merge_ratio_seq->add(young_card_merge_to_scan_ratio_defaults[index]);
_young_cost_per_card_scan_ms_seq->add(young_only_cost_per_card_scan_ms_defaults[index]);

_copy_cost_per_byte_ms_seq->add(cost_per_byte_ms_defaults[index]);
_constant_other_time_ms_seq->add(constant_other_time_ms_defaults[index]);
_young_other_cost_per_region_ms_seq->add(young_other_cost_per_region_ms_defaults[index]);
_non_young_other_cost_per_region_ms_seq->add(non_young_other_cost_per_region_ms_defaults[index]);
_card_scan_to_merge_ratio_seq.set_initial(young_card_scan_to_merge_ratio_defaults[index]);
_cost_per_card_scan_ms_seq.set_initial(young_only_cost_per_card_scan_ms_defaults[index]);
_rs_length_seq.set_initial(0);
_rs_length_diff_seq.set_initial(0.0);

_copy_cost_per_byte_ms_seq.add(cost_per_byte_ms_defaults[index]);
_constant_other_time_ms_seq.add(constant_other_time_ms_defaults[index]);
_young_other_cost_per_region_ms_seq.add(young_other_cost_per_region_ms_defaults[index]);
_non_young_other_cost_per_region_ms_seq.add(non_young_other_cost_per_region_ms_defaults[index]);

// start conservatively (around 50ms is about right)
_concurrent_mark_remark_times_ms->add(0.05);
_concurrent_mark_cleanup_times_ms->add(0.20);
}

bool G1Analytics::enough_samples_available(TruncatedSeq const* seq) const {
bool G1Analytics::enough_samples_available(TruncatedSeq const* seq) {
return seq->num() >= 3;
}

@@ -142,6 +134,18 @@ double G1Analytics::predict_zero_bounded(TruncatedSeq const* seq) const {
return _predictor->predict_zero_bounded(seq);
}

double G1Analytics::predict_in_unit_interval(G1PhaseDependentSeq const* seq, bool for_young_only_phase) const {
return clamp(seq->predict(_predictor, for_young_only_phase), 0.0, 1.0);
}

size_t G1Analytics::predict_size(G1PhaseDependentSeq const* seq, bool for_young_only_phase) const {
return (size_t)predict_zero_bounded(seq, for_young_only_phase);
}

double G1Analytics::predict_zero_bounded(G1PhaseDependentSeq const* seq, bool for_young_only_phase) const {
return MAX2(seq->predict(_predictor, for_young_only_phase), 0.0);
}

int G1Analytics::num_alloc_rate_ms() const {
return _alloc_rate_ms_seq->num();
}
@@ -178,71 +182,47 @@ void G1Analytics::report_dirtied_cards_in_thread_buffers(size_t cards) {
}

void G1Analytics::report_cost_per_card_scan_ms(double cost_per_card_ms, bool for_young_only_phase) {
if (for_young_only_phase) {
_young_cost_per_card_scan_ms_seq->add(cost_per_card_ms);
} else {
_mixed_cost_per_card_scan_ms_seq->add(cost_per_card_ms);
}
_cost_per_card_scan_ms_seq.add(cost_per_card_ms, for_young_only_phase);
}

void G1Analytics::report_cost_per_card_merge_ms(double cost_per_card_ms, bool for_young_only_phase) {
if (for_young_only_phase) {
_young_cost_per_card_merge_ms_seq->add(cost_per_card_ms);
} else {
_mixed_cost_per_card_merge_ms_seq->add(cost_per_card_ms);
}
_cost_per_card_merge_ms_seq.add(cost_per_card_ms, for_young_only_phase);
}

void G1Analytics::report_card_scan_to_merge_ratio(double merge_to_scan_ratio, bool for_young_only_phase) {
if (for_young_only_phase) {
_young_card_scan_to_merge_ratio_seq->add(merge_to_scan_ratio);
} else {
_mixed_card_scan_to_merge_ratio_seq->add(merge_to_scan_ratio);
}
_card_scan_to_merge_ratio_seq.add(merge_to_scan_ratio, for_young_only_phase);
}

void G1Analytics::report_rs_length_diff(double rs_length_diff, bool for_young_only_phase) {
if (for_young_only_phase) {
_young_rs_length_diff_seq->add(rs_length_diff);
} else {
_mixed_rs_length_diff_seq->add(rs_length_diff);
}
_rs_length_diff_seq.add(rs_length_diff, for_young_only_phase);
}

void G1Analytics::report_cost_per_byte_ms(double cost_per_byte_ms, bool mark_or_rebuild_in_progress) {
if (mark_or_rebuild_in_progress) {
_cost_per_byte_ms_during_cm_seq->add(cost_per_byte_ms);
} else {
_copy_cost_per_byte_ms_seq->add(cost_per_byte_ms);
_copy_cost_per_byte_ms_seq.add(cost_per_byte_ms);
}
}

void G1Analytics::report_young_other_cost_per_region_ms(double other_cost_per_region_ms) {
_young_other_cost_per_region_ms_seq->add(other_cost_per_region_ms);
_young_other_cost_per_region_ms_seq.add(other_cost_per_region_ms);
}

void G1Analytics::report_non_young_other_cost_per_region_ms(double other_cost_per_region_ms) {
_non_young_other_cost_per_region_ms_seq->add(other_cost_per_region_ms);
_non_young_other_cost_per_region_ms_seq.add(other_cost_per_region_ms);
}

void G1Analytics::report_constant_other_time_ms(double constant_other_time_ms) {
_constant_other_time_ms_seq->add(constant_other_time_ms);
_constant_other_time_ms_seq.add(constant_other_time_ms);
}

void G1Analytics::report_pending_cards(double pending_cards, bool for_young_only_phase) {
if (for_young_only_phase) {
_young_pending_cards_seq->add(pending_cards);
} else {
_mixed_pending_cards_seq->add(pending_cards);
}
_pending_cards_seq.add(pending_cards, for_young_only_phase);
}

void G1Analytics::report_rs_length(double rs_length, bool for_young_only_phase) {
if (for_young_only_phase) {
_young_rs_length_seq->add(rs_length);
} else {
_mixed_rs_length_seq->add(rs_length);
}
_rs_length_seq.add(rs_length, for_young_only_phase);
}

double G1Analytics::predict_alloc_rate_ms() const {
@@ -266,32 +246,20 @@ size_t G1Analytics::predict_dirtied_cards_in_thread_buffers() const {
}

size_t G1Analytics::predict_scan_card_num(size_t rs_length, bool for_young_only_phase) const {
if (for_young_only_phase || !enough_samples_available(_mixed_card_scan_to_merge_ratio_seq)) {
return (size_t)(rs_length * predict_in_unit_interval(_young_card_scan_to_merge_ratio_seq));
} else {
return (size_t)(rs_length * predict_in_unit_interval(_mixed_card_scan_to_merge_ratio_seq));
}
return rs_length * predict_in_unit_interval(&_card_scan_to_merge_ratio_seq, for_young_only_phase);
}

double G1Analytics::predict_card_merge_time_ms(size_t card_num, bool for_young_only_phase) const {
if (for_young_only_phase || !enough_samples_available(_mixed_cost_per_card_merge_ms_seq)) {
return card_num * predict_zero_bounded(_young_cost_per_card_merge_ms_seq);
} else {
return card_num * predict_zero_bounded(_mixed_cost_per_card_merge_ms_seq);
}
return card_num * predict_zero_bounded(&_cost_per_card_merge_ms_seq, for_young_only_phase);
}

double G1Analytics::predict_card_scan_time_ms(size_t card_num, bool for_young_only_phase) const {
if (for_young_only_phase || !enough_samples_available(_mixed_cost_per_card_scan_ms_seq)) {
return card_num * predict_zero_bounded(_young_cost_per_card_scan_ms_seq);
} else {
return card_num * predict_zero_bounded(_mixed_cost_per_card_scan_ms_seq);
}
return card_num * predict_zero_bounded(&_cost_per_card_scan_ms_seq, for_young_only_phase);
}

double G1Analytics::predict_object_copy_time_ms_during_cm(size_t bytes_to_copy) const {
if (!enough_samples_available(_cost_per_byte_ms_during_cm_seq)) {
return (1.1 * bytes_to_copy) * predict_zero_bounded(_copy_cost_per_byte_ms_seq);
return (1.1 * bytes_to_copy) * predict_zero_bounded(&_copy_cost_per_byte_ms_seq);
} else {
return bytes_to_copy * predict_zero_bounded(_cost_per_byte_ms_during_cm_seq);
}
@@ -301,20 +269,20 @@ double G1Analytics::predict_object_copy_time_ms(size_t bytes_to_copy, bool durin
if (during_concurrent_mark) {
return predict_object_copy_time_ms_during_cm(bytes_to_copy);
} else {
return bytes_to_copy * predict_zero_bounded(_copy_cost_per_byte_ms_seq);
return bytes_to_copy * predict_zero_bounded(&_copy_cost_per_byte_ms_seq);
}
}

double G1Analytics::predict_constant_other_time_ms() const {
return predict_zero_bounded(_constant_other_time_ms_seq);
return predict_zero_bounded(&_constant_other_time_ms_seq);
}

double G1Analytics::predict_young_other_time_ms(size_t young_num) const {
return young_num * predict_zero_bounded(_young_other_cost_per_region_ms_seq);
return young_num * predict_zero_bounded(&_young_other_cost_per_region_ms_seq);
}

double G1Analytics::predict_non_young_other_time_ms(size_t non_young_num) const {
return non_young_num * predict_zero_bounded(_non_young_other_cost_per_region_ms_seq);
return non_young_num * predict_zero_bounded(&_non_young_other_cost_per_region_ms_seq);
}

double G1Analytics::predict_remark_time_ms() const {
@@ -326,19 +294,12 @@ double G1Analytics::predict_cleanup_time_ms() const {
}

size_t G1Analytics::predict_rs_length(bool for_young_only_phase) const {
if (for_young_only_phase || !enough_samples_available(_mixed_rs_length_seq)) {
return predict_size(_young_rs_length_seq) + predict_size(_young_rs_length_diff_seq);
} else {
return predict_size(_mixed_rs_length_seq) + predict_size(_mixed_rs_length_diff_seq);
}
return predict_size(&_rs_length_seq, for_young_only_phase) +
predict_size(&_rs_length_diff_seq, for_young_only_phase);
}

size_t G1Analytics::predict_pending_cards(bool for_young_only_phase) const {
if (for_young_only_phase || !enough_samples_available(_mixed_pending_cards_seq)) {
return predict_size(_young_pending_cards_seq);
} else {
return predict_size(_mixed_pending_cards_seq);
}
return predict_size(&_pending_cards_seq, for_young_only_phase);
}

double G1Analytics::oldest_known_gc_end_time_sec() const {
41 changes: 20 additions & 21 deletions src/hotspot/share/gc/g1/g1Analytics.hpp
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
#ifndef SHARE_GC_G1_G1ANALYTICS_HPP
#define SHARE_GC_G1_G1ANALYTICS_HPP

#include "gc/g1/g1AnalyticsSequences.hpp"
#include "memory/allocation.hpp"
#include "utilities/globalDefinitions.hpp"

@@ -45,34 +46,28 @@ class G1Analytics: public CHeapObj<mtGC> {
TruncatedSeq* _alloc_rate_ms_seq;
double _prev_collection_pause_end_ms;

TruncatedSeq* _young_rs_length_diff_seq;
TruncatedSeq* _mixed_rs_length_diff_seq;
TruncatedSeq* _concurrent_refine_rate_ms_seq;
TruncatedSeq* _dirtied_cards_rate_ms_seq;
TruncatedSeq* _dirtied_cards_in_thread_buffers_seq;
// The ratio between the number of scanned cards and actually merged cards, for
// young-only and mixed gcs.
TruncatedSeq* _young_card_scan_to_merge_ratio_seq;
TruncatedSeq* _mixed_card_scan_to_merge_ratio_seq;
G1PhaseDependentSeq _card_scan_to_merge_ratio_seq;

// The cost to scan a card during young-only and mixed gcs in ms.
TruncatedSeq* _young_cost_per_card_scan_ms_seq;
TruncatedSeq* _mixed_cost_per_card_scan_ms_seq;
G1PhaseDependentSeq _cost_per_card_scan_ms_seq;

// The cost to merge a card during young-only and mixed gcs in ms.
TruncatedSeq* _young_cost_per_card_merge_ms_seq;
TruncatedSeq* _mixed_cost_per_card_merge_ms_seq;
G1PhaseDependentSeq _cost_per_card_merge_ms_seq;

// The cost to copy a byte in ms.
TruncatedSeq* _copy_cost_per_byte_ms_seq;
TruncatedSeq* _constant_other_time_ms_seq;
TruncatedSeq* _young_other_cost_per_region_ms_seq;
TruncatedSeq* _non_young_other_cost_per_region_ms_seq;
G1PhaseDependentSeq _pending_cards_seq;
G1PhaseDependentSeq _rs_length_seq;
G1PhaseDependentSeq _rs_length_diff_seq;

TruncatedSeq* _young_pending_cards_seq;
TruncatedSeq* _mixed_pending_cards_seq;
TruncatedSeq* _young_rs_length_seq;
TruncatedSeq* _mixed_rs_length_seq;
// The cost to copy a byte in ms.
TruncatedSeq _copy_cost_per_byte_ms_seq;
TruncatedSeq _constant_other_time_ms_seq;
TruncatedSeq _young_other_cost_per_region_ms_seq;
TruncatedSeq _non_young_other_cost_per_region_ms_seq;

TruncatedSeq* _cost_per_byte_ms_during_cm_seq;

@@ -84,20 +79,24 @@ class G1Analytics: public CHeapObj<mtGC> {
double _long_term_pause_time_ratio;
double _short_term_pause_time_ratio;

// Returns whether the sequence have enough samples to get a "good" prediction.
// The constant used is random but "small".
bool enough_samples_available(TruncatedSeq const* seq) const;

double predict_in_unit_interval(TruncatedSeq const* seq) const;
size_t predict_size(TruncatedSeq const* seq) const;
double predict_zero_bounded(TruncatedSeq const* seq) const;

double predict_in_unit_interval(G1PhaseDependentSeq const* seq, bool for_young_only_phase) const;
size_t predict_size(G1PhaseDependentSeq const* seq, bool for_young_only_phase) const;
double predict_zero_bounded(G1PhaseDependentSeq const* seq, bool for_young_only_phase) const;

double oldest_known_gc_end_time_sec() const;
double most_recent_gc_end_time_sec() const;

public:
G1Analytics(const G1Predictions* predictor);

// Returns whether the sequence have enough samples to get a "good" prediction.
// The constant used is random but "small".
static bool enough_samples_available(TruncatedSeq const* seq);

double prev_collection_pause_end_ms() const {
return _prev_collection_pause_end_ms;
}
56 changes: 56 additions & 0 deletions src/hotspot/share/gc/g1/g1AnalyticsSequences.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/

#ifndef SHARE_GC_G1_G1ANALYTICSSEQUENCES_HPP
#define SHARE_GC_G1_G1ANALYTICSSEQUENCES_HPP

#include "utilities/globalDefinitions.hpp"
#include "utilities/numberSeq.hpp"

#include <float.h>

class G1Predictions;

// Container for TruncatedSeqs that need separate predictors by GC phase.
class G1PhaseDependentSeq {
TruncatedSeq _young_only_seq;
TruncatedSeq _mixed_seq;

NONCOPYABLE(G1PhaseDependentSeq);

TruncatedSeq* seq_raw(bool use_young_only_phase_seq);

bool enough_samples_to_use_mixed_seq() const;
public:

G1PhaseDependentSeq(int length);

void set_initial(double value);
void add(double value, bool for_young_only_phase);

double predict(const G1Predictions* predictor, bool use_young_only_phase_seq) const;
};

#endif /* SHARE_GC_G1_G1ANALYTICSSEQUENCES_HPP */

61 changes: 61 additions & 0 deletions src/hotspot/share/gc/g1/g1AnalyticsSequences.inline.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/

#ifndef SHARE_GC_G1_G1ANALYTICSSEQUENCES_INLINE_HPP
#define SHARE_GC_G1_G1ANALYTICSSEQUENCES_INLINE_HPP

#include "gc/g1/g1AnalyticsSequences.hpp"
#include "gc/g1/g1Predictions.hpp"

bool G1PhaseDependentSeq::enough_samples_to_use_mixed_seq() const {
return G1Analytics::enough_samples_available(&_mixed_seq);
}

G1PhaseDependentSeq::G1PhaseDependentSeq(int length) :
_young_only_seq(length),
_mixed_seq(length)
{ }

TruncatedSeq* G1PhaseDependentSeq::seq_raw(bool use_young_only_phase_seq) {
return use_young_only_phase_seq ? &_young_only_seq : &_mixed_seq;
}

void G1PhaseDependentSeq::set_initial(double value) {
_young_only_seq.add(value);
}

void G1PhaseDependentSeq::add(double value, bool for_young_only_phase) {
seq_raw(for_young_only_phase)->add(value);
}

double G1PhaseDependentSeq::predict(const G1Predictions* predictor, bool use_young_only_phase_seq) const {
if (use_young_only_phase_seq || !enough_samples_to_use_mixed_seq()) {
return predictor->predict(&_young_only_seq);
} else {
return predictor->predict(&_mixed_seq);
}
}

#endif /* SHARE_GC_G1_G1ANALYTICSSEQUENCES_INLINE_HPP */