From 2ec959301dba13c238b47ad14cc883d7e79c2f6b Mon Sep 17 00:00:00 2001 From: Jorge Bescos Gascon Date: Fri, 29 Jan 2021 13:49:04 +0100 Subject: [PATCH] Configurable COLLISION_BUFFER_POWER Signed-off-by: Jorge Bescos Gascon --- .../monitoring/core/ReservoirConstants.java | 37 +++++++++++++++++-- .../AbstractNanosReservoirTest.java | 9 +++-- .../TimeWindowStatisticsImplTest.java | 32 ++++++++++++---- core-server/src/test/resources/server.policy | 5 ++- 4 files changed, 67 insertions(+), 16 deletions(-) diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/core/ReservoirConstants.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/core/ReservoirConstants.java index a161fdcf807..9d156823062 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/core/ReservoirConstants.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/monitoring/core/ReservoirConstants.java @@ -1,5 +1,5 @@ /* - * Copyright 2015, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright 2015, 2021 Oracle and/or its affiliates. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,10 @@ package org.glassfish.jersey.server.internal.monitoring.core; +import java.security.PrivilegedAction; +import java.util.logging.Level; +import java.util.logging.Logger; + /** * The constants that determine the behaviour of sliding windows and their trimmers. * @@ -23,21 +27,48 @@ */ public final class ReservoirConstants { + /** + * JVM argument to define the value of {@link COLLISION_BUFFER_POWER}. + * Lower values reduce the memory footprint. + */ + public static final String COLLISION_BUFFER_POWER_JVM_ARG = "monitoring.collision.buffer.power"; + + private static final int DEFAULT_COLLISION_BUFFER_POWER = 8; + /** * Allow for 2^that many duplicate ticks before throwing away measurements. + * This value is by default {@link DEFAULT_COLLISION_BUFFER_POWER}, but it can be configured + * with {@link COLLISION_BUFFER_POWER_JVM_ARG} JVM argument */ - public static final int COLLISION_BUFFER_POWER = 8; + public static final int COLLISION_BUFFER_POWER; /** * The size of the collision buffer derived from the collision buffer power. */ - public static final int COLLISION_BUFFER = 1 << COLLISION_BUFFER_POWER; // 256 + public static final int COLLISION_BUFFER; /** * Only trim on updating once every N. */ public static final int TRIM_THRESHOLD = 256; + static { + PrivilegedAction action = new PrivilegedAction() { + @Override + public Integer run() { + return Integer.getInteger(COLLISION_BUFFER_POWER_JVM_ARG, DEFAULT_COLLISION_BUFFER_POWER); + } + }; + int collisionBuffePower = DEFAULT_COLLISION_BUFFER_POWER; + try { + collisionBuffePower = action.run(); + } catch (SecurityException e) { + Logger.getLogger(ReservoirConstants.class.getName()).log(Level.WARNING, e.getLocalizedMessage(), e); + } + COLLISION_BUFFER_POWER = collisionBuffePower; + COLLISION_BUFFER = 1 << COLLISION_BUFFER_POWER; // 256 + } + private ReservoirConstants() { throw new AssertionError("Instantiation not allowed."); } diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/monitoring/AbstractNanosReservoirTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/monitoring/AbstractNanosReservoirTest.java index 8feaf59089c..abdc1025888 100644 --- a/core-server/src/test/java/org/glassfish/jersey/server/internal/monitoring/AbstractNanosReservoirTest.java +++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/monitoring/AbstractNanosReservoirTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -16,11 +16,12 @@ package org.glassfish.jersey.server.internal.monitoring; +import java.util.concurrent.TimeUnit; + +import org.glassfish.jersey.server.internal.monitoring.core.ReservoirConstants; import org.glassfish.jersey.server.internal.monitoring.core.TimeReservoir; import org.glassfish.jersey.server.internal.monitoring.core.UniformTimeSnapshot; -import java.util.concurrent.TimeUnit; - import static org.junit.Assert.assertEquals; /** @@ -29,7 +30,7 @@ public class AbstractNanosReservoirTest { protected static final double DELTA = 0.0001; - protected static final int COLLISION_BUFFER = 256; + protected static final int COLLISION_BUFFER = ReservoirConstants.COLLISION_BUFFER; protected void reservoirUpdateInNanos(TimeReservoir reservoir, long value, long time) { reservoir.update(value, time, TimeUnit.NANOSECONDS); diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/monitoring/TimeWindowStatisticsImplTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/monitoring/TimeWindowStatisticsImplTest.java index b6ca7c41f0e..9c1b57e7c3e 100644 --- a/core-server/src/test/java/org/glassfish/jersey/server/internal/monitoring/TimeWindowStatisticsImplTest.java +++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/monitoring/TimeWindowStatisticsImplTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -18,8 +18,11 @@ import java.util.concurrent.TimeUnit; +import org.glassfish.jersey.server.internal.monitoring.core.ReservoirConstants; import org.glassfish.jersey.server.internal.monitoring.core.UniformTimeReservoir; +import org.junit.BeforeClass; import org.junit.Test; + import static org.junit.Assert.assertEquals; /** @@ -30,8 +33,21 @@ */ public class TimeWindowStatisticsImplTest { + private static final int COLLISION_BUFFER_POWER = 3; private static final double DELTA = 0.0001; + @BeforeClass + public static void beforeClass() { + System.setProperty(ReservoirConstants.COLLISION_BUFFER_POWER_JVM_ARG, + Integer.toString(COLLISION_BUFFER_POWER)); + } + + @Test + public void jvmLoaded() { + assertEquals(COLLISION_BUFFER_POWER, ReservoirConstants.COLLISION_BUFFER_POWER); + assertEquals(8, ReservoirConstants.COLLISION_BUFFER); + } + @Test public void test() { final long now = System.currentTimeMillis(); @@ -173,30 +189,30 @@ public void testExhaustiveRequestsAtTheSameTime() { final TimeWindowStatisticsImpl.Builder builder = new TimeWindowStatisticsImpl.Builder<>( new SlidingWindowTimeReservoir(1, TimeUnit.SECONDS, now, TimeUnit.MILLISECONDS)); // put multiple requests at the beginning so that even the COLLISION_BUFFER bounds is tested - for (int i = 0; i < 256; ++i) { + for (int i = 0; i < ReservoirConstants.COLLISION_BUFFER; ++i) { builder.addRequest(now, 10L); } // add one more request which should be visible at 'now + 1001' builder.addRequest(now + 1, 10L); // put multiple requests in the middle of the window - for (int i = 0; i < 256; ++i) { + for (int i = 0; i < ReservoirConstants.COLLISION_BUFFER; ++i) { builder.addRequest(now + 500, 10L); } - check(builder, now + 500, 256 * 2 + 1, 10, 10, 10, 256 * 2 * 2 + 1 * 2); + check(builder, now + 500, ReservoirConstants.COLLISION_BUFFER * 2 + 1, 10, 10, 10, ReservoirConstants.COLLISION_BUFFER * 2 * 2 + 1 * 2); // put multiple requests at the end of the window - for (int i = 0; i < 256; ++i) { + for (int i = 0; i < ReservoirConstants.COLLISION_BUFFER; ++i) { builder.addRequest(now + 1000, 10L); } - check(builder, now + 1000, 256 * 3 + 1, 10, 10, 10, 256 * 3 + 1); + check(builder, now + 1000, ReservoirConstants.COLLISION_BUFFER * 3 + 1, 10, 10, 10, ReservoirConstants.COLLISION_BUFFER * 3 + 1); // at 'now + 1001' all the requests from 'now' should be gone - check(builder, now + 1001, 256 * 2 + 1, 10, 10, 10, 256 * 2 + 1); + check(builder, now + 1001, ReservoirConstants.COLLISION_BUFFER * 2 + 1, 10, 10, 10, ReservoirConstants.COLLISION_BUFFER * 2 + 1); // at 'now + 1002' the one additional request we added is gone - check(builder, now + 1002, 256 * 2, 10, 10, 10, 256 * 2); + check(builder, now + 1002, ReservoirConstants.COLLISION_BUFFER * 2, 10, 10, 10, ReservoirConstants.COLLISION_BUFFER * 2); } /** diff --git a/core-server/src/test/resources/server.policy b/core-server/src/test/resources/server.policy index e37eeda4dd9..6df86503e89 100644 --- a/core-server/src/test/resources/server.policy +++ b/core-server/src/test/resources/server.policy @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -60,6 +60,9 @@ grant codebase "file:${project.build.directory}/test-classes/-" { permission java.lang.RuntimePermission "accessClassInPackage.sun.misc.*"; permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect"; permission java.lang.RuntimePermission "reflectionFactoryAccess"; + + // Needed by TimeWindowStatisticsImplTest + permission java.util.PropertyPermission "monitoring.collision.buffer.power", "read,write"; }; grant codebase "file:${project.build.directory}/classes/-" {