mirror of https://github.com/apache/druid.git
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:
parent
45dfd679e9
commit
2f2fe20089
|
@ -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" }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue