diff --git a/performance_benchmark/ReadMe.txt b/performance_benchmark/ReadMe.txt new file mode 100644 index 0000000..fc5d0ce --- /dev/null +++ b/performance_benchmark/ReadMe.txt @@ -0,0 +1,84 @@ +Best way to performance test it is with +Apache Benchmark. ---- https://httpd.apache.org/docs/2.4/programs/ab.html + + +EG ab -n 1000 -c 99 http://localhost:4567/task/501 +would send 1000 requests, with a concurrency of 99 to the URL. + +If you want to test PUT for example + +With a file called data containing : +{"description":"whatever description","resolved":false, "id":1} + +Perf test::: + +ab -n 1000 -c 2 -k -u data -m PUT -T "application/json" http://localhost:4567/task/1234 + + +Would make 1000 requests at a concurrency level of 2 with keep alive requests PUT'ing the data to the specific task. +This would be a BAD test as you will have issues with optimistic locking on that resource. +the code does a get in one session and a write in another session - allowing the other request to update in the background + + + +an example output for the GET request + +Limited to 99 concurrent requests as the DB connection pool is only set to 100. + + +ab -n 1000 -c 99 http://localhost:4567/task/501 +This is ApacheBench, Version 2.3 <$Revision: 1843412 $> +Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ +Licensed to The Apache Software Foundation, http://www.apache.org/ + +Benchmarking localhost (be patient) +Completed 100 requests +Completed 200 requests +Completed 300 requests +Completed 400 requests +Completed 500 requests +Completed 600 requests +Completed 700 requests +Completed 800 requests +Completed 900 requests +Completed 1000 requests +Finished 1000 requests + + +Server Software: Jetty(9.4.z-SNAPSHOT) +Server Hostname: localhost +Server Port: 4567 + +Document Path: /task/501 +Document Length: 4 bytes + +Concurrency Level: 99 +Time taken for tests: 0.153 seconds +Complete requests: 1000 +Failed requests: 0 +Non-2xx responses: 1000 +Total transferred: 137000 bytes +HTML transferred: 4000 bytes +Requests per second: 6556.60 [#/sec] (mean) +Time per request: 15.099 [ms] (mean) +Time per request: 0.153 [ms] (mean, across all concurrent requests) +Transfer rate: 877.20 [Kbytes/sec] received + +Connection Times (ms) + min mean[+/-sd] median max +Connect: 0 5 2.3 4 13 +Processing: 2 9 6.8 7 33 +Waiting: 1 7 7.0 5 32 +Total: 4 14 7.8 11 41 + +Percentage of the requests served within a certain time (ms) + 50% 11 + 66% 14 + 75% 16 + 80% 18 + 90% 25 + 95% 33 + 98% 38 + 99% 39 + 100% 41 (longest request) + diff --git a/performance_benchmark/data b/performance_benchmark/data new file mode 100644 index 0000000..e96cf5f --- /dev/null +++ b/performance_benchmark/data @@ -0,0 +1 @@ +{"description":"whatever description","resolved":false, "id":1} diff --git a/performance_benchmark/data_no_id b/performance_benchmark/data_no_id new file mode 100644 index 0000000..57a1e1d --- /dev/null +++ b/performance_benchmark/data_no_id @@ -0,0 +1 @@ +{"description":"whatever description","resolved":false} diff --git a/performance_benchmark/run_all.sh b/performance_benchmark/run_all.sh index def04af..6e79094 100755 --- a/performance_benchmark/run_all.sh +++ b/performance_benchmark/run_all.sh @@ -2,6 +2,16 @@ set -o errexit +if [ "x$1" = "x" ] ; then + echo "Parameters : + +eg +http://localhost:4567/ 10 100 1 +would make 10 sets of 100 requests with a 1 sec pause between sets +" +exit +fi + run() { # input parameters local base_url=$1 diff --git a/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/App.java b/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/App.java index 50b1e74..b48d9d3 100644 --- a/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/App.java +++ b/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/App.java @@ -7,26 +7,31 @@ import static spark.Spark.delete; import me.vitor.taskapp_sparkjava.controller.TaskController; +import me.vitor.taskapp_sparkjava.model.TaskRepositoryHibernate; +import me.vitor.taskapp_sparkjava.service.TaskService; import me.vitor.taskapp_sparkjava.transformer.JsonTransformer; public class App { - private static final String PATH_TASK = "/task"; - private static final String PATH_ID = ":id"; - private static final String PATH_TASK_WITH_ID = PATH_TASK + "/" + PATH_ID; - - public static void main(String[] args) { - App app = new App(); - app.setup(); - } - - private void setup() { - get(PATH_TASK, TaskController::getTasks, new JsonTransformer()); - get(PATH_TASK_WITH_ID, TaskController::getTask, new JsonTransformer()); - post(PATH_TASK, TaskController::postTask); - put(PATH_TASK_WITH_ID, TaskController::putTask); - patch(PATH_TASK_WITH_ID, TaskController::patchTask); - delete(PATH_TASK_WITH_ID, TaskController::deleteTask); - } + private static final String PATH_TASK = "/task"; + private static final String PATH_ID = ":id"; + private static final String PATH_TASK_WITH_ID = PATH_TASK + "/" + PATH_ID; + + public static void main(String[] args) { + App app = new App(); + app.setup(); + } + + private void setup() { + + TaskController controller = new TaskController(new TaskService(new TaskRepositoryHibernate())); + + get(PATH_TASK, controller::getTasks, new JsonTransformer()); + get(PATH_TASK_WITH_ID, controller::getTask, new JsonTransformer()); + post(PATH_TASK, controller::postTask); + put(PATH_TASK_WITH_ID, controller::putTask); + patch(PATH_TASK_WITH_ID, controller::patchTask); + delete(PATH_TASK_WITH_ID, controller::deleteTask); + } } diff --git a/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/controller/TaskController.java b/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/controller/TaskController.java index f88add1..38055db 100644 --- a/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/controller/TaskController.java +++ b/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/controller/TaskController.java @@ -2,7 +2,6 @@ import java.util.List; import me.vitor.taskapp_sparkjava.model.Task; -import me.vitor.taskapp_sparkjava.model.TaskRepositoryHibernate; import me.vitor.taskapp_sparkjava.service.TaskService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,84 +10,83 @@ public class TaskController { - private static final String H_LOCATION = "Location"; - private static final Logger log = LoggerFactory.getLogger(TaskController.class); - - public static List getTasks(Request request, Response response) { - TaskService taskService = new TaskService(new TaskRepositoryHibernate()); - List taskList = taskService.findAll(); - return taskList; - } - - public static String postTask(Request request, Response response) { - TaskService taskService = new TaskService(new TaskRepositoryHibernate()); - Task task = ControllerUtils.getTaskFromRequestBody(request); - Long taskId = taskService.insert(task); - response.header(H_LOCATION, ControllerUtils.generateUri(request, taskId)); - response.status(201); - - // can't return null here otherwise will get a 404 - // https://github.com/perwendel/spark/issues/620 - return ""; - } - - public static Task getTask(Request request, Response response) { - Long id = Long.parseLong(request.params("id")); - TaskService taskService = new TaskService(new TaskRepositoryHibernate()); - Task task = taskService.findById(id); - - if (task == null) { - response.status(404); - return null; + private static final String H_LOCATION = "Location"; + private final TaskService taskService; + private static final Logger log = LoggerFactory.getLogger(TaskController.class); + + public TaskController(TaskService taskService) { + this.taskService = taskService; + } + + public List getTasks(Request request, Response response) { + List taskList = taskService.findAll(); + return taskList; } - return task; - } + public String postTask(Request request, Response response) { + Task task = ControllerUtils.getTaskFromRequestBody(request); + Long taskId = taskService.insert(task); + response.header(H_LOCATION, ControllerUtils.generateUri(request, taskId)); + response.status(201); - public static String putTask(Request request, Response response) { - String paramId = request.params("id"); - Long id = Long.parseLong(paramId); + // can't return null here otherwise will get a 404 + // https://github.com/perwendel/spark/issues/620 + return ""; + } + + public Task getTask(Request request, Response response) { + Long id = Long.parseLong(request.params("id")); + Task task = taskService.findById(id); - Task task = ControllerUtils.getTaskFromRequestBody(request); - TaskService taskService = new TaskService(new TaskRepositoryHibernate()); - Long putId = taskService.put(task, id).getId(); + if (task == null) { + response.status(404); + return null; + } - response.header(H_LOCATION, ControllerUtils.generateUri(request, putId)); - response.status(204); - return ""; - } + return task; + } - public static String patchTask(Request request, Response response) { - String paramId = request.params("id"); - Long id = Long.parseLong(paramId); - TaskService taskService = new TaskService(new TaskRepositoryHibernate()); + public String putTask(Request request, Response response) { + String paramId = request.params("id"); + Long id = Long.parseLong(paramId); - boolean taskExists = taskService.taskExists(id); + Task task = ControllerUtils.getTaskFromRequestBody(request); + Long putId = taskService.put(task, id).getId(); - if (!taskExists) { - response.status(404); - return "Not found"; + response.header(H_LOCATION, ControllerUtils.generateUri(request, putId)); + response.status(204); + return ""; } - Task task = ControllerUtils.getTaskFromRequestBody(request); - taskService.patch(task, id); - response.status(204); - return ""; - } - - public static String deleteTask(Request request, Response response) { - String paramId = request.params("id"); - Long id = Long.parseLong(paramId); - TaskService taskService = new TaskService(new TaskRepositoryHibernate()); - boolean taskExists = taskService.taskExists(id); - - if (!taskExists) { - response.status(404); - return "Not found"; + public String patchTask(Request request, Response response) { + String paramId = request.params("id"); + Long id = Long.parseLong(paramId); + + boolean taskExists = taskService.taskExists(id); + + if (!taskExists) { + response.status(404); + return "Not found"; + } + + Task task = ControllerUtils.getTaskFromRequestBody(request); + taskService.patch(task, id); + response.status(204); + return ""; } - taskService.delete(id); - return ""; - } + public String deleteTask(Request request, Response response) { + String paramId = request.params("id"); + Long id = Long.parseLong(paramId); + boolean taskExists = taskService.taskExists(id); + + if (!taskExists) { + response.status(404); + return "Not found"; + } + + taskService.delete(id); + return ""; + } } diff --git a/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/model/TaskRepositoryHibernate.java b/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/model/TaskRepositoryHibernate.java index 1acee9e..69b405b 100644 --- a/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/model/TaskRepositoryHibernate.java +++ b/sparkjava/src/main/java/me/vitor/taskapp_sparkjava/model/TaskRepositoryHibernate.java @@ -8,49 +8,51 @@ public class TaskRepositoryHibernate implements TaskRepository { - private static SessionFactory factory = new Configuration().configure().buildSessionFactory(); - - @Override - public Task findBy(Long id) { - Session session = factory.openSession(); - Query query = session.createQuery("FROM Task where id = :id"); - query.setParameter("id", id); - List tasks = query.list(); - session.close(); - - if (tasks == null || tasks.isEmpty()) { - return null; + private static SessionFactory factory = new Configuration().configure().buildSessionFactory(); + + @Override + public Task findBy(Long id) { + List tasks; + try (Session session = factory.openSession()) { + Query query = session.createQuery("FROM Task where id = :id"); + query.setParameter("id", id); + tasks = query.list(); + } + + if (tasks == null || tasks.isEmpty()) { + return null; + } + return tasks.get(0); + } + + @Override + public List findAll() { + List tasks; + try (Session session = factory.openSession()) { + tasks = session.createQuery("FROM Task").list(); + } + return tasks; + } + + @Override + public Task save(Task task) { + try (Session session = factory.openSession()) { + session.beginTransaction(); + session.saveOrUpdate(task); + session.getTransaction().commit(); + } + return task; + } + + @Override + public void deleteById(Long id) { + try (Session session = factory.openSession()) { + session.beginTransaction(); + Task task = new Task(); + task.setId(id); + session.remove(task); + session.getTransaction().commit(); + } } - return tasks.get(0); - } - - @Override - public List findAll() { - Session session = factory.openSession(); - List tasks = session.createQuery("FROM Task").list(); - session.close(); - return tasks; - } - - @Override - public Task save(Task task) { - Session session = factory.openSession(); - session.beginTransaction(); - session.saveOrUpdate(task); - session.getTransaction().commit(); - session.close(); - return task; - } - - @Override - public void deleteById(Long id) { - Session session = factory.openSession(); - session.beginTransaction(); - Task task = new Task(); - task.setId(id); - session.remove(task); - session.getTransaction().commit(); - session.close(); - } } diff --git a/sparkjava/src/main/resources/hibernate.cfg.xml b/sparkjava/src/main/resources/hibernate.cfg.xml index f940e28..05bfbd9 100644 --- a/sparkjava/src/main/resources/hibernate.cfg.xml +++ b/sparkjava/src/main/resources/hibernate.cfg.xml @@ -14,7 +14,7 @@ PUBLIC - 1 + 100 org.hibernate.dialect.H2Dialect