|
| 1 | +package org.ldbcouncil.finbench.impls.dummy; |
| 2 | + |
| 3 | +import com.sun.management.OperatingSystemMXBean; |
| 4 | +import java.lang.management.ManagementFactory; |
| 5 | +import java.util.concurrent.TimeUnit; |
| 6 | +import org.ldbcouncil.finbench.driver.DbException; |
| 7 | +import org.ldbcouncil.finbench.driver.optimization.OptimizationSupport; |
| 8 | +import org.ldbcouncil.finbench.driver.optimization.OperationProfileSpec; |
| 9 | +import org.ldbcouncil.finbench.driver.optimization.ResourceSnapshot; |
| 10 | +import org.ldbcouncil.finbench.driver.optimization.SyntheticExecutionResult; |
| 11 | +import org.ldbcouncil.finbench.driver.optimization.SyntheticLoadSpec; |
| 12 | + |
| 13 | +/** |
| 14 | + * Test implementation that models CPU, memory and duration inside the driver JVM. |
| 15 | + */ |
| 16 | +public class DummyOptimizationSupport implements OptimizationSupport { |
| 17 | + private static final long MAX_TEST_ALLOCATION_BYTES = 16L * 1024 * 1024; |
| 18 | + |
| 19 | + @Override |
| 20 | + public ResourceSnapshot sampleResources() { |
| 21 | + Runtime runtime = Runtime.getRuntime(); |
| 22 | + long usedMemory = runtime.totalMemory() - runtime.freeMemory(); |
| 23 | + double cpuCores = 0; |
| 24 | + java.lang.management.OperatingSystemMXBean bean = ManagementFactory.getOperatingSystemMXBean(); |
| 25 | + if (bean instanceof OperatingSystemMXBean) { |
| 26 | + OperatingSystemMXBean osBean = (OperatingSystemMXBean) bean; |
| 27 | + double processLoad = osBean.getProcessCpuLoad(); |
| 28 | + if (processLoad >= 0) { |
| 29 | + cpuCores = processLoad * osBean.getAvailableProcessors(); |
| 30 | + } |
| 31 | + } |
| 32 | + return new ResourceSnapshot(System.currentTimeMillis(), cpuCores, usedMemory); |
| 33 | + } |
| 34 | + |
| 35 | + @Override |
| 36 | + public SyntheticExecutionResult executeRepresentativeOperation(OperationProfileSpec spec) throws DbException { |
| 37 | + long durationMillis = Math.max(1, spec.expectedDurationMillis()); |
| 38 | + long memoryBytes = 1024L * Math.max(1, spec.operationName().length()); |
| 39 | + return executeSyntheticLoad(new SyntheticLoadSpec(spec.operationName(), 0.25, memoryBytes, durationMillis)); |
| 40 | + } |
| 41 | + |
| 42 | + @Override |
| 43 | + public SyntheticExecutionResult executeSyntheticLoad(SyntheticLoadSpec spec) throws DbException { |
| 44 | + if (spec.targetDurationMillis() < 0 || spec.targetMemoryBytes() < 0 || spec.targetCpuCores() < 0) { |
| 45 | + throw new DbException("Synthetic load values must be non-negative"); |
| 46 | + } |
| 47 | + |
| 48 | + int allocationSize = (int) Math.min(spec.targetMemoryBytes(), MAX_TEST_ALLOCATION_BYTES); |
| 49 | + byte[] allocation = allocationSize == 0 ? null : new byte[allocationSize]; |
| 50 | + if (allocation != null) { |
| 51 | + for (int offset = 0; offset < allocation.length; offset += 4096) { |
| 52 | + allocation[offset] = 1; |
| 53 | + } |
| 54 | + } |
| 55 | + |
| 56 | + long start = System.nanoTime(); |
| 57 | + long deadline = start + TimeUnit.MILLISECONDS.toNanos(spec.targetDurationMillis()); |
| 58 | + if (spec.targetCpuCores() > 0) { |
| 59 | + long value = 1; |
| 60 | + while (System.nanoTime() < deadline) { |
| 61 | + value = value * 31 + 17; |
| 62 | + } |
| 63 | + if (allocation != null) { |
| 64 | + allocation[0] = (byte) value; |
| 65 | + } |
| 66 | + } else { |
| 67 | + sleepUntil(deadline); |
| 68 | + } |
| 69 | + long durationMillis = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); |
| 70 | + return new SyntheticExecutionResult(durationMillis, allocationSize); |
| 71 | + } |
| 72 | + |
| 73 | + private static void sleepUntil(long deadline) throws DbException { |
| 74 | + while (System.nanoTime() < deadline) { |
| 75 | + long remainingNanos = deadline - System.nanoTime(); |
| 76 | + try { |
| 77 | + TimeUnit.NANOSECONDS.sleep(remainingNanos); |
| 78 | + } catch (InterruptedException e) { |
| 79 | + Thread.currentThread().interrupt(); |
| 80 | + throw new DbException("Synthetic load interrupted", e); |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | +} |
0 commit comments