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.
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.