8205725: Update the JVMTI Spec for Heap Sampling
Update the JVMTI Spec for Heap Sampling Reviewed-by: amenkov, sspitsyn
This commit is contained in:
parent
4e92c2dfdc
commit
3380b0d0ef
src/hotspot/share
test/hotspot/jtreg/serviceability/jvmti/HeapMonitor
@ -10369,7 +10369,7 @@ myInit() {
|
|||||||
<description>
|
<description>
|
||||||
Can generate sampled allocation events.
|
Can generate sampled allocation events.
|
||||||
If this capability is enabled then the heap sampling method
|
If this capability is enabled then the heap sampling method
|
||||||
<functionlink id="SetHeapSamplingRate"></functionlink> can be
|
<functionlink id="SetHeapSamplingInterval"></functionlink> can be
|
||||||
called and <eventlink id="SampledObjectAlloc"></eventlink> events can be generated.
|
called and <eventlink id="SampledObjectAlloc"></eventlink> events can be generated.
|
||||||
</description>
|
</description>
|
||||||
</capabilityfield>
|
</capabilityfield>
|
||||||
@ -11552,41 +11552,47 @@ myInit() {
|
|||||||
</category>
|
</category>
|
||||||
|
|
||||||
<category id="heap_monitoring" label="Heap Monitoring">
|
<category id="heap_monitoring" label="Heap Monitoring">
|
||||||
<function id="SetHeapSamplingRate" phase="onload" num="156" since="11">
|
<function id="SetHeapSamplingInterval" phase="onload" num="156" since="11">
|
||||||
<synopsis>Set Heap Sampling Rate</synopsis>
|
<synopsis>Set Heap Sampling Interval</synopsis>
|
||||||
<description>
|
<description>
|
||||||
Generate a <eventlink id="SampledObjectAlloc"/> event when objects are allocated.
|
Generate a <eventlink id="SampledObjectAlloc"/> event when objects are allocated.
|
||||||
Each thread keeps a counter of bytes allocated. The event will only be generated
|
Each thread keeps a counter of bytes allocated. The event will only be generated
|
||||||
when that counter exceeds an average of <paramlink id="sampling_rate"></paramlink>
|
when that counter exceeds an average of <paramlink id="sampling_interval"></paramlink>
|
||||||
since the last sample.
|
since the last sample.
|
||||||
<p/>
|
<p/>
|
||||||
Setting <paramlink id="sampling_rate"></paramlink> to 0 will cause an event to be
|
Setting <paramlink id="sampling_interval"></paramlink> to 0 will cause an event to be
|
||||||
generated by each allocation supported by the system.
|
generated by each allocation supported by the system once the new interval is taken into account.
|
||||||
|
<p/>
|
||||||
|
Note that updating the new sampling interval might take various number of allocations
|
||||||
|
to provoke internal data structure updates. Therefore it is important to
|
||||||
|
consider the sampling interval as an average. This includes the interval 0, where events
|
||||||
|
might not be generated straight away for each allocation.
|
||||||
</description>
|
</description>
|
||||||
<origin>new</origin>
|
<origin>new</origin>
|
||||||
<capabilities>
|
<capabilities>
|
||||||
<required id="can_generate_sampled_object_alloc_events"></required>
|
<required id="can_generate_sampled_object_alloc_events"></required>
|
||||||
</capabilities>
|
</capabilities>
|
||||||
<parameters>
|
<parameters>
|
||||||
<param id="sampling_rate">
|
<param id="sampling_interval">
|
||||||
<jint/>
|
<jint/>
|
||||||
<description>
|
<description>
|
||||||
The sampling rate in bytes. The sampler uses a statistical approach to
|
The sampling interval in bytes. The sampler uses a statistical approach to
|
||||||
generate an event, on average, once for every <paramlink id="sampling_rate"/> bytes of
|
generate an event, on average, once for every <paramlink id="sampling_interval"/> bytes of
|
||||||
memory allocated by a given thread.
|
memory allocated by a given thread.
|
||||||
<p/>
|
<p/>
|
||||||
Passing 0 as a sampling rate generates a sample for every allocation.
|
Once the new sampling interval is taken into account, 0 as a sampling interval will generate
|
||||||
|
a sample for every allocation.
|
||||||
<p/>
|
<p/>
|
||||||
Note: The overhead of this feature is directly correlated with the sampling rate.
|
Note: The overhead of this feature is directly correlated with the sampling interval.
|
||||||
A high sampling rate, such as 1024 bytes, will incur a high overhead.
|
A high sampling interval, such as 1024 bytes, will incur a high overhead.
|
||||||
A lower rate, such as 1024KB, will have a much lower overhead. Sampling should only
|
A lower interval, such as 1024KB, will have a much lower overhead. Sampling should only
|
||||||
be used with an understanding that it may impact performance.
|
be used with an understanding that it may impact performance.
|
||||||
</description>
|
</description>
|
||||||
</param>
|
</param>
|
||||||
</parameters>
|
</parameters>
|
||||||
<errors>
|
<errors>
|
||||||
<error id="JVMTI_ERROR_ILLEGAL_ARGUMENT">
|
<error id="JVMTI_ERROR_ILLEGAL_ARGUMENT">
|
||||||
<paramlink id="sampling_rate"></paramlink> is less than zero.
|
<paramlink id="sampling_interval"></paramlink> is less than zero.
|
||||||
</error>
|
</error>
|
||||||
</errors>
|
</errors>
|
||||||
</function>
|
</function>
|
||||||
@ -13586,20 +13592,23 @@ myInit() {
|
|||||||
id="SampledObjectAlloc" const="JVMTI_EVENT_SAMPLED_OBJECT_ALLOC" num="86" since="11">
|
id="SampledObjectAlloc" const="JVMTI_EVENT_SAMPLED_OBJECT_ALLOC" num="86" since="11">
|
||||||
<description>
|
<description>
|
||||||
Sent when an allocated object is sampled.
|
Sent when an allocated object is sampled.
|
||||||
By default, the sampling rate is a geometric variable with a 512KB mean.
|
By default, the sampling interval is set to 512KB. The sampling is semi-random to avoid
|
||||||
|
pattern-based bias and provides an approximate overall average interval over long periods of
|
||||||
|
sampling.
|
||||||
|
<p/>
|
||||||
Each thread tracks how many bytes it has allocated since it sent the last event.
|
Each thread tracks how many bytes it has allocated since it sent the last event.
|
||||||
When the number of bytes exceeds the sampling rate, it will send another event.
|
When the number of bytes exceeds the sampling interval, it will send another event.
|
||||||
This implies that, on average, one object will be sampled every time a thread has
|
This implies that, on average, one object will be sampled every time a thread has
|
||||||
allocated 512KB bytes since the last sample.
|
allocated 512KB bytes since the last sample.
|
||||||
<p/>
|
<p/>
|
||||||
Note that this is a geometric variable: it will not sample every 512KB precisely.
|
Note that the sampler is pseudo-random: it will not sample every 512KB precisely.
|
||||||
The goal of this is to ensure high quality sampling even if allocation is
|
The goal of this is to ensure high quality sampling even if allocation is
|
||||||
happening in a fixed pattern (i.e., the same set of objects are being allocated
|
happening in a fixed pattern (i.e., the same set of objects are being allocated
|
||||||
every 512KB).
|
every 512KB).
|
||||||
<p/>
|
<p/>
|
||||||
If another sampling rate is required, the user can call
|
If another sampling interval is required, the user can call
|
||||||
<functionlink id="SetHeapSamplingRate"></functionlink> with a strictly positive integer value, representing
|
<functionlink id="SetHeapSamplingInterval"></functionlink> with a strictly positive integer value,
|
||||||
the new sampling rate.
|
representing the new sampling interval.
|
||||||
<p/>
|
<p/>
|
||||||
This event is sent once the sampled allocation has been performed. It provides the object, stack trace
|
This event is sent once the sampled allocation has been performed. It provides the object, stack trace
|
||||||
of the allocation, the thread allocating, the size of allocation, and the object's class.
|
of the allocation, the thread allocating, the size of allocation, and the object's class.
|
||||||
|
@ -3644,13 +3644,13 @@ JvmtiEnv::GetAvailableProcessors(jint* processor_count_ptr) {
|
|||||||
} /* end GetAvailableProcessors */
|
} /* end GetAvailableProcessors */
|
||||||
|
|
||||||
jvmtiError
|
jvmtiError
|
||||||
JvmtiEnv::SetHeapSamplingRate(jint sampling_rate) {
|
JvmtiEnv::SetHeapSamplingInterval(jint sampling_interval) {
|
||||||
if (sampling_rate < 0) {
|
if (sampling_interval < 0) {
|
||||||
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
|
return JVMTI_ERROR_ILLEGAL_ARGUMENT;
|
||||||
}
|
}
|
||||||
ThreadHeapSampler::set_sampling_rate(sampling_rate);
|
ThreadHeapSampler::set_sampling_interval(sampling_interval);
|
||||||
return JVMTI_ERROR_NONE;
|
return JVMTI_ERROR_NONE;
|
||||||
} /* end SetHeapSamplingRate */
|
} /* end SetHeapSamplingInterval */
|
||||||
|
|
||||||
//
|
//
|
||||||
// System Properties functions
|
// System Properties functions
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
// Cheap random number generator
|
// Cheap random number generator
|
||||||
uint64_t ThreadHeapSampler::_rnd;
|
uint64_t ThreadHeapSampler::_rnd;
|
||||||
// Default is 512kb.
|
// Default is 512kb.
|
||||||
int ThreadHeapSampler::_sampling_rate = 512 * 1024;
|
int ThreadHeapSampler::_sampling_interval = 512 * 1024;
|
||||||
int ThreadHeapSampler::_enabled;
|
int ThreadHeapSampler::_enabled;
|
||||||
|
|
||||||
// Statics for the fast log
|
// Statics for the fast log
|
||||||
@ -69,7 +69,7 @@ static double fast_log2(const double & d) {
|
|||||||
// Generates a geometric variable with the specified mean (512K by default).
|
// Generates a geometric variable with the specified mean (512K by default).
|
||||||
// This is done by generating a random number between 0 and 1 and applying
|
// This is done by generating a random number between 0 and 1 and applying
|
||||||
// the inverse cumulative distribution function for an exponential.
|
// the inverse cumulative distribution function for an exponential.
|
||||||
// Specifically: Let m be the inverse of the sample rate, then
|
// Specifically: Let m be the inverse of the sample interval, then
|
||||||
// the probability distribution function is m*exp(-mx) so the CDF is
|
// the probability distribution function is m*exp(-mx) so the CDF is
|
||||||
// p = 1 - exp(-mx), so
|
// p = 1 - exp(-mx), so
|
||||||
// q = 1 - p = exp(-mx)
|
// q = 1 - p = exp(-mx)
|
||||||
@ -96,14 +96,14 @@ void ThreadHeapSampler::pick_next_geometric_sample() {
|
|||||||
// negative answer.
|
// negative answer.
|
||||||
double log_val = (fast_log2(q) - 26);
|
double log_val = (fast_log2(q) - 26);
|
||||||
double result =
|
double result =
|
||||||
(0.0 < log_val ? 0.0 : log_val) * (-log(2.0) * (get_sampling_rate())) + 1;
|
(0.0 < log_val ? 0.0 : log_val) * (-log(2.0) * (get_sampling_interval())) + 1;
|
||||||
assert(result > 0 && result < SIZE_MAX, "Result is not in an acceptable range.");
|
assert(result > 0 && result < SIZE_MAX, "Result is not in an acceptable range.");
|
||||||
size_t rate = static_cast<size_t>(result);
|
size_t interval = static_cast<size_t>(result);
|
||||||
_bytes_until_sample = rate;
|
_bytes_until_sample = interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadHeapSampler::pick_next_sample(size_t overflowed_bytes) {
|
void ThreadHeapSampler::pick_next_sample(size_t overflowed_bytes) {
|
||||||
if (get_sampling_rate() == 1) {
|
if (get_sampling_interval() == 1) {
|
||||||
_bytes_until_sample = 1;
|
_bytes_until_sample = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -161,12 +161,12 @@ void ThreadHeapSampler::disable() {
|
|||||||
OrderAccess::release_store(&_enabled, 0);
|
OrderAccess::release_store(&_enabled, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ThreadHeapSampler::get_sampling_rate() {
|
int ThreadHeapSampler::get_sampling_interval() {
|
||||||
return OrderAccess::load_acquire(&_sampling_rate);
|
return OrderAccess::load_acquire(&_sampling_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadHeapSampler::set_sampling_rate(int sampling_rate) {
|
void ThreadHeapSampler::set_sampling_interval(int sampling_interval) {
|
||||||
OrderAccess::release_store(&_sampling_rate, sampling_rate);
|
OrderAccess::release_store(&_sampling_interval, sampling_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Methods used in assertion mode to check if a collector is present or not at
|
// Methods used in assertion mode to check if a collector is present or not at
|
||||||
|
@ -36,7 +36,7 @@ class ThreadHeapSampler {
|
|||||||
void pick_next_geometric_sample();
|
void pick_next_geometric_sample();
|
||||||
void pick_next_sample(size_t overflowed_bytes = 0);
|
void pick_next_sample(size_t overflowed_bytes = 0);
|
||||||
static int _enabled;
|
static int _enabled;
|
||||||
static int _sampling_rate;
|
static int _sampling_interval;
|
||||||
|
|
||||||
// Used for assertion mode to determine if there is a path to a TLAB slow path
|
// Used for assertion mode to determine if there is a path to a TLAB slow path
|
||||||
// without a collector present.
|
// without a collector present.
|
||||||
@ -63,8 +63,8 @@ class ThreadHeapSampler {
|
|||||||
static void enable();
|
static void enable();
|
||||||
static void disable();
|
static void disable();
|
||||||
|
|
||||||
static void set_sampling_rate(int sampling_rate);
|
static void set_sampling_interval(int sampling_interval);
|
||||||
static int get_sampling_rate();
|
static int get_sampling_interval();
|
||||||
|
|
||||||
bool sampling_collector_present() const;
|
bool sampling_collector_present() const;
|
||||||
bool remove_sampling_collector();
|
bool remove_sampling_collector();
|
||||||
|
@ -45,8 +45,8 @@ public class HeapMonitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set a specific sampling rate, 0 samples every allocation. */
|
/** Set a specific sampling interval, 0 samples every allocation. */
|
||||||
public native static void setSamplingRate(int rate);
|
public native static void setSamplingInterval(int interval);
|
||||||
public native static void enableSamplingEvents();
|
public native static void enableSamplingEvents();
|
||||||
public native static boolean enableSamplingEventsForTwoThreads(Thread firstThread, Thread secondThread);
|
public native static boolean enableSamplingEventsForTwoThreads(Thread firstThread, Thread secondThread);
|
||||||
public native static void disableSamplingEvents();
|
public native static void disableSamplingEvents();
|
||||||
@ -131,7 +131,7 @@ public class HeapMonitor {
|
|||||||
|
|
||||||
public static int[][][] sampleEverything() {
|
public static int[][][] sampleEverything() {
|
||||||
enableSamplingEvents();
|
enableSamplingEvents();
|
||||||
setSamplingRate(0);
|
setSamplingInterval(0);
|
||||||
|
|
||||||
// Loop around an allocation loop and wait until the tlabs have settled.
|
// Loop around an allocation loop and wait until the tlabs have settled.
|
||||||
final int maxTries = 10;
|
final int maxTries = 10;
|
||||||
|
@ -26,7 +26,7 @@ package MyPackage;
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @build Frame HeapMonitor
|
* @build Frame HeapMonitor
|
||||||
* @summary Verifies the JVMTI Heap Monitor rate when allocating arrays.
|
* @summary Verifies the JVMTI Heap Monitor interval when allocating arrays.
|
||||||
* @compile HeapMonitorArrayAllSampledTest.java
|
* @compile HeapMonitorArrayAllSampledTest.java
|
||||||
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorArrayAllSampledTest
|
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorArrayAllSampledTest
|
||||||
*/
|
*/
|
||||||
@ -46,7 +46,7 @@ public class HeapMonitorArrayAllSampledTest {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
int sizes[] = {1000, 10000, 100000, 1000000};
|
int sizes[] = {1000, 10000, 100000, 1000000};
|
||||||
|
|
||||||
HeapMonitor.setSamplingRate(0);
|
HeapMonitor.setSamplingInterval(0);
|
||||||
HeapMonitor.enableSamplingEvents();
|
HeapMonitor.enableSamplingEvents();
|
||||||
|
|
||||||
for (int currentSize : sizes) {
|
for (int currentSize : sizes) {
|
||||||
@ -56,8 +56,8 @@ public class HeapMonitorArrayAllSampledTest {
|
|||||||
allocate(currentSize);
|
allocate(currentSize);
|
||||||
|
|
||||||
// 10% error ensures a sanity test without becoming flaky.
|
// 10% error ensures a sanity test without becoming flaky.
|
||||||
// Flakiness is due to the fact that this test is dependent on the sampling rate, which is a
|
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
|
||||||
// statistical geometric variable around the sampling rate. This means that the test could be
|
// statistical geometric variable around the sampling interval. This means that the test could be
|
||||||
// unlucky and not achieve the mean average fast enough for the test case.
|
// unlucky and not achieve the mean average fast enough for the test case.
|
||||||
if (!HeapMonitor.statsHaveExpectedNumberSamples(maxIteration, 10)) {
|
if (!HeapMonitor.statsHaveExpectedNumberSamples(maxIteration, 10)) {
|
||||||
throw new RuntimeException("Statistics should show about " + maxIteration + " samples.");
|
throw new RuntimeException("Statistics should show about " + maxIteration + " samples.");
|
||||||
|
@ -25,7 +25,7 @@ package MyPackage;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Verifies the JVMTI SetHeapSamplingRate returns an illegal argument for negative ints.
|
* @summary Verifies the JVMTI SetHeapSamplingInterval returns an illegal argument for negative ints.
|
||||||
* @build Frame HeapMonitor
|
* @build Frame HeapMonitor
|
||||||
* @compile HeapMonitorIllegalArgumentTest.java
|
* @compile HeapMonitorIllegalArgumentTest.java
|
||||||
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorIllegalArgumentTest
|
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorIllegalArgumentTest
|
||||||
|
@ -26,7 +26,7 @@ package MyPackage;
|
|||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @build Frame HeapMonitor
|
* @build Frame HeapMonitor
|
||||||
* @summary Verifies the JVMTI Heap Monitor rate when allocating arrays.
|
* @summary Verifies the JVMTI Heap Monitor interval when allocating arrays.
|
||||||
* @compile HeapMonitorStatArrayCorrectnessTest.java
|
* @compile HeapMonitorStatArrayCorrectnessTest.java
|
||||||
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorStatArrayCorrectnessTest
|
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorStatArrayCorrectnessTest
|
||||||
*/
|
*/
|
||||||
@ -58,7 +58,7 @@ public class HeapMonitorStatArrayCorrectnessTest {
|
|||||||
|
|
||||||
// 111 is as good a number as any.
|
// 111 is as good a number as any.
|
||||||
final int samplingMultiplier = 111;
|
final int samplingMultiplier = 111;
|
||||||
HeapMonitor.setSamplingRate(samplingMultiplier * currentSize);
|
HeapMonitor.setSamplingInterval(samplingMultiplier * currentSize);
|
||||||
|
|
||||||
allocate(currentSize);
|
allocate(currentSize);
|
||||||
|
|
||||||
@ -79,8 +79,8 @@ public class HeapMonitorStatArrayCorrectnessTest {
|
|||||||
expected /= samplingMultiplier;
|
expected /= samplingMultiplier;
|
||||||
|
|
||||||
// 10% error ensures a sanity test without becoming flaky.
|
// 10% error ensures a sanity test without becoming flaky.
|
||||||
// Flakiness is due to the fact that this test is dependent on the sampling rate, which is a
|
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
|
||||||
// statistical geometric variable around the sampling rate. This means that the test could be
|
// statistical geometric variable around the sampling interval. This means that the test could be
|
||||||
// unlucky and not achieve the mean average fast enough for the test case.
|
// unlucky and not achieve the mean average fast enough for the test case.
|
||||||
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
|
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
|
||||||
throw new RuntimeException("Statistics should show about " + expected + " samples.");
|
throw new RuntimeException("Statistics should show about " + expected + " samples.");
|
||||||
|
@ -50,12 +50,12 @@ public class HeapMonitorStatObjectCorrectnessTest {
|
|||||||
HeapMonitor.disableSamplingEvents();
|
HeapMonitor.disableSamplingEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testBigAllocationRate() {
|
private static void testBigAllocationInterval() {
|
||||||
final int sizeObject = 1400;
|
final int sizeObject = 1400;
|
||||||
|
|
||||||
// 111 is as good a number as any.
|
// 111 is as good a number as any.
|
||||||
final int samplingMultiplier = 111;
|
final int samplingMultiplier = 111;
|
||||||
HeapMonitor.setSamplingRate(samplingMultiplier * sizeObject);
|
HeapMonitor.setSamplingInterval(samplingMultiplier * sizeObject);
|
||||||
|
|
||||||
allocate();
|
allocate();
|
||||||
|
|
||||||
@ -79,8 +79,8 @@ public class HeapMonitorStatObjectCorrectnessTest {
|
|||||||
expected /= samplingMultiplier;
|
expected /= samplingMultiplier;
|
||||||
|
|
||||||
// 10% error ensures a sanity test without becoming flaky.
|
// 10% error ensures a sanity test without becoming flaky.
|
||||||
// Flakiness is due to the fact that this test is dependent on the sampling rate, which is a
|
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
|
||||||
// statistical geometric variable around the sampling rate. This means that the test could be
|
// statistical geometric variable around the sampling interval. This means that the test could be
|
||||||
// unlucky and not achieve the mean average fast enough for the test case.
|
// unlucky and not achieve the mean average fast enough for the test case.
|
||||||
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
|
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
|
||||||
throw new RuntimeException("Statistics should show about " + expected + " samples.");
|
throw new RuntimeException("Statistics should show about " + expected + " samples.");
|
||||||
@ -97,15 +97,15 @@ public class HeapMonitorStatObjectCorrectnessTest {
|
|||||||
|
|
||||||
private static void testEveryAllocationSampled() {
|
private static void testEveryAllocationSampled() {
|
||||||
// 0 means sample every allocation.
|
// 0 means sample every allocation.
|
||||||
HeapMonitor.setSamplingRate(0);
|
HeapMonitor.setSamplingInterval(0);
|
||||||
|
|
||||||
allocate();
|
allocate();
|
||||||
|
|
||||||
double expected = maxIteration;
|
double expected = maxIteration;
|
||||||
|
|
||||||
// 10% error ensures a sanity test without becoming flaky.
|
// 10% error ensures a sanity test without becoming flaky.
|
||||||
// Flakiness is due to the fact that this test is dependent on the sampling rate, which is a
|
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
|
||||||
// statistical geometric variable around the sampling rate. This means that the test could be
|
// statistical geometric variable around the sampling interval. This means that the test could be
|
||||||
// unlucky and not achieve the mean average fast enough for the test case.
|
// unlucky and not achieve the mean average fast enough for the test case.
|
||||||
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
|
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
|
||||||
throw new RuntimeException("Statistics should show about " + expected + " samples.");
|
throw new RuntimeException("Statistics should show about " + expected + " samples.");
|
||||||
@ -113,7 +113,7 @@ public class HeapMonitorStatObjectCorrectnessTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
testBigAllocationRate();
|
testBigAllocationInterval();
|
||||||
testEveryAllocationSampled();
|
testEveryAllocationSampled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,20 +25,20 @@ package MyPackage;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @summary Verifies the JVMTI Heap Monitor sampling rate average.
|
* @summary Verifies the JVMTI Heap Monitor sampling interval average.
|
||||||
* @build Frame HeapMonitor
|
* @build Frame HeapMonitor
|
||||||
* @compile HeapMonitorStatRateTest.java
|
* @compile HeapMonitorStatIntervalTest.java
|
||||||
* @requires vm.compMode != "Xcomp"
|
* @requires vm.compMode != "Xcomp"
|
||||||
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorStatRateTest
|
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorStatIntervalTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class HeapMonitorStatRateTest {
|
public class HeapMonitorStatIntervalTest {
|
||||||
|
|
||||||
private native static double getAverageRate();
|
private native static double getAverageInterval();
|
||||||
|
|
||||||
private static boolean testRateOnce(int rate, boolean throwIfFailure) {
|
private static boolean testIntervalOnce(int interval, boolean throwIfFailure) {
|
||||||
HeapMonitor.resetEventStorage();
|
HeapMonitor.resetEventStorage();
|
||||||
HeapMonitor.setSamplingRate(rate);
|
HeapMonitor.setSamplingInterval(interval);
|
||||||
|
|
||||||
HeapMonitor.enableSamplingEvents();
|
HeapMonitor.enableSamplingEvents();
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ public class HeapMonitorStatRateTest {
|
|||||||
|
|
||||||
HeapMonitor.disableSamplingEvents();
|
HeapMonitor.disableSamplingEvents();
|
||||||
|
|
||||||
double expectedCount = allocationTotal * allocationIterations / rate;
|
double expectedCount = allocationTotal * allocationIterations / interval;
|
||||||
|
|
||||||
double error = Math.abs(actualCount - expectedCount);
|
double error = Math.abs(actualCount - expectedCount);
|
||||||
double errorPercentage = error / expectedCount * 100;
|
double errorPercentage = error / expectedCount * 100;
|
||||||
@ -62,30 +62,30 @@ public class HeapMonitorStatRateTest {
|
|||||||
boolean success = (errorPercentage < 10.0);
|
boolean success = (errorPercentage < 10.0);
|
||||||
|
|
||||||
if (!success && throwIfFailure) {
|
if (!success && throwIfFailure) {
|
||||||
throw new RuntimeException("Rate average over 10% for rate " + rate + " -> " + actualCount
|
throw new RuntimeException("Interval average over 10% for interval " + interval + " -> "
|
||||||
+ ", " + expectedCount);
|
+ actualCount + ", " + expectedCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void testRate(int rate) {
|
private static void testInterval(int interval) {
|
||||||
// Test the rate twice, it can happen that the test is "unlucky" and the rate just goes above
|
// Test the interval twice, it can happen that the test is "unlucky" and the interval just goes above
|
||||||
// the 10% mark. So try again to squash flakiness.
|
// the 10% mark. So try again to squash flakiness.
|
||||||
// Flakiness is due to the fact that this test is dependent on the sampling rate, which is a
|
// Flakiness is due to the fact that this test is dependent on the sampling interval, which is a
|
||||||
// statistical geometric variable around the sampling rate. This means that the test could be
|
// statistical geometric variable around the sampling interval. This means that the test could be
|
||||||
// unlucky and not achieve the mean average fast enough for the test case.
|
// unlucky and not achieve the mean average fast enough for the test case.
|
||||||
if (!testRateOnce(rate, false)) {
|
if (!testIntervalOnce(interval, false)) {
|
||||||
testRateOnce(rate, true);
|
testIntervalOnce(interval, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
int[] tab = {1024, 8192};
|
int[] tab = {1024, 8192};
|
||||||
|
|
||||||
for (int rateIdx = 0; rateIdx < tab.length; rateIdx++) {
|
for (int intervalIdx = 0; intervalIdx < tab.length; intervalIdx++) {
|
||||||
testRate(tab[rateIdx]);
|
testInterval(tab[intervalIdx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,8 @@ public class HeapMonitorThreadTest {
|
|||||||
final int numThreads = 5;
|
final int numThreads = 5;
|
||||||
List<ThreadInformation> threadList = ThreadInformation.createThreadList(numThreads);
|
List<ThreadInformation> threadList = ThreadInformation.createThreadList(numThreads);
|
||||||
|
|
||||||
// Sample at a rate of 8k.
|
// Sample at a interval of 8k.
|
||||||
HeapMonitor.setSamplingRate(1 << 13);
|
HeapMonitor.setSamplingInterval(1 << 13);
|
||||||
HeapMonitor.enableSamplingEvents();
|
HeapMonitor.enableSamplingEvents();
|
||||||
|
|
||||||
System.err.println("Starting threads");
|
System.err.println("Starting threads");
|
||||||
|
@ -62,10 +62,10 @@ public class HeapMonitorVMEventsTest implements Cloneable {
|
|||||||
double diff = Math.abs(first - second) * 100;
|
double diff = Math.abs(first - second) * 100;
|
||||||
diff /= first;
|
diff /= first;
|
||||||
|
|
||||||
// Accept a 10% error rate: with objects being allocated: this allows a bit of room in
|
// Accept a 10% error interval: with objects being allocated: this allows a bit of room in
|
||||||
// case other items are getting allocated during the test.
|
// case other items are getting allocated during the test.
|
||||||
if (diff > 10) {
|
if (diff > 10) {
|
||||||
throw new RuntimeException("Error rate is over the accepted rate: " + diff
|
throw new RuntimeException("Error interval is over the accepted interval: " + diff
|
||||||
+ ": " + first + " , " + second);
|
+ ": " + first + " , " + second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,7 +369,7 @@ static int event_storage_get_count(EventStorage* storage) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double event_storage_get_average_rate(EventStorage* storage) {
|
static double event_storage_get_average_interval(EventStorage* storage) {
|
||||||
double accumulation = 0;
|
double accumulation = 0;
|
||||||
int max_size;
|
int max_size;
|
||||||
int i;
|
int i;
|
||||||
@ -839,8 +839,8 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL
|
JNIEXPORT void JNICALL
|
||||||
Java_MyPackage_HeapMonitor_setSamplingRate(JNIEnv* env, jclass cls, jint value) {
|
Java_MyPackage_HeapMonitor_setSamplingInterval(JNIEnv* env, jclass cls, jint value) {
|
||||||
(*jvmti)->SetHeapSamplingRate(jvmti, value);
|
(*jvmti)->SetHeapSamplingInterval(jvmti, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
@ -940,8 +940,8 @@ Java_MyPackage_HeapMonitorNoCapabilityTest_allSamplingMethodsFail(JNIEnv *env,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_capability_error((*jvmti)->SetHeapSamplingRate(jvmti, 1<<19),
|
if (check_capability_error((*jvmti)->SetHeapSamplingInterval(jvmti, 1<<19),
|
||||||
"Set Heap Sampling Rate")) {
|
"Set Heap Sampling Interval")) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -950,23 +950,23 @@ Java_MyPackage_HeapMonitorNoCapabilityTest_allSamplingMethodsFail(JNIEnv *env,
|
|||||||
JNIEXPORT jboolean JNICALL
|
JNIEXPORT jboolean JNICALL
|
||||||
Java_MyPackage_HeapMonitorIllegalArgumentTest_testIllegalArgument(JNIEnv *env,
|
Java_MyPackage_HeapMonitorIllegalArgumentTest_testIllegalArgument(JNIEnv *env,
|
||||||
jclass cls) {
|
jclass cls) {
|
||||||
if (check_error((*jvmti)->SetHeapSamplingRate(jvmti, 0),
|
if (check_error((*jvmti)->SetHeapSamplingInterval(jvmti, 0),
|
||||||
"Sampling rate 0 failed\n")){
|
"Sampling interval 0 failed\n")){
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_error((*jvmti)->SetHeapSamplingRate(jvmti, 1024),
|
if (check_error((*jvmti)->SetHeapSamplingInterval(jvmti, 1024),
|
||||||
"Sampling rate 1024 failed\n")){
|
"Sampling interval 1024 failed\n")){
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check_error((*jvmti)->SetHeapSamplingRate(jvmti, -1),
|
if (!check_error((*jvmti)->SetHeapSamplingInterval(jvmti, -1),
|
||||||
"Sampling rate -1 passed\n")){
|
"Sampling interval -1 passed\n")){
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check_error((*jvmti)->SetHeapSamplingRate(jvmti, -1024),
|
if (!check_error((*jvmti)->SetHeapSamplingInterval(jvmti, -1024),
|
||||||
"Sampling rate -1024 passed\n")){
|
"Sampling interval -1024 passed\n")){
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -974,8 +974,8 @@ Java_MyPackage_HeapMonitorIllegalArgumentTest_testIllegalArgument(JNIEnv *env,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jdouble JNICALL
|
JNIEXPORT jdouble JNICALL
|
||||||
Java_MyPackage_HeapMonitorStatRateTest_getAverageRate(JNIEnv *env, jclass cls) {
|
Java_MyPackage_HeapMonitorStatIntervalTest_getAverageInterval(JNIEnv *env, jclass cls) {
|
||||||
return event_storage_get_average_rate(&global_event_storage);
|
return event_storage_get_average_interval(&global_event_storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct sThreadsFound {
|
typedef struct sThreadsFound {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user