Skip to content

Commit 74ccaf3

Browse files
AnEmortalKidcchesser
authored andcommitted
Add Gatling Simulation (#10)
1 parent 2860005 commit 74ccaf3

25 files changed

Lines changed: 1277 additions & 135 deletions

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,9 @@ pom.xml.versionsBackup
2828
# Eclipse Project files
2929
.metadata
3030
.recommenders
31+
32+
# Intellij
33+
*.iml
34+
35+
# dumps directory
36+
dumps/

java-perf-workshop-server/src/main/java/cchesser/javaperf/workshop/WorkshopApplication.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package cchesser.javaperf.workshop;
22

33
import com.fasterxml.jackson.databind.SerializationFeature;
4-
import cchesser.javaperf.workshop.health.RemoveServiceHealthCheck;
4+
import cchesser.javaperf.workshop.health.RemoteServiceHealthCheck;
55
import cchesser.javaperf.workshop.resources.WorkshopResource;
66
import io.dropwizard.Application;
77
import io.dropwizard.setup.Bootstrap;
@@ -26,7 +26,7 @@ public void initialize(Bootstrap<WorkshopConfiguration> bootstrap) {
2626
public void run(WorkshopConfiguration configuration, Environment environment) {
2727
final WorkshopResource resource = new WorkshopResource(configuration);
2828
environment.jersey().register(resource);
29-
environment.healthChecks().register("remoteService", new RemoveServiceHealthCheck(configuration));
29+
environment.healthChecks().register("remoteService", new RemoteServiceHealthCheck(configuration));
3030
environment.getObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
3131
}
3232
}

java-perf-workshop-server/src/main/java/cchesser/javaperf/workshop/WorkshopConfiguration.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package cchesser.javaperf.workshop;
22

3-
import org.hibernate.validator.constraints.NotEmpty;
4-
3+
import cchesser.javaperf.workshop.cache.CacheConfiguration;
54
import com.fasterxml.jackson.annotation.JsonProperty;
65
import io.dropwizard.Configuration;
6+
import org.hibernate.validator.constraints.NotEmpty;
77

88
public class WorkshopConfiguration extends Configuration {
99

1010
@NotEmpty
1111
private String conferenceServiceHost = "localhost:9090";
1212

13+
@JsonProperty
14+
private CacheConfiguration historicalCache = new CacheConfiguration();
15+
1316
@JsonProperty
1417
public String getConferenceServiceHost() {
1518
return conferenceServiceHost;
@@ -20,4 +23,13 @@ public void setSonferenceServiceHost(String host) {
2023
this.conferenceServiceHost = host;
2124
}
2225

26+
@JsonProperty
27+
public CacheConfiguration getHistoricalCache() {
28+
return historicalCache;
29+
}
30+
31+
@JsonProperty
32+
public void setHistoricalCache(CacheConfiguration historicalCache) {
33+
this.historicalCache = historicalCache;
34+
}
2335
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package cchesser.javaperf.workshop.cache;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
5+
import javax.validation.constraints.Max;
6+
import javax.validation.constraints.Min;
7+
8+
public class CacheConfiguration {
9+
10+
@Min(32)
11+
@Max(65536)
12+
@JsonProperty
13+
private int cacheLimit = 10000;
14+
15+
@Min(1024)
16+
@Max(65536)
17+
@JsonProperty
18+
private int discardLimit = 65536;
19+
20+
@JsonProperty
21+
public int getCacheLimit() {
22+
return cacheLimit;
23+
}
24+
25+
@JsonProperty
26+
public void setCacheLimit(int cacheLimit) {
27+
this.cacheLimit = cacheLimit;
28+
}
29+
30+
@JsonProperty
31+
public int getDiscardLimit() {
32+
return discardLimit;
33+
}
34+
35+
@JsonProperty
36+
public void setDiscardLimit(int discardLimit) {
37+
this.discardLimit = discardLimit;
38+
}
39+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package cchesser.javaperf.workshop.cache;
2+
3+
import java.util.*;
4+
import java.util.Map.Entry;
5+
import java.util.stream.Collectors;
6+
7+
/**
8+
* An LFU Cache with history tracking, modified
9+
* from Stack Overflow: https://stackoverflow.com/a/23668899 (used as a basis).
10+
*
11+
* @author JMonterrubio
12+
*/
13+
public class HistoricalCache<K, V> {
14+
15+
private Map<K, CacheEntry<V>> innerCache = new LinkedHashMap<>();
16+
private int cacheLimit;
17+
18+
private Deque<String> historyLog = new LinkedList<>();
19+
private int historyLimit;
20+
21+
public HistoricalCache(int cacheLimit, int historyLimit) {
22+
this.cacheLimit = cacheLimit;
23+
this.historyLimit = historyLimit;
24+
}
25+
26+
/**
27+
* Stores the given key value pair in the cache
28+
*
29+
* @param key the unique identifier associated with the given value
30+
* @param value the value mapped to the given key
31+
*/
32+
public void store(K key, V value) {
33+
if (isFull()) {
34+
K keyToRemove = getLFUKey();
35+
HistoricalCache<K, V>.CacheEntry<V> removedEntry = innerCache.remove(keyToRemove);
36+
37+
if (historyLog.size() >= historyLimit) {
38+
historyLog.removeLast();
39+
}
40+
historyLog.add(removedEntry.toString());
41+
}
42+
43+
CacheEntry<V> newEntry = new CacheEntry<V>();
44+
newEntry.data = value;
45+
newEntry.frequency = 0;
46+
47+
innerCache.put(key, newEntry);
48+
}
49+
50+
/**
51+
* Retrieves the value associated with the given key from the cache.
52+
*
53+
* @param key the key that maps to that value
54+
* @return the value mapped to the key
55+
* @throws NullPointerException if the key doesn't exist
56+
*/
57+
public V fetch(K key) {
58+
if (innerCache.containsKey(key)) {
59+
innerCache.get(key).frequency++;
60+
}
61+
62+
return innerCache.get(key).data;
63+
}
64+
65+
/**
66+
* Indicates whether a key exists in the cache or not
67+
*
68+
* @param key the key to check
69+
* @return <code>true</code> if the key is in the cache, <code>false</code>
70+
* otherwise.
71+
*/
72+
public boolean exists(K key) {
73+
return innerCache.containsKey(key);
74+
}
75+
76+
private boolean isFull() {
77+
return innerCache.size() == cacheLimit;
78+
}
79+
80+
private K getLFUKey() {
81+
Optional<Entry<K, HistoricalCache<K, V>.CacheEntry<V>>> lfuEntry = innerCache.entrySet().stream()
82+
.collect(Collectors.minBy(Comparator.comparingInt(entry -> entry.getValue().frequency)));
83+
84+
return lfuEntry.get().getKey();
85+
}
86+
87+
private class CacheEntry<T> {
88+
private T data;
89+
private int frequency;
90+
}
91+
92+
}

java-perf-workshop-server/src/main/java/cchesser/javaperf/workshop/data/AsciiArtConvertor.java renamed to java-perf-workshop-server/src/main/java/cchesser/javaperf/workshop/data/AsciiArtConverter.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
package cchesser.javaperf.workshop.data;
22

3-
import java.awt.Font;
4-
import java.awt.Graphics;
5-
import java.awt.Graphics2D;
6-
import java.awt.RenderingHints;
3+
import javax.imageio.ImageIO;
4+
import java.awt.*;
75
import java.awt.image.BufferedImage;
86
import java.io.File;
97
import java.io.IOException;
10-
11-
import javax.imageio.ImageIO;
8+
import java.nio.file.Files;
9+
import java.nio.file.Path;
1210

1311
/**
1412
* This is a trival example of doing something unnecessary in the service and using up some heap.
1513
* Example was obtained from StackOverflow: http://stackoverflow.com/questions/7098972/ascii-art-java
1614
*/
17-
class AsciiArtConvertor {
15+
class AsciiArtConverter {
1816

1917
static String convert(String text) {
2018

@@ -28,7 +26,11 @@ static String convert(String text) {
2826

2927
StringBuilder rendered = new StringBuilder();
3028
try {
31-
ImageIO.write(image, "png", new File("text.png"));
29+
Path tempFilePath = Files.createTempFile("text", "png");
30+
File tempFile = tempFilePath.toFile();
31+
tempFile.deleteOnExit();
32+
33+
ImageIO.write(image, "png", tempFile);
3234

3335
for (int y = 0; y < 32; y++) {
3436
StringBuilder sb = new StringBuilder();

0 commit comments

Comments
 (0)