jetty-9 ConcurrentScheduler refinements

This commit is contained in:
Greg Wilkins 2012-09-03 15:29:01 +10:00
parent c3776764f4
commit e29e55ffcc
3 changed files with 354 additions and 1 deletions

View File

@ -0,0 +1,63 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.util.thread;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
public class ScheduledExecutionServiceScheduler extends AbstractLifeCycle implements Scheduler
{
ScheduledExecutorService _service;
public ScheduledExecutionServiceScheduler()
{
}
@Override
protected void doStart() throws Exception
{
_service=new ScheduledThreadPoolExecutor(1);
super.doStart();
}
@Override
protected void doStop() throws Exception
{
super.doStop();
_service=null;
}
@Override
public Task schedule(final Runnable task, final long delay, final TimeUnit units)
{
final Future<?> future = _service.schedule(task,delay,units);
return new Task()
{
@Override
public boolean cancel()
{
return future.cancel(true);
}
};
}
}

View File

@ -0,0 +1,290 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.util;
import java.lang.management.CompilationMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class BenchmarkHelper implements Runnable
{
private final OperatingSystemMXBean operatingSystem;
private final CompilationMXBean jitCompiler;
private final MemoryMXBean heapMemory;
private final AtomicInteger starts = new AtomicInteger();
private volatile MemoryPoolMXBean youngMemoryPool;
private volatile MemoryPoolMXBean survivorMemoryPool;
private volatile MemoryPoolMXBean oldMemoryPool;
private volatile boolean hasMemoryPools;
private volatile ScheduledFuture<?> memoryPoller;
private volatile GarbageCollectorMXBean youngCollector;
private volatile GarbageCollectorMXBean oldCollector;
private volatile boolean hasCollectors;
private volatile ScheduledExecutorService scheduler;
private volatile boolean polling;
private volatile long lastYoungUsed;
private volatile long startYoungCollections;
private volatile long startYoungCollectionsTime;
private volatile long totalYoungUsed;
private volatile long lastSurvivorUsed;
private volatile long totalSurvivorUsed;
private volatile long lastOldUsed;
private volatile long startOldCollections;
private volatile long startOldCollectionsTime;
private volatile long totalOldUsed;
private volatile long startTime;
private volatile long startProcessCPUTime;
private volatile long startJITCTime;
public BenchmarkHelper()
{
this.operatingSystem = ManagementFactory.getOperatingSystemMXBean();
this.jitCompiler = ManagementFactory.getCompilationMXBean();
this.heapMemory = ManagementFactory.getMemoryMXBean();
List<MemoryPoolMXBean> memoryPools = ManagementFactory.getMemoryPoolMXBeans();
for (MemoryPoolMXBean memoryPool : memoryPools)
{
if ("PS Eden Space".equals(memoryPool.getName()) ||
"Par Eden Space".equals(memoryPool.getName()) ||
"G1 Eden".equals(memoryPool.getName()))
youngMemoryPool = memoryPool;
else if ("PS Survivor Space".equals(memoryPool.getName()) ||
"Par Survivor Space".equals(memoryPool.getName()) ||
"G1 Survivor".equals(memoryPool.getName()))
survivorMemoryPool = memoryPool;
else if ("PS Old Gen".equals(memoryPool.getName()) ||
"CMS Old Gen".equals(memoryPool.getName()) ||
"G1 Old Gen".equals(memoryPool.getName()))
oldMemoryPool = memoryPool;
}
hasMemoryPools = youngMemoryPool != null && survivorMemoryPool != null && oldMemoryPool != null;
List<GarbageCollectorMXBean> garbageCollectors = ManagementFactory.getGarbageCollectorMXBeans();
for (GarbageCollectorMXBean garbageCollector : garbageCollectors)
{
if ("PS Scavenge".equals(garbageCollector.getName()) ||
"ParNew".equals(garbageCollector.getName()) ||
"G1 Young Generation".equals(garbageCollector.getName()))
youngCollector = garbageCollector;
else if ("PS MarkSweep".equals(garbageCollector.getName()) ||
"ConcurrentMarkSweep".equals(garbageCollector.getName()) ||
"G1 Old Generation".equals(garbageCollector.getName()))
oldCollector = garbageCollector;
}
hasCollectors = youngCollector != null && oldCollector != null;
}
public void run()
{
if (!hasMemoryPools)
return;
long young = youngMemoryPool.getUsage().getUsed();
long survivor = survivorMemoryPool.getUsage().getUsed();
long old = oldMemoryPool.getUsage().getUsed();
if (!polling)
{
polling = true;
}
else
{
if (lastYoungUsed <= young)
{
totalYoungUsed += young - lastYoungUsed;
}
if (lastSurvivorUsed <= survivor)
{
totalSurvivorUsed += survivor - lastSurvivorUsed;
}
if (lastOldUsed <= old)
{
totalOldUsed += old - lastOldUsed;
}
else
{
// May need something more here, like "how much was collected"
}
}
lastYoungUsed = young;
lastSurvivorUsed = survivor;
lastOldUsed = old;
}
public boolean startStatistics()
{
// Support for multiple nodes requires to ignore start requests after the first
// but also requires that requests after the first wait until the initialization
// is completed (otherwise node #2 may start the run while the server is GC'ing)
synchronized (this)
{
if (starts.incrementAndGet() > 1)
return false;
System.gc();
System.err.println("\n========================================");
System.err.println("Statistics Started at " + new Date());
System.err.println("Operative System: " + operatingSystem.getName() + " " + operatingSystem.getVersion() + " " + operatingSystem.getArch());
System.err.println("JVM : " + System.getProperty("java.vm.vendor") + " " + System.getProperty("java.vm.name") + " runtime " + System.getProperty("java.vm.version") + " " + System.getProperty("java.runtime.version"));
System.err.println("Processors: " + operatingSystem.getAvailableProcessors());
if (operatingSystem instanceof com.sun.management.OperatingSystemMXBean)
{
com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean)operatingSystem;
long totalMemory = os.getTotalPhysicalMemorySize();
long freeMemory = os.getFreePhysicalMemorySize();
System.err.println("System Memory: " + percent(totalMemory - freeMemory, totalMemory) + "% used of " + gibiBytes(totalMemory) + " GiB");
}
else
{
System.err.println("System Memory: N/A");
}
MemoryUsage heapMemoryUsage = heapMemory.getHeapMemoryUsage();
System.err.println("Used Heap Size: " + mebiBytes(heapMemoryUsage.getUsed()) + " MiB");
System.err.println("Max Heap Size: " + mebiBytes(heapMemoryUsage.getMax()) + " MiB");
if (hasMemoryPools)
{
long youngGenerationHeap = heapMemoryUsage.getMax() - oldMemoryPool.getUsage().getMax();
System.err.println("Young Generation Heap Size: " + mebiBytes(youngGenerationHeap) + " MiB");
}
else
{
System.err.println("Young Generation Heap Size: N/A");
}
System.err.println("- - - - - - - - - - - - - - - - - - - - ");
scheduler = Executors.newSingleThreadScheduledExecutor();
polling = false;
memoryPoller = scheduler.scheduleWithFixedDelay(this, 0, 250, TimeUnit.MILLISECONDS);
lastYoungUsed = 0;
if (hasCollectors)
{
startYoungCollections = youngCollector.getCollectionCount();
startYoungCollectionsTime = youngCollector.getCollectionTime();
}
totalYoungUsed = 0;
lastSurvivorUsed = 0;
totalSurvivorUsed = 0;
lastOldUsed = 0;
if (hasCollectors)
{
startOldCollections = oldCollector.getCollectionCount();
startOldCollectionsTime = oldCollector.getCollectionTime();
}
totalOldUsed = 0;
startTime = System.nanoTime();
if (operatingSystem instanceof com.sun.management.OperatingSystemMXBean)
{
com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean)operatingSystem;
startProcessCPUTime = os.getProcessCpuTime();
}
startJITCTime = jitCompiler.getTotalCompilationTime();
return true;
}
}
public boolean stopStatistics()
{
synchronized (this)
{
if (starts.decrementAndGet() > 0)
return false;
memoryPoller.cancel(false);
scheduler.shutdown();
System.err.println("- - - - - - - - - - - - - - - - - - - - ");
System.err.println("Statistics Ended at " + new Date());
long elapsedTime = System.nanoTime() - startTime;
System.err.println("Elapsed time: " + TimeUnit.NANOSECONDS.toMillis(elapsedTime) + " ms");
long elapsedJITCTime = jitCompiler.getTotalCompilationTime() - startJITCTime;
System.err.println("\tTime in JIT compilation: " + elapsedJITCTime + " ms");
if (hasCollectors)
{
long elapsedYoungCollectionsTime = youngCollector.getCollectionTime() - startYoungCollectionsTime;
long youngCollections = youngCollector.getCollectionCount() - startYoungCollections;
System.err.println("\tTime in Young Generation GC: " + elapsedYoungCollectionsTime + " ms (" + youngCollections + " collections)");
long elapsedOldCollectionsTime = oldCollector.getCollectionTime() - startOldCollectionsTime;
long oldCollections = oldCollector.getCollectionCount() - startOldCollections;
System.err.println("\tTime in Old Generation GC: " + elapsedOldCollectionsTime + " ms (" + oldCollections + " collections)");
}
else
{
System.err.println("\tTime in GC: N/A");
}
if (hasMemoryPools)
{
System.err.println("Garbage Generated in Young Generation: " + mebiBytes(totalYoungUsed) + " MiB");
System.err.println("Garbage Generated in Survivor Generation: " + mebiBytes(totalSurvivorUsed) + " MiB");
System.err.println("Garbage Generated in Old Generation: " + mebiBytes(totalOldUsed) + " MiB");
}
else
{
System.err.println("Garbage Generated: N/A");
}
if (operatingSystem instanceof com.sun.management.OperatingSystemMXBean)
{
com.sun.management.OperatingSystemMXBean os = (com.sun.management.OperatingSystemMXBean)operatingSystem;
long elapsedProcessCPUTime = os.getProcessCpuTime() - startProcessCPUTime;
System.err.println("Average CPU Load: " + ((float)elapsedProcessCPUTime * 100 / elapsedTime) + "/" + (100 * operatingSystem.getAvailableProcessors()));
}
else
{
System.err.println("Average CPU Load: N/A");
}
System.err.println("----------------------------------------\n");
return true;
}
}
public float percent(long dividend, long divisor)
{
return (float)dividend * 100 / divisor;
}
public float mebiBytes(long bytes)
{
return (float)bytes / 1024 / 1024;
}
public float gibiBytes(long bytes)
{
return (float)bytes / 1024 / 1024 / 1024;
}
}

View File

@ -142,7 +142,7 @@ public class SchedulerTest
@Slow
public void testManySchedulesAndCancels() throws Exception
{
schedule(500,5000,2000,50);
schedule(500,3000,1800,50);
}
@Test