Improve global-cached-lookups metric reporting (#13219)

It was found that the namespace/cache/heapSizeInBytes metric that tracks the total heap size in bytes of all lookup caches loaded on a service instance was being under reported. We were not accounting for the memory overhead of the String object, which I've found in testing to be ~40 bytes. While this overhead may be java version dependent, it should not vary much, and accounting for this provides a better estimate. Also fixed some logging, and reading bytes from the JDBI result set a little more efficient by saving hash table lookups. Also added some of the lookup metrics to the default statsD emitter metric whitelist.
This commit is contained in:
zachjsh 2022-10-13 18:51:54 -04:00 committed by GitHub
parent 45dfd679e9
commit 2f2fe20089
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 14 additions and 8 deletions

View File

@ -169,5 +169,8 @@
"segment/compacted/bytes" : { "dimensions" : ["dataSource"], "type" : "gauge" }, "segment/compacted/bytes" : { "dimensions" : ["dataSource"], "type" : "gauge" },
"segment/compacted/count" : { "dimensions" : ["dataSource"], "type" : "count" }, "segment/compacted/count" : { "dimensions" : ["dataSource"], "type" : "count" },
"interval/compacted/count" : { "dimensions" : ["dataSource"], "type" : "count" } "interval/compacted/count" : { "dimensions" : ["dataSource"], "type" : "count" },
"namespace/cache/numEntries" : { "dimensions" : [], "type" : "gauge" },
"namespace/cache/heapSizeInBytes" : { "dimensions" : [], "type" : "gauge" }
} }

View File

@ -245,7 +245,8 @@ public class MapPopulator<K, V>
{ {
if (null != o) { if (null != o) {
if (o.getClass().getName().equals(STRING_CLASS_NAME)) { if (o.getClass().getName().equals(STRING_CLASS_NAME)) {
return ((String) (o)).length(); // Each String object has ~40 bytes of overhead
return ((long) ((String) (o)).length() * Character.BYTES) + 40;
} else if (o.getClass().getName().equals(DOUBLE_CLASS_NAME)) { } else if (o.getClass().getName().equals(DOUBLE_CLASS_NAME)) {
return 8; return 8;
} else if (o.getClass().getName().equals(FLOAT_CLASS_NAME)) { } else if (o.getClass().getName().equals(FLOAT_CLASS_NAME)) {

View File

@ -105,7 +105,7 @@ public final class JdbcCacheGenerator implements CacheGenerator<JdbcExtractionNa
); );
final long duration = System.nanoTime() - startNs; final long duration = System.nanoTime() - startNs;
LOG.info( LOG.info(
"Finished loading %,d values (%d bytes) for [%s] in %,d ns", "Finished loading %d values (%d bytes) for [%s] in %d ns",
populateResult.getEntries(), populateResult.getEntries(),
populateResult.getBytes(), populateResult.getBytes(),
entryId, entryId,
@ -151,7 +151,7 @@ public final class JdbcCacheGenerator implements CacheGenerator<JdbcExtractionNa
final String keyColumn = namespace.getKeyColumn(); final String keyColumn = namespace.getKeyColumn();
return handle.createQuery(buildLookupQuery(table, filter, keyColumn, valueColumn)) return handle.createQuery(buildLookupQuery(table, filter, keyColumn, valueColumn))
.map((index1, r1, ctx1) -> new Pair<>(r1.getString(keyColumn), r1.getString(valueColumn))) .map((index1, r1, ctx1) -> new Pair<>(r1.getString(1), r1.getString(2)))
.iterator(); .iterator();
} }

View File

@ -156,7 +156,7 @@ public final class UriCacheGenerator implements CacheGenerator<UriExtractionName
); );
final long duration = System.nanoTime() - startNs; final long duration = System.nanoTime() - startNs;
log.info( log.info(
"Finished loading %,d values (%d bytes) from %,d lines for [%s] in %,d ns", "Finished loading %d values (%d bytes) from %d lines for [%s] in %d ns",
populateResult.getEntries(), populateResult.getEntries(),
populateResult.getBytes(), populateResult.getBytes(),
populateResult.getLines(), populateResult.getLines(),

View File

@ -150,7 +150,9 @@ public class OnHeapNamespaceExtractionCacheManager extends NamespaceExtractionCa
size += key.length() + value.length(); size += key.length() + value.length();
} }
} }
// Each String object has ~40 bytes of overhead, and x 2 for key and value strings
long heapSizeInBytes = (80 * numEntries) + size * Character.BYTES;
serviceEmitter.emit(ServiceMetricEvent.builder().build("namespace/cache/numEntries", numEntries)); serviceEmitter.emit(ServiceMetricEvent.builder().build("namespace/cache/numEntries", numEntries));
serviceEmitter.emit(ServiceMetricEvent.builder().build("namespace/cache/heapSizeInBytes", size * Character.BYTES)); serviceEmitter.emit(ServiceMetricEvent.builder().build("namespace/cache/heapSizeInBytes", heapSizeInBytes));
} }
} }

View File

@ -39,7 +39,7 @@ public class MapPopulatorTest
public void test_getByteLengthOfObject_string_stringLength() public void test_getByteLengthOfObject_string_stringLength()
{ {
String o = "string"; String o = "string";
Assert.assertEquals(o.length(), MapPopulator.getByteLengthOfObject(o)); Assert.assertEquals((o.length() * Character.BYTES) + 40, MapPopulator.getByteLengthOfObject(o));
} }
@Test @Test
@ -184,7 +184,7 @@ public class MapPopulatorTest
Assert.assertEquals(expectedMap, map); Assert.assertEquals(expectedMap, map);
Assert.assertEquals(4, result.getEntries()); Assert.assertEquals(4, result.getEntries());
Assert.assertEquals(0, result.getLines()); Assert.assertEquals(0, result.getLines());
Assert.assertEquals(16L, result.getBytes()); Assert.assertEquals(192L, result.getBytes());
} }
@Test @Test