blob: 3ecc9f5aefec77b4a3fe91b07788d2c0b9278a26 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.unomi.metrics.internal;
import org.apache.unomi.metrics.MetricsService;
import org.junit.Test;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
public class MetricsServiceTest {
public static final int THREAD_POOL_SIZE = 100;
public static final int WORKER_COUNT = 100000;
class Worker implements Callable<BigInteger> {
MetricsService metricsService;
String workerName;
int nbLoops = 1000;
public Worker(MetricsService metricsService, String workerName, int nbLoops) {
this.metricsService = metricsService;
this.workerName = workerName;
this.nbLoops = nbLoops;
}
@Override
public BigInteger call() {
long startTime = System.currentTimeMillis();
BigInteger n1=BigInteger.ZERO,n2=BigInteger.ONE,n3=BigInteger.ZERO;
for (int i = 0; i < nbLoops; i++) {
n3 = n1.add(n2);
n1 = n2;
n2 = n3;
}
if (metricsService != null) {
metricsService.updateTimer(workerName, startTime);
}
return n3;
}
}
@Test
public void testMetricsImpact() throws InterruptedException {
int workerCount = WORKER_COUNT;
System.out.println("Free memory=" + humanReadableByteCount(Runtime.getRuntime().freeMemory(), false));
System.out.println("Testing with metrics deactivated...");
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
List<Callable<BigInteger>> todo = new ArrayList<Callable<BigInteger>>(workerCount);
MetricsServiceImpl metricsService = new MetricsServiceImpl();
metricsService.setActivated(false);
Random random = new Random();
long withoutMetricsStartTime = System.currentTimeMillis();
for (int i = 0; i < workerCount; i++) {
todo.add(new Worker(null, "worker-" + i, 1000+ random.nextInt(1000)));
}
List<Future<BigInteger>> answers = executorService.invokeAll(todo);
long withoutMetricsTotalTime = System.currentTimeMillis() - withoutMetricsStartTime;
System.out.println("Total time without metrics=" + withoutMetricsTotalTime + "ms");
assertEquals("Metrics should be empty", 0, metricsService.getMetrics().size());
System.out.println("Free memory=" + humanReadableByteCount(Runtime.getRuntime().freeMemory(), false));
System.out.println("Testing with metrics activated (but no callers)...");
todo.clear();
metricsService.setActivated(true);
assertEquals("Callers should be completely empty", metricsService.getCallersStatus().size(), 0);
long withMetricsStartTime = System.currentTimeMillis();
for (int i = 0; i < workerCount; i++) {
todo.add(new Worker(metricsService, "worker-" + i, 1000+ random.nextInt(1000)));
}
answers = executorService.invokeAll(todo);
long withMetricsTotalTime = System.currentTimeMillis() - withMetricsStartTime;
System.out.println("Total time with metrics (no callers) =" + withMetricsTotalTime + "ms");
assertEquals("Metrics count is not correct", workerCount, metricsService.getMetrics().size());
System.out.println("Free memory=" + humanReadableByteCount(Runtime.getRuntime().freeMemory(), false));
System.out.println("Testing with metrics activated (all callers activated)...");
todo.clear();
metricsService.setActivated(true);
metricsService.setCallerActivated("*", true);
assertNotEquals("Callers should not be completely empty", metricsService.getCallersStatus().size(), 0);
long withMetricsAndCallersStartTime = System.currentTimeMillis();
for (int i = 0; i < workerCount; i++) {
todo.add(new Worker(metricsService, "worker-" + i, 1000+ random.nextInt(1000)));
}
answers = executorService.invokeAll(todo);
long withMetricsAndCallersTotalTime = System.currentTimeMillis() - withMetricsAndCallersStartTime;
System.out.println("Total time with metrics (with callers)=" + withMetricsAndCallersTotalTime + "ms");
assertEquals("Metrics count is not correct", workerCount, metricsService.getMetrics().size());
System.out.println("Free memory=" + humanReadableByteCount(Runtime.getRuntime().freeMemory(), false));
}
@Test
public void testStackTraceGenerationSpeed() {
long startWithException = System.currentTimeMillis();
for (long i = 0; i < 100000; i++) {
String stackTrace = Arrays.toString(new Exception().getStackTrace());
int stackTraceHash = stackTrace.hashCode();
}
System.out.println("Total time using exception and getStackTrace = " + (System.currentTimeMillis()
- startWithException) + "ms.");
long startWithThrowable = System.currentTimeMillis();
for (long i = 0; i < 100000; i++) {
String stackTrace = Arrays.toString(new Throwable().getStackTrace());
int stackTraceHash = stackTrace.hashCode();
}
System.out.println("Total time using throwable and getStackTrace = " + (System.currentTimeMillis()
- startWithThrowable) + "ms.");
long startWithThread = System.currentTimeMillis();
for (long i = 0; i < 100000; i++) {
String stackTtrace = Arrays.toString(Thread.currentThread().getStackTrace());
int stackTraceHash = stackTtrace.hashCode();
}
System.out.println("Total time using current thread and getStackTrace = " + (System.currentTimeMillis()
- startWithThread) + "ms.");
System.out.println("Free memory=" + humanReadableByteCount(Runtime.getRuntime().freeMemory(), false));
}
public static String humanReadableByteCount(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit) return bytes + " B";
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp-1) + (si ? "" : "i");
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
}
}