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

Taking into account overflowed bytes might bias the Heap Sampler

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • 11, 12
    • hotspot

      The current implementation of the heap sampler seems to perhaps add extra error in the sampling interval due to trying to fix the overflowed bytes for the next sample. This results in not getting the expected number of objects when attempting to "unsample" the data.

      Seemingly this will happen a lot when a big object is allocated before a smaller object since it increases the risk of the smaller object being sampled though it might not have been to begin with. What is currently not sure is: is the bias a corner case, is there a better means to handle the overflowed bytes, etc. A little study should be performed to figure this out.

      The test case presented below shows that there is a % difference when considering a version of the code with vs without the overflow handling. Without being almost better in every case for the test case.

      For more information:

      Consider the code in the heap sampler:

        // Try to correct sample size by removing extra space from last allocation.
        if (overflowed_bytes > 0 && _bytes_until_sample > overflowed_bytes) {
          _bytes_until_sample -= overflowed_bytes;
        }

      Now consider this example:
      public class Main {
        public static void main(String[] args) throws Exception {
          allocate_large_small();
          allocate_small();
        }
                                         
        private static void allocate_large_small() {
          for (int i = 0; i < 100000; i++) {
            byte a256k[] = new byte[256 * 1024];
            byte a1k[] = new byte[1024];
            a256k = new byte[256 * 1024];
            byte a512[] = new byte[512];
            a256k = new byte[256 * 1024];
            byte a256[] = new byte[256];
            a256k = new byte[256 * 1024];
            byte a16[] = new byte[16];
          }
        }

        private static void allocate_small() {
          for (int i = 0; i < 1000000; i++) {
            byte a1k[] = new byte[1024];
            byte a512[] = new byte[512];
            byte a256[] = new byte[256];
            byte a16[] = new byte[16];
          }
        }
      }

      When unsampling the allocations per line, we get these error rates:
      Line: 11; Orig (230030.00, 60304664800.00); Ratio 2.541375 Unsampled (584592.38, 153256739242.96) Error 16.918477
      Line: 12; Orig (1333.00, 1386320.00); Ratio 504.623242 Unsampled (672662.78, 699569293.16) Error 34.532556
      Line: 13; Orig (230673.00, 60473233680.00); Ratio 2.541375 Unsampled (586226.49, 153685135901.37) Error 17.245297
      Line: 14; Orig (988.00, 521664.00); Ratio 993.469781 Unsampled (981548.14, 518257419.78) Error 96.309629
      Line: 15; Orig (230046.00, 60308859360.00); Ratio 2.541375 Unsampled (584633.05, 153267399190.92) Error 16.926609
      Line: 16; Orig (358.00, 97376.00); Ratio 1928.029455 Unsampled (690234.54, 187743796.21) Error 38.046909
      Line: 17; Orig (230489.00, 60424996240.00); Ratio 2.541375 Unsampled (585758.87, 153562546499.90) Error 17.151775
      Line: 18; Orig (383.00, 12256.00); Ratio 16384.500005 Unsampled (6275263.50, 200808432.06) Error 1155.052700
      Line: 24; Orig (9967.00, 10365680.00); Ratio 504.623242 Unsampled (5029579.86, 5230763049.48) Error 0.591597
      Line: 25; Orig (5100.00, 2692800.00); Ratio 993.469781 Unsampled (5066695.88, 2675215425.99) Error 1.333918
      Line: 26; Orig (2660.00, 723520.00); Ratio 1928.029455 Unsampled (5128558.35, 1394967871.28) Error 2.571167
      Line: 27; Orig (309.00, 9888.00); Ratio 16384.500005 Unsampled (5062810.50, 162009936.05) Error 1.256210

      Without that code, we get:
      Line: 11; Orig (196440.00, 51498710400.00); Ratio 2.541375 Unsampled (499227.61, 130877511006.77) Error 0.154477
      Line: 12; Orig (1165.00, 1211600.00); Ratio 504.623242 Unsampled (587886.08, 611401520.28) Error 17.577215
      Line: 13; Orig (197298.00, 51723643680.00); Ratio 2.541375 Unsampled (501408.11, 131449150715.81) Error 0.281622
      Line: 14; Orig (743.00, 392304.00); Ratio 993.469781 Unsampled (738148.05, 389742168.92) Error 47.629609
      Line: 15; Orig (195676.00, 51298420160.00); Ratio 2.541375 Unsampled (497286.00, 130368498491.96) Error 0.542799
      Line: 16; Orig (301.00, 81872.00); Ratio 1928.029455 Unsampled (580336.87, 157851627.54) Error 16.067373
      Line: 17; Orig (197393.00, 51748548880.00); Ratio 2.541375 Unsampled (501649.54, 131512444156.79) Error 0.329909
      Line: 18; Orig (214.00, 6848.00); Ratio 16384.500005 Unsampled (3506283.00, 112201056.03) Error 601.256600
      Line: 24; Orig (10002.00, 10402080.00); Ratio 504.623242 Unsampled (5047241.67, 5249131335.50) Error 0.944833
      Line: 25; Orig (5115.00, 2700720.00); Ratio 993.469781 Unsampled (5081597.93, 2683083706.65) Error 1.631959
      Line: 26; Orig (2581.00, 702032.00); Ratio 1928.029455 Unsampled (4976244.02, 1353538374.35) Error 0.475120
      Line: 27; Orig (329.00, 10528.00); Ratio 16384.500005 Unsampled (5390500.50, 172496016.05) Error 7.810010

      So this code does have an effect on unsampling exactness and we should study it and determine its correctness.

            Unassigned Unassigned
            jcbeyler Jean Christophe Beyler
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: