Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8247615

Initialize the bytes left for the heap sampler

    Details

    • Subcomponent:
    • Resolved In Build:
      b07

      Description

      Copied over from https://mail.openjdk.java.net/pipermail/serviceability-dev/2020-June/031758.html

      JVMTI callback SampledObjectAlloc is currently always called for the first
      allocation of a thread. This generates a lot of bias in an application that
      regularly starts new threads.

      I tested this with latest Java 11 and Java 15.

      E.g. here is a sample that creates 100 threads and allocates one object in
      each thread.

          public class AllocationProfilingBiasReproducer {
              public static void main(String[] args) throws Exception {
                  for (int i = 0; i < 100; i++) {
                      new Thread(new Task(), "Task " + i).start();
                      Thread.sleep(1);
                  }
                  Thread.sleep(1000);
              }
              private static class Task implements Runnable {
                  @Override
                  public void run() {
                      new A();
                  }
              }
              private static class A {
              }
          }

      I built a simple JVMTI agent that registers SampledObjectAlloc callback and
      sets interval to 1 MB with SetHeapSamplingInterval. The callback simply
      logs thread name and class name of allocated object.

      I see the following output:

      SampledObjectAlloc Ljava/lang/String; via Task 0
      SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 1
      SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 2
      SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 3
      SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 4
      SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 5
      SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 6
      SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 7
      SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 8
      SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 9
      SampledObjectAlloc LAllocationProfilingBiasReproducer$A; via Task 10
      ...

      This is not expected.

      I set a breakpoint in my SampledObjectAlloc callback and observed the
      following:

      In MemAllocator::Allocation::notify_allocation_jvmti_sampler() the local
      var bytes_since_last is always 0xf1f1f1f1f1f1f1f1 for first allocation of a
      thread. So first allocation is always reported to my agent.

      ThreadLocalAllocBuffer::_bytes_since_last_sample_point does not seem to be
      explicitly initialized before accessing it for the first time. I assume
      0xf1f1f1f1f1f1f1f1 is a default value provided by some Hotspot allocator.
      Only after the first event fired, notify_allocation_jvmti_sampler
      calls ThreadLocalAllocBuffer::set_sample_end which initializes
      _bytes_since_last_sample_point to a proper value.

        Attachments

          Activity

            People

            • Assignee:
              jcbeyler Jean Christophe Beyler
              Reporter:
              jcbeyler Jean Christophe Beyler
            • Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: