/*
* Copyright 2013-2015 EMC Corporation. 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.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* or in the "license" file accompanying this file. This file 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 com.emc.ecs.sync.util;
import com.emc.ecs.sync.EcsSync;
import com.emc.ecs.sync.config.SyncConfig;
import com.emc.ecs.sync.config.SyncOptions;
import com.emc.ecs.sync.config.annotation.FilterConfig;
import com.emc.ecs.sync.config.storage.TestConfig;
import com.emc.ecs.sync.filter.AbstractFilter;
import com.emc.ecs.sync.model.ObjectContext;
import com.emc.ecs.sync.model.SyncObject;
import org.junit.Test;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicLong;
public class TimingUtilTest {
// NOTE: timing window requires manual verification of the log output
@Test
public void testTimings() {
int threadCount = Runtime.getRuntime().availableProcessors() * 4; // 4 threads per core for stress
int window = threadCount * 100; // should dump stats every 100 "objects" per thread
int total = window * 5; // ~500 root objects per thread total
TestConfig testConfig = new TestConfig();
testConfig.setObjectCount(total);
testConfig.setMaxSize(1024);
testConfig.setReadData(false);
testConfig.setDiscardData(false);
NoOpConfig noOpConfig = new NoOpConfig();
SyncOptions options = new SyncOptions().withTimingsEnabled(true).withTimingWindow(window).withThreadCount(threadCount);
SyncConfig syncConfig = new SyncConfig().withSource(testConfig).withTarget(testConfig)
.withFilters(Collections.singletonList(noOpConfig)).withOptions(options);
EcsSync sync = new EcsSync();
sync.setSyncConfig(syncConfig);
sync.run();
System.out.println("---Timing enabled---");
System.out.println("Per-thread overhead is " + (noOpConfig.getOverhead() / threadCount / 1000000) + "ms over 500 calls");
System.out.println("Per-call overhead is " + ((noOpConfig.getOverhead()) / (total) / 1000) + "µs");
// now disable timings
noOpConfig = new NoOpConfig();
syncConfig.setFilters(Collections.singletonList(noOpConfig));
options.setTimingsEnabled(false);
sync.run();
System.out.println("---Timing disabled---");
System.out.println("Per-thread overhead is " + (noOpConfig.getOverhead() / threadCount / 1000000) + "ms over 500 calls");
System.out.println("Per-call overhead is " + ((noOpConfig.getOverhead()) / (total) / 1000) + "µs");
}
public static class NoOpFilter extends AbstractFilter<NoOpConfig> {
@Override
public void filter(ObjectContext objectContext) {
long start = System.nanoTime();
time(new Function<Void>() {
@Override
public Void call() {
return null;
}
}, "No-op");
long overhead = System.nanoTime() - start;
config.addOverhead(overhead);
getNext().filter(objectContext);
}
@Override
public SyncObject reverseFilter(ObjectContext objectContext) {
throw new UnsupportedOperationException();
}
}
@FilterConfig(cliName = "no-op")
public static class NoOpConfig {
private AtomicLong overhead = new AtomicLong();
public long getOverhead() {
return overhead.longValue();
}
private void addOverhead(long ns) {
overhead.addAndGet(ns);
}
}
}