-
Notifications
You must be signed in to change notification settings - Fork 6.2k
DRAFT: Adaptive evac with surge #28955
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
base: master
Are you sure you want to change the base?
Changes from all commits
6c90312
43c1842
c097513
980110b
7ae16e1
ac39797
b6ef323
a8e40e1
1911e04
7ce1120
2412337
6ddcc4d
437c71f
65eb7b9
77ae0c1
fa28658
7e97937
6a2085b
04f079b
ac04ca7
a281853
31d7bb3
92f9012
17579d3
28f5f4d
f304451
b705c37
f84239e
b2accf3
d49a9a2
dc68262
7611ea5
0ca33a6
28a4332
9f40598
689c683
d1ac7e6
0478cdd
3ed2b83
97bdd69
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,58 @@ | |
| #include "memory/allocation.hpp" | ||
| #include "utilities/numberSeq.hpp" | ||
|
|
||
| class ShenandoahPhaseTimeEstimator { | ||
| private: | ||
| static const uint MaxSamples = 8; | ||
|
|
||
| const char* _name; | ||
| bool _changed; | ||
| bool _changed_no_stdev; | ||
| uint _first_index; | ||
| uint _num_samples; | ||
| double _sum_of_x; | ||
| double _sum_of_y; | ||
| double _sum_of_xx; | ||
| double _sum_of_xy; | ||
| double _most_recent_start; | ||
| double _x_values[MaxSamples]; | ||
| double _y_values[MaxSamples]; | ||
| double _most_recent_prediction_x_value; | ||
| double _most_recent_prediction; | ||
| double _most_recent_prediction_x_value_no_stdev; | ||
| double _most_recent_prediction_no_stdev; | ||
| double _most_recent_bytes_allocated; | ||
|
|
||
| public: | ||
| explicit ShenandoahPhaseTimeEstimator(const char *name); | ||
|
|
||
| void add_sample(double independent_variable, double dependent_variable); | ||
|
|
||
| // Return conservative prediction of time required for next execution of this phase, | ||
| // which is Max(average_prediction, linear_prediction), | ||
| // average_prediction is average + std_dev, and | ||
| // linear_prediction is determined best-fit line + std_dev of this calculation | ||
| double predict_at(double independent_value); | ||
|
|
||
| double predict_at_without_stdev(double independent_value); | ||
|
|
||
| void set_most_recent_start_time(double now) { | ||
| _most_recent_start = now; | ||
| } | ||
|
|
||
| double get_most_recent_start_time() { | ||
| return _most_recent_start; | ||
| } | ||
|
|
||
| void set_most_recent_bytes_allocated(size_t bytes) { | ||
| _most_recent_bytes_allocated = bytes; | ||
| } | ||
|
|
||
| size_t get_most_recent_bytes_allocated() { | ||
| return _most_recent_bytes_allocated; | ||
| } | ||
| }; | ||
|
|
||
| class ShenandoahAllocationRate : public CHeapObj<mtGC> { | ||
| public: | ||
| explicit ShenandoahAllocationRate(); | ||
|
|
@@ -40,6 +92,7 @@ | |
| double sample(size_t allocated); | ||
|
|
||
| double upper_bound(double sds) const; | ||
| double average_rate(double sds) const; | ||
| bool is_spiking(double rate, double threshold) const; | ||
| private: | ||
|
|
||
|
|
@@ -73,7 +126,7 @@ | |
| RegionData* data, size_t size, | ||
| size_t actual_free); | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is declared by shenandoahHeuristics, overrides in shenandoahAdaptiveHeuristics. ShenandoahAdaptiveHeuristics uses this to set the start time for the mark phase. Add override declaration. This change belongs to phase-accounting |
||
| void record_cycle_start(); | ||
| virtual void record_cycle_start(); | ||
| void record_success_concurrent(); | ||
| void record_success_degenerated(); | ||
| void record_success_full(); | ||
|
|
@@ -84,6 +137,17 @@ | |
| virtual bool is_diagnostic() { return false; } | ||
| virtual bool is_experimental() { return false; } | ||
|
|
||
| virtual void record_phase_duration(ShenandoahMajorGCPhase p, double x, double duration) override; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These changes belong to phase-accounting |
||
|
|
||
| void record_mark_end(double now, size_t marked_words) override; | ||
| // In non-generational mode, supply pip_words as zero | ||
| void record_evac_end(double now, size_t evacuated_words, size_t pip_words) override; | ||
| void record_update_end(double now, size_t updated_words) override; | ||
| // In non-generational mode, supply pip_words as zero | ||
| void record_final_roots_end(double now, size_t pip_words) override; | ||
|
|
||
| uint should_surge_phase(ShenandoahMajorGCPhase phase, double now) override; | ||
|
|
||
| private: | ||
| // These are used to adjust the margin of error and the spike threshold | ||
| // in response to GC cycle outcomes. These values are shared, but the | ||
|
|
@@ -99,6 +163,18 @@ | |
|
|
||
| friend class ShenandoahAllocationRate; | ||
|
|
||
| void adjust_last_trigger_parameters(double amount); | ||
| void adjust_margin_of_error(double amount); | ||
| void adjust_spike_threshold(double amount); | ||
|
|
||
| protected: | ||
| // Use this to estimate how much time will be required for future mark, evac, update, final-roots phases. | ||
| ShenandoahPhaseTimeEstimator _phase_stats[ShenandoahMajorGCPhase::_num_phases] = { | ||
| ShenandoahPhaseTimeEstimator("mark"), | ||
| ShenandoahPhaseTimeEstimator("evac"), | ||
| ShenandoahPhaseTimeEstimator("update"), | ||
| ShenandoahPhaseTimeEstimator("final-roots") }; | ||
|
|
||
| // Used to record the last trigger that signaled to start a GC. | ||
| // This itself is used to decide whether or not to adjust the margin of | ||
| // error for the average cycle time and allocation rate or the allocation | ||
|
|
@@ -107,11 +183,6 @@ | |
| SPIKE, RATE, OTHER | ||
| }; | ||
|
|
||
| void adjust_last_trigger_parameters(double amount); | ||
| void adjust_margin_of_error(double amount); | ||
| void adjust_spike_threshold(double amount); | ||
|
|
||
| protected: | ||
| ShenandoahAllocationRate _allocation_rate; | ||
|
|
||
| // The margin of error expressed in standard deviations to add to our | ||
|
|
@@ -140,6 +211,60 @@ | |
| // source of feedback to adjust trigger parameters. | ||
| TruncatedSeq _available; | ||
|
|
||
| // How many total words were evacuated in the most recently completed GC? | ||
| size_t _words_most_recently_evacuated; | ||
|
|
||
| // How many words do we expect to mark in the next GC? | ||
| // (aka how many words did we evacuate from most recently completed GC?) | ||
| size_t _anticipated_mark_words; | ||
|
|
||
| // How many words do we expect to evacuate in the next GC? | ||
| // (aka how many words did we evacuate from most recently completed GC?) | ||
| size_t _anticipated_evac_words; | ||
|
|
||
| // How many words do we expect to update in the next GC? | ||
| size_t _anticipated_update_words; | ||
|
|
||
| double predict_mark_time(size_t anticipated_marked_words) override; | ||
| double predict_evac_time(size_t anticipated_evac_words, size_t anticipated_pip_words) override; | ||
| double predict_update_time(size_t anticipated_update_words) override; | ||
| double predict_final_roots_time(size_t pip_words) override; | ||
|
|
||
| double predict_mark_time_nonconservative(size_t anticipated_marked_words) override; | ||
| double predict_evac_time_nonconservative(size_t anticipated_evac_words, size_t anticipated_pip_words) override; | ||
| double predict_update_time_nonconservative(size_t anticipated_update_words) override; | ||
| double predict_final_roots_time_nonconservative(size_t pip_words) override; | ||
|
|
||
| double predict_gc_time() override; | ||
| double predict_gc_time_nonconservative() override; | ||
|
|
||
| inline size_t get_anticipated_mark_words() { | ||
| return _anticipated_mark_words; | ||
| } | ||
|
|
||
| inline void set_anticipated_evac_words(size_t words) { | ||
| #undef KELVIN_ANTICIPATION | ||
| #ifdef KELVIN_ANTICIPATION | ||
| log_info(gc)("SAH::set_anticipated_evac_words(%zu)", words); | ||
| #endif | ||
| _anticipated_evac_words = words; | ||
| } | ||
|
|
||
| inline size_t get_anticipated_evac_words() { | ||
| return _anticipated_evac_words; | ||
| } | ||
|
|
||
| inline void set_anticipated_update_words(size_t words) { | ||
| #ifdef KELVIN_ANTICIPATION | ||
| log_info(gc)("SAH::set_anticipated_update_words(%zu)", words); | ||
| #endif | ||
| _anticipated_update_words = words; | ||
| } | ||
|
|
||
| inline size_t get_anticipated_update_words() { | ||
| return _anticipated_update_words; | ||
| } | ||
|
|
||
| // A conservative minimum threshold of free space that we'll try to maintain when possible. | ||
| // For example, we might trigger a concurrent gc if we are likely to drop below | ||
| // this threshold, or we might consider this when dynamically resizing generations | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes belong to phase-accounting