View Javadoc

1   package com.atlassian.vcache.internal.harness;
2   
3   import com.atlassian.cache.CacheFactory;
4   import com.atlassian.cache.memory.MemoryCacheManager;
5   import com.atlassian.marshalling.jdk.JavaSerializationMarshalling;
6   import com.atlassian.vcache.ChangeRate;
7   import com.atlassian.vcache.DirectExternalCache;
8   import com.atlassian.vcache.ExternalCacheSettingsBuilder;
9   import com.atlassian.vcache.JvmCache;
10  import com.atlassian.vcache.JvmCacheSettingsBuilder;
11  import com.atlassian.vcache.RequestCache;
12  import com.atlassian.vcache.internal.core.DefaultVCacheCreationHandler;
13  import com.atlassian.vcache.internal.core.WorkContextRequestContextSupplier;
14  import com.atlassian.vcache.internal.core.metrics.DefaultMetricsCollector;
15  import com.atlassian.vcache.internal.core.metrics.MetricsCollector;
16  import com.atlassian.vcache.internal.core.metrics.NoopMetricsCollector;
17  import com.atlassian.vcache.internal.core.service.AbstractVCacheService;
18  import com.atlassian.vcache.internal.legacy.LegacyServiceSettings;
19  import com.atlassian.vcache.internal.legacy.LegacyServiceSettingsBuilder;
20  import com.atlassian.vcache.internal.legacy.LegacyVCacheService;
21  import com.atlassian.vcache.internal.memcached.MemcachedVCacheService;
22  import com.atlassian.vcache.internal.memcached.MemcachedVCacheServiceSettings;
23  import com.atlassian.vcache.internal.memcached.MemcachedVCacheServiceSettingsBuilder;
24  import com.atlassian.vcache.internal.test.EmptyVCacheSettingsDefaultsProvider;
25  import com.atlassian.vcache.internal.test.ThreadLocalRequestContextSupplier;
26  import com.codahale.metrics.MetricRegistry;
27  import com.codahale.metrics.Snapshot;
28  import net.spy.memcached.AddrUtil;
29  import net.spy.memcached.BinaryConnectionFactory;
30  import net.spy.memcached.MemcachedClient;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  
34  import java.io.IOException;
35  import java.text.DecimalFormat;
36  import java.time.Duration;
37  import java.util.Arrays;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Map;
41  import java.util.concurrent.TimeUnit;
42  import java.util.stream.Collectors;
43  import java.util.stream.IntStream;
44  
45  import static java.util.Objects.requireNonNull;
46  import static java.util.stream.Collectors.joining;
47  
48  /**
49   * Runs some stressy thing.
50   */
51  public class StressHarness {
52      private static final Logger log = LoggerFactory.getLogger(StressHarness.class);
53  
54      private static final ThreadLocalRequestContextSupplier requestContextSupplier = ThreadLocalRequestContextSupplier.strictSupplier();
55      private static final WorkContextRequestContextSupplier workContextContextSupplier = new WorkContextRequestContextSupplier(() -> "tenant-123");
56      private static final CacheFactory cacheFactory = new MemoryCacheManager();
57  
58      private final MetricRegistry metricRegistry = new MetricRegistry();
59      private final AbstractVCacheService service;
60      private OverallConfig overallConfig;
61  
62      public StressHarness(AbstractVCacheService service) {
63          this.service = requireNonNull(service);
64      }
65  
66      public static void main(String[] args) throws InterruptedException, IOException {
67          log.info("And away");
68  
69          final boolean useLegacy = false;
70          final LegacyServiceSettings settings = new LegacyServiceSettingsBuilder().build();
71          final MetricsCollector metricsCollector = new DefaultMetricsCollector(requestContextSupplier);
72  
73          final AbstractVCacheService legacySvc = new LegacyVCacheService(
74                  "harness",
75                  requestContextSupplier,
76                  workContextContextSupplier,
77                  new EmptyVCacheSettingsDefaultsProvider(),
78                  new DefaultVCacheCreationHandler(
79                          10_000, Duration.ofHours(2), 10_000, ChangeRate.HIGH_CHANGE, ChangeRate.HIGH_CHANGE),
80                  metricsCollector,
81                  () -> cacheFactory,
82                  settings,
83                  context -> {
84                  });
85  
86          final MemcachedClient memcachedClient = new MemcachedClient(
87                  new BinaryConnectionFactory(),
88                  AddrUtil.getAddresses("192.168.99.100:32768"));
89  
90          final MemcachedVCacheServiceSettings serviceSettings = new MemcachedVCacheServiceSettingsBuilder()
91                  .productIdentifier("" + System.nanoTime())
92                  .clientSupplier(() -> memcachedClient)
93                  .threadLocalContextSupplier(requestContextSupplier)
94                  .defaultsProvider(new EmptyVCacheSettingsDefaultsProvider())
95                  .creationHandler(new DefaultVCacheCreationHandler(
96                          10_000, Duration.ofHours(2), 10_000, ChangeRate.HIGH_CHANGE, ChangeRate.HIGH_CHANGE))
97                  .metricsCollector(metricsCollector)
98                  .begunTransactionalActivityHandler(context -> {
99                  })
100                 .build();
101         final AbstractVCacheService memcachedSvc = new MemcachedVCacheService(serviceSettings);
102 
103         final StressHarness harness = new StressHarness(useLegacy ? legacySvc : memcachedSvc);
104 //        final StressHarness harness = new StressHarness(memcachedSvc);
105         harness.setup();
106         harness.perform();
107 
108         System.out.printf(
109                 "\n\nFinished: serializeHack is '%s', collecting metrics is '%s', use legacy is '%s'\n",
110                 settings.isSerializationHack(), !(metricsCollector instanceof NoopMetricsCollector), useLegacy);
111     }
112 
113     private void perform() throws InterruptedException {
114         // Spin up threads
115         // Wait time
116         // Set time to stop
117         final List<Worker> workers = IntStream.rangeClosed(1, 10)
118                 .mapToObj(i -> new Worker(i, overallConfig))
119                 .collect(Collectors.toList());
120 
121         workers.forEach(w -> new Thread(w).start());
122         Thread.sleep(60_000);
123         workers.forEach(Worker::stopIt);
124         Thread.sleep(500); // yeah yeah, I should wait for the threads!
125 
126         final List<String> columns = Arrays.asList("Timer", "Count", "Min", "Max", "Median", "95th", "99th");
127         System.out.println(columns.stream().collect(joining("\t")));
128         metricRegistry.getTimers().entrySet().forEach(timerEntry -> {
129             final Snapshot snapshot = timerEntry.getValue().getSnapshot();
130             final List<String> parts = Arrays.asList(
131                     timerEntry.getKey(),
132                     Long.toString(timerEntry.getValue().getCount()),
133                     toMillisString(snapshot.getMin()),
134                     toMillisString(snapshot.getMax()),
135                     toMillisString(snapshot.getMedian()),
136                     toMillisString(snapshot.get95thPercentile()),
137                     toMillisString(snapshot.get99thPercentile()));
138 
139             System.out.println(parts.stream().collect(joining("\t")));
140         });
141     }
142 
143     private String toMillisString(double nanoseconds) {
144         return new DecimalFormat("#0.0#####").format(
145                 nanoseconds / TimeUnit.NANOSECONDS.convert(1, TimeUnit.MILLISECONDS));
146     }
147 
148     private void setup() {
149         final Map<String, CacheConfig> cacheTestConfigMap = new HashMap<>();
150         overallConfig = new OverallConfig(metricRegistry, service, requestContextSupplier, cacheTestConfigMap, 5, 200);
151 
152         // JvmCache
153         final JvmCache<String, String> jvmCache1 = service.getJvmCache("jvmCache1", new JvmCacheSettingsBuilder().build());
154         final CacheConfig jvmCache1Config = new CacheConfig(jvmCache1, 10, 10, 10, 20, 90);
155 //        cacheTestConfigMap.put(jvmCache1.getName(), jvmCache1Config);
156 
157         // Request Cache
158         final RequestCache<String, String> requestCache1 = service.getRequestCache("requestCache1");
159         final CacheConfig requestCache1Config = new CacheConfig(requestCache1, 20, 20, 20, 40, 90);
160 //        cacheTestConfigMap.put(requestCache1.getName(), requestCache1Config);
161 
162         // DirectEX
163         final DirectExternalCache<String> directExternalCache = service.getDirectExternalCache(
164                 "directEC1",
165                 JavaSerializationMarshalling.pair(String.class),
166                 new ExternalCacheSettingsBuilder().build());
167         final CacheConfig directExternalCacheConfig = new CacheConfig(directExternalCache, 20, 20, 20, 40, 90);
168         cacheTestConfigMap.put(directExternalCache.getName(), directExternalCacheConfig);
169     }
170 }