Browse Source

Add JLHTTP Postgres Fortunes benchmark (#3860)

amichair 7 years ago
parent
commit
9711b77823

+ 7 - 0
frameworks/Java/jlhttp/README.md

@@ -13,10 +13,13 @@ JLHTTP usually sides with the smaller size.
 
 * [JSON](src/main/java/benchmarks/Server.java)
 * [Plaintext](src/main/java/benchmarks/Server.java)
+* [Fortunes](src/main/java/benchmarks/Server.java)
 
 ## Important Libraries
 The tests were run with:
 * [Jackson](https://github.com/FasterXML/jackson)
+* [HikariCP](https://github.com/brettwooldridge/HikariCP)
+* [HTTL](https://httl.github.io/en/)
 
 ## Test URLs
 ### JSON
@@ -26,3 +29,7 @@ http://localhost:8080/json
 ### Plaintext
 
 http://localhost:8080/plaintext
+
+### Fortunes
+
+http://localhost:8080/fortunes

+ 18 - 0
frameworks/Java/jlhttp/benchmark_config.json

@@ -20,6 +20,24 @@
         "display_name": "JLHTTP",
         "notes": "",
         "versus": ""
+      },
+      "postgres": {
+        "fortune_url": "/fortunes",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Platform",
+        "database": "Postgres",
+        "framework": "None",
+        "language": "Java",
+        "flavor": "None",
+        "orm": "Raw",
+        "platform": "JLHTTP",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "JLHTTP-postgres",
+        "notes": "",
+        "versus": ""
       }
     }
   ]

+ 10 - 0
frameworks/Java/jlhttp/jlhttp-postgres.dockerfile

@@ -0,0 +1,10 @@
+FROM maven:3.5.3-jdk-10-slim as maven
+WORKDIR /jlhttp
+COPY pom.xml pom.xml
+COPY src src
+RUN mvn compile assembly:single -q
+
+FROM openjdk:10-jre-slim
+WORKDIR /jlhttp
+COPY --from=maven /jlhttp/target/jlhttp-1.0-jar-with-dependencies.jar app.jar
+CMD ["java", "-server", "-Xss256k", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-jar", "app.jar", "postgres"]

+ 24 - 0
frameworks/Java/jlhttp/pom.xml

@@ -18,6 +18,7 @@
             <artifactId>jlhttp</artifactId>
             <version>2.4</version>
         </dependency>
+
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
@@ -28,6 +29,29 @@
             <artifactId>jackson-module-afterburner</artifactId>
             <version>2.9.5</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>42.2.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.zaxxer</groupId>
+            <artifactId>HikariCP</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.httl</groupId>
+            <artifactId>httl</artifactId>
+            <version>1.0.11</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>1.7.25</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 25 - 0
frameworks/Java/jlhttp/src/main/java/benchmarks/Fortune.java

@@ -0,0 +1,25 @@
+package benchmarks;
+
+public class Fortune implements Comparable<Fortune> {
+
+    private final int id;
+    private final String message;
+
+    public Fortune(int id, String message) {
+        this.id = id;
+        this.message = message;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    @Override
+    public int compareTo(Fortune other) {
+        return message.compareTo(other.message);
+    }
+}

+ 80 - 2
frameworks/Java/jlhttp/src/main/java/benchmarks/Server.java

@@ -1,8 +1,21 @@
 package benchmarks;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.text.ParseException;
+import java.util.*;
 import java.util.concurrent.*;
+import javax.sql.DataSource;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import httl.Engine;
+import httl.Template;
 import net.freeutils.httpserver.HTTPServer;
 import net.freeutils.httpserver.HTTPServer.*;
 
@@ -17,6 +30,37 @@ public class Server {
         MAPPER.registerModule(new AfterburnerModule());
     }
 
+    private static List<Fortune> queryFortunes(DataSource ds) throws SQLException {
+        List<Fortune> fortunes = new ArrayList<>();
+        try (Connection conn = ds.getConnection();
+             PreparedStatement statement = conn.prepareStatement("SELECT id, message FROM fortune");
+             ResultSet resultSet = statement.executeQuery()) {
+            while (resultSet.next())
+                fortunes.add(new Fortune(resultSet.getInt(1), resultSet.getString(2)));
+        }
+        return fortunes;
+    }
+
+    private static DataSource createPostgresDataSource() throws ClassNotFoundException {
+        Class.forName("org.postgresql.Driver");
+        HikariConfig config = new HikariConfig();
+        config.setJdbcUrl("jdbc:postgresql://tfb-database:5432/hello_world");
+        config.setUsername("benchmarkdbuser");
+        config.setPassword("benchmarkdbpass");
+        config.setMaximumPoolSize(64);
+        return new HikariDataSource(config);
+    }
+
+    private static Template loadTemplate(String filename) throws IOException, ParseException {
+        Properties props = new Properties();
+        props.put("import.packages", "java.util," + Fortune.class.getPackage().getName());
+        props.put("input.encoding", "UTF-8");
+        props.put("output.encoding", "UTF-8");
+        props.put("precompiled", "false");
+        Engine engine = Engine.getEngine(props);
+        return engine.getTemplate(filename);
+    }
+
     private static ContextHandler createPlaintextHandler() {
         return (req, resp) -> {
             resp.getHeaders().add("Content-Type", "text/plain");
@@ -29,6 +73,7 @@ public class Server {
 
     private static ContextHandler createJSONHandler() {
         return (req, resp) -> {
+            // serialize message to JSON
             Message msg = new Message(HELLO_TEXT);
             byte[] bytes;
             try {
@@ -36,7 +81,7 @@ public class Server {
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
-
+            // send response
             resp.getHeaders().add("Content-Type", "application/json");
             resp.getHeaders().add("Content-Length", Integer.toString(bytes.length));
             resp.sendHeaders(200);
@@ -45,9 +90,38 @@ public class Server {
         };
     }
 
+    private static ContextHandler createFortunesHandler(DataSource ds) throws IOException, ParseException {
+        Template template = loadTemplate("/fortunes.template.httl");
+        return (req, resp) -> {
+            try {
+                // query db
+                List<Fortune> fortunes = queryFortunes(ds);
+                fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+                Collections.sort(fortunes);
+                // render template
+                Map<String, Object> context = new HashMap<>(1);
+                context.put("fortunes", fortunes);
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                template.render(context, out);
+                byte[] bytes = out.toByteArray();
+                // send response
+                resp.getHeaders().add("Content-Type", "text/html; charset=utf-8");
+                resp.getHeaders().add("Content-Length", Integer.toString(bytes.length));
+                resp.sendHeaders(200);
+                resp.getOutputStream().write(bytes);
+                return 0;
+            } catch (SQLException | ParseException e) {
+                throw new IOException(e);
+            }
+        };
+    }
+
     public static void main(String[] args) throws Exception {
         // parse arguments
-        int port = args.length > 0 ? Integer.parseInt(args[0]) : 8080;
+        String settings = args.length > 0 ? args[0] : "";
+        int port = args.length > 1 ? Integer.parseInt(args[1]) : 8080;
+        if (settings.contains("debug"))
+            System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "DEBUG");
         // create server
         HTTPServer server = new HTTPServer(port);
         server.setExecutor(new ThreadPoolExecutor(
@@ -56,6 +130,10 @@ public class Server {
         // add context handlers
         host.addContext("/plaintext", createPlaintextHandler());
         host.addContext("/json", createJSONHandler());
+        if (settings.contains("postgres")) {
+            DataSource ds = createPostgresDataSource();
+            host.addContext("/fortunes", createFortunesHandler(ds));
+        }
         // start server
         server.start();
     }

+ 13 - 0
frameworks/Java/jlhttp/src/main/resources/fortunes.template.httl

@@ -0,0 +1,13 @@
+<!--#set(List<Fortune> fortunes)-->
+<!DOCTYPE html>
+<html>
+<head><title>Fortunes</title></head>
+<body>
+<table>
+<tr><th>id</th><th>message</th></tr>
+<!-- #for(Fortune fortune : fortunes) -->
+<tr><td>${fortune.id}</td><td>${fortune.message}</td></tr>
+<!-- #end -->
+</table>
+</body>
+</html>