0
  private final Map<String, Path> relativePathsByKey = new ConcurrentHashMap<>();

  private byte[] readValue(final String key) throws IOException {
    Path relativePath = relativePathsByKey.get(key);
    final byte[] returnValue;
    if (relativePath != null) {
      returnValue = readValue(getCacheFileFullPath(relativePath, key));
    } else {
      relativePath = createRelativeFilePath(key);
      Path fullPath = getCacheFileFullPath(relativePath, key);
      if (fullPath.toFile().exists()) {
        returnValue = readValue(fullPath);
        relativePathsByKey.put(key, relativePath);
      } else {
        returnValue = null;
      }
    }
    return returnValue;
  }

  private Path createRelativeFilePath(final String key) {
    final MLFileCacheKey fileCacheKey =
        new MLFileCacheKey(
            key, offHeapCacheConfig.getLevels(), offHeapCacheConfig.getSegmentSize());

    final StringBuilder sb = new StringBuilder();
    final String[] segments = fileCacheKey.getKeySegments();
    for (int i = 0; i < segments.length; i++) {
      final int hash = segments[i].hashCode();
      sb.append('d')
          .append(i)
          .append('_')
          .append(Math.abs(hash % offHeapCacheConfig.getDirectoriesPerLevel()))
          .append(File.separator);
    }
    return Paths.get(sb.toString().intern());
  }

I keep the file paths in a ConcurrentHashMap for quick access to files. I took two heap dumps at different times. The results are shown below. What I found is that the size (memory) of the map is totally not making sense when compared to each other.

The second last column from the right is the retained size in bytes as shown by yourkit heap dump:

When the map had ~10M entries - retained size = 1.7GB enter image description here

When it had ~20M entries - retained size = 6.4GB. It is not making sense at all to me when compared to the above picture. enter image description here

When I went into each node of the map I see that each node in the map is having a list of next nodes: node from the map having ~20M entries and the node's retained size = 2,368 bytes enter image description here

node from the map with ~10M entries and the node's retained size is much less 1,216 bytes: enter image description here

Then I went ahead and checked the retained objects of one of the "next" nodes in both dumps: The node from the dump with ~20M entries is referencing two extra objects that are taking up the extra space: From the dump with ~20M entries: enter image description here One from the dump with ~10M entries: enter image description here

I'm now confused as to whether it is the GC that's lagging or I took the two dumps at times that did not line up with the way the map internally organizes itself in Java.

P K
  • 69
  • 7
  • It's not GC (garbage won't show up in heap dumps). The difference seems to be in the keys. For some reason, in the smaller one, the keys are not being counted as part of the retained size of the nodes. – Tim Moore Jan 29 '23 at 11:50
  • What version of Java is used? – Tim Moore Jan 29 '23 at 11:52
  • It's hard to know what's happening from the heap dump screenshots alone. It would be helpful if you could show the code that adds entries to the map. My wild guess is that the initial ~10M entries have hash keys that are interned strings, which are allocated in the string pool and perhaps not counted as part of the retained size of the node for that reason. Then, new entries are added later with normally allocated strings, which _are_ counted as part of the retained size of the node. Either way, the same amount of memory is used, it's just counted differently. Just a guess. – Tim Moore Jan 29 '23 at 12:06
  • @TimMoore java 1.8. Added the code that puts into the map. – P K Jan 29 '23 at 20:32
  • 1
    Thanks for the additional code, but this doesn’t show how the keys are created. I just learned that YourKit only includes child objects in the retained size of a parent object if the parent has the only reference to the child. Objects with multiple references are not counted in any other object’s retained size. Could that explain it? See https://stackoverflow.com/q/23941688/29470 – Tim Moore Jan 29 '23 at 21:05

0 Answers0