This is an automated email from the ASF dual-hosted git repository. avijayan pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/ambari.git
commit 01243e2b639c08a4172b378dbcac96bb2de3fe67 Author: Aravindan Vijayan <avija...@hortonworks.com> AuthorDate: Tue Mar 13 16:23:19 2018 -0700 AMBARI-23225: Ambari Server login fails due to TimelineMetricsCacheSizeOfEngine error in AMS perf branch. --- .../cache/TimelineMetricsCacheSizeOfEngine.java | 85 ++++++++++++++++++++-- 1 file changed, 77 insertions(+), 8 deletions(-) diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/timeline/cache/TimelineMetricsCacheSizeOfEngine.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/timeline/cache/TimelineMetricsCacheSizeOfEngine.java index 8b54017..baae751 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/timeline/cache/TimelineMetricsCacheSizeOfEngine.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/metrics/timeline/cache/TimelineMetricsCacheSizeOfEngine.java @@ -17,24 +17,61 @@ */ package org.apache.ambari.server.controller.metrics.timeline.cache; -import org.apache.hadoop.metrics2.sink.timeline.cache.TimelineMetricsEhCacheSizeOfEngine; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.hadoop.metrics2.sink.timeline.TimelineMetric; +import org.apache.hadoop.metrics2.sink.timeline.TimelineMetrics; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.sf.ehcache.pool.Size; +import net.sf.ehcache.pool.SizeOfEngine; +import net.sf.ehcache.pool.impl.DefaultSizeOfEngine; +import net.sf.ehcache.pool.sizeof.ReflectionSizeOf; +import net.sf.ehcache.pool.sizeof.SizeOf; + /** * Cache sizing engine that reduces reflective calls over the Object graph to * find total Heap usage. */ -public class TimelineMetricsCacheSizeOfEngine extends TimelineMetricsEhCacheSizeOfEngine { +public class TimelineMetricsCacheSizeOfEngine implements SizeOfEngine { private final static Logger LOG = LoggerFactory.getLogger(TimelineMetricsCacheSizeOfEngine.class); + public static int DEFAULT_MAX_DEPTH = 1000; + public static boolean DEFAULT_ABORT_WHEN_MAX_DEPTH_EXCEEDED = false; + + private SizeOfEngine underlying = null; + SizeOf reflectionSizeOf = new ReflectionSizeOf(); + + // Optimizations + private volatile long timelineMetricPrimitivesApproximation = 0; + + private long sizeOfMapEntry; + private long sizeOfMapEntryOverhead; + + private TimelineMetricsCacheSizeOfEngine(SizeOfEngine underlying) { + this.underlying = underlying; + } public TimelineMetricsCacheSizeOfEngine() { - // Invoke default constructor in base class + this(new DefaultSizeOfEngine(DEFAULT_MAX_DEPTH, DEFAULT_ABORT_WHEN_MAX_DEPTH_EXCEEDED)); + + this.sizeOfMapEntry = reflectionSizeOf.sizeOf(new Long(1)) + + reflectionSizeOf.sizeOf(new Double(2.0)); + + //SizeOfMapEntryOverhead = SizeOfMapWithOneEntry - (SizeOfEmptyMap + SizeOfOneEntry) + TreeMap<Long, Double> map = new TreeMap<>(); + long emptyMapSize = reflectionSizeOf.sizeOf(map); + map.put(new Long(1), new Double(2.0)); + long sizeOfMapOneEntry = reflectionSizeOf.deepSizeOf(DEFAULT_MAX_DEPTH, DEFAULT_ABORT_WHEN_MAX_DEPTH_EXCEEDED, map).getCalculated(); + this.sizeOfMapEntryOverhead = sizeOfMapOneEntry - (emptyMapSize + this.sizeOfMapEntry); + + LOG.info("Creating custom sizeof engine for TimelineMetrics."); } @Override - public long getSizeOfEntry(Object key, Object value) { + public Size sizeOf(Object key, Object value, Object container) { try { LOG.debug("BEGIN - Sizeof, key: {}, value: {}", key, value); @@ -48,7 +85,7 @@ public class TimelineMetricsCacheSizeOfEngine extends TimelineMetricsEhCacheSize size += getTimelineMetricCacheValueSize((TimelineMetricsCacheValue) value); } // Mark size as not being exact - return size; + return new Size(size, false); } finally { LOG.debug("END - Sizeof, key: {}", key); } @@ -71,13 +108,45 @@ public class TimelineMetricsCacheSizeOfEngine extends TimelineMetricsEhCacheSize private long getTimelineMetricCacheValueSize(TimelineMetricsCacheValue value) { long size = 16; // startTime + endTime - + TimelineMetrics metrics = value.getTimelineMetrics(); size += 8; // Object reference - size += getTimelineMetricsSize(value.getTimelineMetrics()); // TreeMap + if (metrics != null) { + for (TimelineMetric metric : metrics.getMetrics()) { + + if (timelineMetricPrimitivesApproximation == 0) { + timelineMetricPrimitivesApproximation += reflectionSizeOf.sizeOf(metric.getMetricName()); + timelineMetricPrimitivesApproximation += reflectionSizeOf.sizeOf(metric.getAppId()); + timelineMetricPrimitivesApproximation += reflectionSizeOf.sizeOf(metric.getHostName()); + timelineMetricPrimitivesApproximation += reflectionSizeOf.sizeOf(metric.getInstanceId()); + timelineMetricPrimitivesApproximation += reflectionSizeOf.sizeOf(metric.getStartTime()); + timelineMetricPrimitivesApproximation += reflectionSizeOf.sizeOf(metric.getType()); + timelineMetricPrimitivesApproximation += 8; // Object overhead + + LOG.debug("timelineMetricPrimitivesApproximation bytes = {}", timelineMetricPrimitivesApproximation); + } + size += timelineMetricPrimitivesApproximation; + + Map<Long, Double> metricValues = metric.getMetricValues(); + if (metricValues != null && !metricValues.isEmpty()) { + // Numeric wrapper: 12 bytes + 8 bytes Data type + 4 bytes alignment = 48 (Long, Double) + // Tree Map: 12 bytes for header + 20 bytes for 5 object fields : pointers + 1 byte for flag = 40 + LOG.debug("Size of metric value: {}", (sizeOfMapEntry + sizeOfMapEntryOverhead) * metricValues.size()); + size += (sizeOfMapEntry + sizeOfMapEntryOverhead) * metricValues.size(); // Treemap size is O(1) + } + } + LOG.debug("Total Size of metric values in cache: {}", size); + } return size; } + @Override + public SizeOfEngine copyWith(int maxDepth, boolean abortWhenMaxDepthExceeded) { + LOG.debug("Copying tracing sizeof engine, maxdepth: {}, abort: {}", + maxDepth, abortWhenMaxDepthExceeded); -} + return new TimelineMetricsCacheSizeOfEngine( + underlying.copyWith(maxDepth, abortWhenMaxDepthExceeded)); + } +} \ No newline at end of file -- To stop receiving notification emails like this one, please contact avija...@apache.org.