diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/ConsistentHashing.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/ConsistentHashing.java deleted file mode 100644 index 9df933db2..000000000 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/ConsistentHashing.java +++ /dev/null @@ -1,35 +0,0 @@ -package ru.vk.itmo.test.georgiidalbeev; - -import java.util.Collections; -import java.util.List; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.function.Function; - -public class ConsistentHashing { - - private final SortedMap circle; - private final Function hashFunction; - - public ConsistentHashing(Function hashFunction, List nodes) { - this.hashFunction = hashFunction; - SortedMap tempCircle = new TreeMap<>(); - for (T node : nodes) { - int hash = hashFunction.apply((String) node); - tempCircle.put(hash, node); - } - this.circle = Collections.unmodifiableSortedMap(tempCircle); - } - - public T getNode(String key) { - if (circle.isEmpty()) { - return null; - } - int hash = hashFunction.apply(key); - if (!circle.containsKey(hash)) { - SortedMap tailMap = circle.tailMap(hash); - hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey(); - } - return circle.get(hash); - } -} diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyHandleResult.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyHandleResult.java new file mode 100644 index 000000000..a5a7d6ddd --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyHandleResult.java @@ -0,0 +1,14 @@ +package ru.vk.itmo.test.georgiidalbeev; + +public record MyHandleResult(int status, byte[] data, long timestamp) { + + public MyHandleResult(int status, byte[] data, long timestamp) { + this.status = status; + this.data = data; + this.timestamp = timestamp; + } + + public MyHandleResult(int status, byte[] data) { + this(status, data, 0); + } +} diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyMergeHandleResult.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyMergeHandleResult.java new file mode 100644 index 000000000..90cb3e747 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyMergeHandleResult.java @@ -0,0 +1,69 @@ +package ru.vk.itmo.test.georgiidalbeev; + +import one.nio.http.HttpSession; +import one.nio.http.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.concurrent.atomic.AtomicInteger; + +public class MyMergeHandleResult { + private static final Logger log = LoggerFactory.getLogger(MyMergeHandleResult.class); + private final AtomicInteger count; + private final AtomicInteger success; + private final int ack; + private final int from; + private final HttpSession session; + private boolean isSent; + MyHandleResult mergedResult = new MyHandleResult(HttpURLConnection.HTTP_GATEWAY_TIMEOUT, null); + + public MyMergeHandleResult(HttpSession session, int size, int ack) { + this.session = session; + this.count = new AtomicInteger(); + this.ack = ack; + this.from = size; + this.success = new AtomicInteger(); + } + + public void add(MyHandleResult handleResult) { + int get = count.incrementAndGet(); + + if (handleResult.status() == HttpURLConnection.HTTP_OK + || handleResult.status() == HttpURLConnection.HTTP_CREATED + || handleResult.status() == HttpURLConnection.HTTP_ACCEPTED + || handleResult.status() == HttpURLConnection.HTTP_NOT_FOUND) { + success.incrementAndGet(); + if (mergedResult.timestamp() <= handleResult.timestamp()) { + mergedResult = handleResult; + } + if (success.get() >= ack && !isSent) { + isSent = true; + sendResult(); + } + } + + if (get == from && success.get() < ack && !isSent) { + sendResult(); + } + } + + private void sendResult() { + try { + if (success.get() < ack) { + session.sendResponse(new Response(Response.GATEWAY_TIMEOUT, Response.EMPTY)); + } else { + session.sendResponse(new Response(String.valueOf(mergedResult.status()), mergedResult.data())); + } + } catch (Exception e) { + log.error("Exception during handleRequest", e); + try { + session.sendResponse(new Response(Response.INTERNAL_ERROR, Response.EMPTY)); + } catch (IOException ex) { + log.error("Exception while sending close connection", e); + session.scheduleClose(); + } + } + } +} diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyReferenceServer.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyReferenceServer.java new file mode 100644 index 000000000..914a3e28c --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyReferenceServer.java @@ -0,0 +1,286 @@ +package ru.vk.itmo.test.georgiidalbeev; + +import one.nio.async.CustomThreadFactory; +import one.nio.http.HttpServer; +import one.nio.http.HttpServerConfig; +import one.nio.http.HttpSession; +import one.nio.http.Path; +import one.nio.http.Request; +import one.nio.http.Response; +import one.nio.server.AcceptorConfig; +import one.nio.util.Hash; +import one.nio.util.Utf8; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.vk.itmo.ServiceConfig; +import ru.vk.itmo.test.georgiidalbeev.dao.ReferenceBaseEntry; +import ru.vk.itmo.test.georgiidalbeev.dao.ReferenceDao; + +import java.io.IOException; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.function.Supplier; + +import static ru.vk.itmo.test.georgiidalbeev.MyReferenceService.shutdownAndAwaitTermination; + +public class MyReferenceServer extends HttpServer { + + private static final String HEADER_REMOTE = "X-flag-remote-reference-server-to-node-by-paschenko"; + private static final String HEADER_REMOTE_ONE_NIO_HEADER = HEADER_REMOTE + ": da"; + private static final String HEADER_TIMESTAMP = "X-flag-remote-reference-server-to-node-by-paschenko2"; + private static final String HEADER_TIMESTAMP_ONE_NIO_HEADER = HEADER_TIMESTAMP + ": "; + private static final Logger log = LoggerFactory.getLogger(MyReferenceServer.class); + private static final int THREADS = Runtime.getRuntime().availableProcessors(); + + private final ExecutorService executorLocal = Executors.newFixedThreadPool(THREADS / 2, + new CustomThreadFactory("local-work")); + private final ExecutorService executorRemote = Executors.newFixedThreadPool(THREADS / 2, + new CustomThreadFactory("remote-work")); + private final ReferenceDao dao; + private final ServiceConfig config; + private final HttpClient httpClient; + + public MyReferenceServer(ServiceConfig config, ReferenceDao dao) throws IOException { + super(createServerConfigWithPort(config.selfPort())); + this.dao = dao; + this.config = config; + + this.httpClient = HttpClient.newBuilder() + .executor(Executors.newFixedThreadPool(THREADS)) + .connectTimeout(Duration.ofMillis(500)) + .version(HttpClient.Version.HTTP_1_1).build(); + } + + private static HttpServerConfig createServerConfigWithPort(int port) { + HttpServerConfig serverConfig = new HttpServerConfig(); + AcceptorConfig acceptorConfig = new AcceptorConfig(); + acceptorConfig.port = port; + acceptorConfig.reusePort = true; + serverConfig.selectors = Runtime.getRuntime().availableProcessors() / 2; + + serverConfig.acceptors = new AcceptorConfig[]{acceptorConfig}; + serverConfig.closeSessions = true; + return serverConfig; + } + + @Override + public void handleRequest(Request request, HttpSession session) throws IOException { + if (!"/v0/entity".equals(request.getPath())) { + sendError(session, Response.BAD_REQUEST); + return; + } + + if (!isValidMethod(request.getMethod())) { + sendError(session, Response.METHOD_NOT_ALLOWED); + return; + } + + String id = request.getParameter("id="); + if (id == null || id.isBlank()) { + sendError(session, Response.BAD_REQUEST); + return; + } + + if (request.getHeader(HEADER_REMOTE_ONE_NIO_HEADER) != null) { + handleLocalRequest(request, session, id); + return; + } + + int ack = getInt(request, "ack=", config.clusterUrls().size() / 2 + 1); + int from = getInt(request, "from=", config.clusterUrls().size()); + + if (!isValidAckFrom(ack, from)) { + sendError(session, Response.BAD_REQUEST); + return; + } + + handleRemoteRequest(request, session, id, ack, from); + } + + private void sendError(HttpSession session, String errorCode) throws IOException { + session.sendError(errorCode, null); + } + + private boolean isValidMethod(int method) { + return method == Request.METHOD_GET || method == Request.METHOD_DELETE || method == Request.METHOD_PUT; + } + + private void handleLocalRequest(Request request, HttpSession session, String id) { + executorLocal.execute(() -> { + try { + MyHandleResult local = local(request, id); + Response response = new Response(String.valueOf(local.status()), local.data()); + response.addHeader(HEADER_TIMESTAMP_ONE_NIO_HEADER + local.timestamp()); + session.sendResponse(response); + } catch (Exception e) { + handleError(session, e); + } + }); + } + + private boolean isValidAckFrom(int ack, int from) { + return from > 0 && from <= config.clusterUrls().size() && ack <= from && ack > 0; + } + + private void handleRemoteRequest(Request request, HttpSession session, String id, int ack, int from) { + int[] indexes = getIndexes(id, from); + MyMergeHandleResult mergeHandleResult = new MyMergeHandleResult(session, indexes.length, ack); + for (int index : indexes) { + String executorNode = config.clusterUrls().get(index); + if (executorNode.equals(config.selfUrl())) { + handleAsync(mergeHandleResult, () -> CompletableFuture.completedFuture(local(request, id))); + } else { + handleAsync(mergeHandleResult, () -> invokeRemote(executorNode, request)); + } + } + } + + private void handleError(HttpSession session, Exception e) { + log.error("Exception during handleRequest", e); + try { + session.sendResponse(new Response(Response.INTERNAL_ERROR, Response.EMPTY)); + } catch (IOException ex) { + log.error("Exception while sending close connection", e); + session.scheduleClose(); + } + } + + private int getInt(Request request, String param, int defaultValue) throws IOException { + int ack; + String ackStr = request.getParameter(param); + if (ackStr == null || ackStr.isBlank()) { + ack = defaultValue; + } else { + try { + ack = Integer.parseInt(ackStr); + } catch (Exception e) { + throw new IllegalArgumentException("parse error"); + } + } + return ack; + } + + private void handleAsync(MyMergeHandleResult mergeHandleResult, + Supplier> supplier) { + supplier.get().thenAccept(mergeHandleResult::add).exceptionally(e -> { + log.error("Exception during handleRequest", e); + mergeHandleResult.add(new MyHandleResult(HttpURLConnection.HTTP_INTERNAL_ERROR, Response.EMPTY)); + return null; + }); + } + + @Override + public void handleDefault(Request request, HttpSession session) throws IOException { + session.sendResponse(new Response(Response.BAD_REQUEST, Response.EMPTY)); + } + + @Path("/v0/status") + public Response status() { + return Response.ok("OK"); + } + + private CompletableFuture invokeRemote(String executorNode, Request request) { + HttpRequest httpRequest = HttpRequest.newBuilder(URI.create(executorNode + request.getURI())) + .method(request.getMethodName(), request.getBody() == null ? HttpRequest.BodyPublishers.noBody() : + HttpRequest.BodyPublishers.ofByteArray(request.getBody())).header(HEADER_REMOTE, "da") + .timeout(Duration.ofMillis(500)).build(); + + return httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofByteArray()).thenApply(httpResponse -> { + Optional string = httpResponse.headers().firstValue(HEADER_TIMESTAMP); + long timestamp; + if (string.isPresent()) { + try { + timestamp = Long.parseLong(string.get()); + } catch (Exception e) { + log.error("Error while parsing timestamp"); + timestamp = 0; + } + } else { + timestamp = 0; + } + return new MyHandleResult(httpResponse.statusCode(), httpResponse.body(), timestamp); + }).exceptionally(e -> { + log.info("I/O exception while calling remote node", e); + return new MyHandleResult(HttpURLConnection.HTTP_INTERNAL_ERROR, Response.EMPTY); + }); + } + + private MyHandleResult local(Request request, String id) { + long currentTimeMillis = System.currentTimeMillis(); + switch (request.getMethod()) { + case Request.METHOD_GET -> { + MemorySegment key = MemorySegment.ofArray(Utf8.toBytes(id)); + ReferenceBaseEntry entry = dao.get(key); + if (entry == null) { + return new MyHandleResult(HttpURLConnection.HTTP_NOT_FOUND, Response.EMPTY); + } + if (entry.value() == null) { + return new MyHandleResult(HttpURLConnection.HTTP_NOT_FOUND, Response.EMPTY, entry.timestamp()); + } + + return new MyHandleResult(HttpURLConnection.HTTP_OK, + entry.value().toArray(ValueLayout.JAVA_BYTE), + entry.timestamp()); + } + case Request.METHOD_PUT -> { + MemorySegment key = MemorySegment.ofArray(Utf8.toBytes(id)); + MemorySegment value = MemorySegment.ofArray(request.getBody()); + dao.upsert(new ReferenceBaseEntry<>(key, value, currentTimeMillis)); + return new MyHandleResult(HttpURLConnection.HTTP_CREATED, Response.EMPTY); + } + case Request.METHOD_DELETE -> { + MemorySegment key = MemorySegment.ofArray(Utf8.toBytes(id)); + dao.upsert(new ReferenceBaseEntry<>(key, null, currentTimeMillis)); + return new MyHandleResult(HttpURLConnection.HTTP_ACCEPTED, Response.EMPTY); + } + default -> { + return new MyHandleResult(HttpURLConnection.HTTP_BAD_METHOD, Response.EMPTY); + } + } + } + + private int[] getIndexes(String id, int count) { + assert count < 5; + + int[] result = new int[count]; + int[] maxHashs = new int[count]; + + for (int i = 0; i < count; i++) { + String url = config.clusterUrls().get(i); + int hash = Hash.murmur3(url + id); + result[i] = i; + maxHashs[i] = hash; + } + + for (int i = count; i < config.clusterUrls().size(); i++) { + String url = config.clusterUrls().get(i); + int hash = Hash.murmur3(url + id); + for (int j = 0; j < maxHashs.length; j++) { + int maxHash = maxHashs[j]; + if (maxHash < hash) { + maxHashs[j] = hash; + result[j] = i; + break; + } + } + } + return result; + } + + @Override + public synchronized void stop() { + super.stop(); + shutdownAndAwaitTermination(executorLocal); + shutdownAndAwaitTermination(executorRemote); + } +} diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyReferenceService.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyReferenceService.java new file mode 100644 index 000000000..b71333587 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/MyReferenceService.java @@ -0,0 +1,124 @@ +package ru.vk.itmo.test.georgiidalbeev; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.vk.itmo.Service; +import ru.vk.itmo.ServiceConfig; +import ru.vk.itmo.dao.Config; +import ru.vk.itmo.test.ServiceFactory; +import ru.vk.itmo.test.georgiidalbeev.dao.ReferenceDao; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class MyReferenceService implements Service { + private static final Logger log = LoggerFactory.getLogger(MyReferenceService.class); + + private static final long FLUSHING_THRESHOLD_BYTES = 1024 * 1024; + + private static final String LOCALHOST_PREFIX = "http://localhost:"; + + private final ServiceConfig config; + + private ReferenceDao dao; + private MyReferenceServer server; + private boolean stopped; + + public MyReferenceService(ServiceConfig config) { + this.config = config; + } + + public static void shutdownAndAwaitTermination(ExecutorService pool) { + pool.shutdown(); + try { + if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { + pool.shutdownNow(); + if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { + log.error("Pool did not terminate"); + } + } + } catch (InterruptedException ex) { + pool.shutdownNow(); + Thread.currentThread().interrupt(); + } + } + + public static void main(String[] args) throws IOException { + Map nodes = new HashMap<>(); + int nodePort = 8080; + for (int i = 0; i < 3; i++) { + nodes.put(nodePort, LOCALHOST_PREFIX + nodePort); + nodePort += 10; + } + + List clusterUrls = new ArrayList<>(nodes.values()); + List clusterConfs = new ArrayList<>(); + for (Map.Entry entry : nodes.entrySet()) { + int port = entry.getKey(); + String url = entry.getValue(); + Path path = Paths.get("tmp/db/" + port); + Files.createDirectories(path); + ServiceConfig serviceConfig = new ServiceConfig(port, + url, + clusterUrls, + path); + clusterConfs.add(serviceConfig); + } + + for (ServiceConfig serviceConfig : clusterConfs) { + MyReferenceService instance = new MyReferenceService(serviceConfig); + try { + instance.start().get(1, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + log.error("Interrupted exception while start instance"); + } catch (ExecutionException | TimeoutException e) { + throw new IllegalArgumentException(e); + } + } + } + + @Override + public synchronized CompletableFuture start() throws IOException { + dao = new ReferenceDao(new Config(config.workingDir(), FLUSHING_THRESHOLD_BYTES)); + server = new MyReferenceServer(config, dao); + server.start(); + stopped = false; + return CompletableFuture.completedFuture(null); + } + + @Override + public synchronized CompletableFuture stop() throws IOException { + if (stopped) { + return CompletableFuture.completedFuture(null); + } + try { + server.stop(); + + } finally { + dao.close(); + } + stopped = true; + return CompletableFuture.completedFuture(null); + } + + @ServiceFactory(stage = 5) + public static class Factory implements ServiceFactory.Factory { + + @Override + public Service create(ServiceConfig config) { + return new MyReferenceService(config); + } + } +} diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewFactory.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewFactory.java deleted file mode 100644 index 1bbce254b..000000000 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewFactory.java +++ /dev/null @@ -1,14 +0,0 @@ -package ru.vk.itmo.test.georgiidalbeev; - -import ru.vk.itmo.Service; -import ru.vk.itmo.ServiceConfig; -import ru.vk.itmo.test.ServiceFactory; - -@ServiceFactory(stage = 3) -public class NewFactory implements ServiceFactory.Factory { - - @Override - public Service create(ServiceConfig config) { - return new NewService(config); - } -} diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewResponseCodes.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewResponseCodes.java deleted file mode 100644 index 61644e693..000000000 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewResponseCodes.java +++ /dev/null @@ -1,16 +0,0 @@ -package ru.vk.itmo.test.georgiidalbeev; - -public enum NewResponseCodes { - TOO_MANY_REQUESTS("429 Too Many Requests"); - - private final String code; - - NewResponseCodes(String code) { - this.code = code; - } - - public String getCode() { - return code; - } -} - diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewServer.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewServer.java deleted file mode 100644 index 671cb4d18..000000000 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewServer.java +++ /dev/null @@ -1,233 +0,0 @@ -package ru.vk.itmo.test.georgiidalbeev; - -import one.nio.http.HttpException; -import one.nio.http.HttpServer; -import one.nio.http.HttpServerConfig; -import one.nio.http.HttpSession; -import one.nio.http.Param; -import one.nio.http.Path; -import one.nio.http.Request; -import one.nio.http.RequestMethod; -import one.nio.http.Response; -import one.nio.server.AcceptorConfig; -import one.nio.util.Hash; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import ru.vk.itmo.ServiceConfig; -import ru.vk.itmo.dao.BaseEntry; -import ru.vk.itmo.dao.Dao; -import ru.vk.itmo.dao.Entry; - -import java.io.IOException; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.ValueLayout; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.TimeUnit; - -public class NewServer extends HttpServer { - - private static final String PATH = "/v0/entity"; - private static final long MAX_RESPONSE_TIME = TimeUnit.SECONDS.toNanos(1); - private final Dao> dao; - private final ExecutorService executorService; - private final Logger log = LoggerFactory.getLogger(NewServer.class); - private final Map httpClients; - private final ConsistentHashing consistentHashing; - private final String selfUrl; - - public NewServer(ServiceConfig config, - Dao> dao, - ExecutorService executorService, - List clusterUrls, - List httpClients - ) throws IOException { - super(configureServer(config)); - this.dao = dao; - this.executorService = executorService; - this.consistentHashing = new ConsistentHashing<>(Hash::murmur3, clusterUrls); - this.selfUrl = config.selfUrl(); - this.httpClients = new HashMap<>(); - for (int i = 0; i < clusterUrls.size(); i++) { - this.httpClients.put(clusterUrls.get(i), httpClients.get(i)); - } - } - - private static HttpServerConfig configureServer(ServiceConfig serviceConfig) { - HttpServerConfig serverConfig = new HttpServerConfig(); - AcceptorConfig acceptorConfig = new AcceptorConfig(); - acceptorConfig.port = serviceConfig.selfPort(); - acceptorConfig.reusePort = true; - - serverConfig.acceptors = new AcceptorConfig[]{acceptorConfig}; - serverConfig.closeSessions = true; - return serverConfig; - } - - @Path(PATH) - @RequestMethod(Request.METHOD_PUT) - public Response putEntity(@Param(value = "id", required = true) String id, Request request) throws IOException { - MemorySegment key = validateId(id); - if (key == null) { - return new Response(Response.BAD_REQUEST, Response.EMPTY); - } - - String node = consistentHashing.getNode(id); - if (!node.equals(this.selfUrl)) { - return proxyRequest(request, node, id, request.getBody()); - } - - Entry entry = new BaseEntry<>( - key, - MemorySegment.ofArray(request.getBody()) - ); - - dao.upsert(entry); - - return new Response(Response.CREATED, Response.EMPTY); - } - - @Path(PATH) - @RequestMethod(Request.METHOD_GET) - public Response getEntity(@Param(value = "id", required = true) String id, Request request) throws IOException { - MemorySegment key = validateId(id); - if (key == null) { - return new Response(Response.BAD_REQUEST, Response.EMPTY); - } - - String node = consistentHashing.getNode(id); - if (!node.equals(this.selfUrl)) { - return proxyRequest(request, node, id, null); - } - - Entry entry = dao.get(key); - - if (entry == null) { - return new Response(Response.NOT_FOUND, Response.EMPTY); - } - - return Response.ok(entry.value().toArray(ValueLayout.JAVA_BYTE)); - } - - @Path(PATH) - @RequestMethod(Request.METHOD_DELETE) - public Response deleteEntity(@Param(value = "id", required = true) String id, Request request) throws IOException { - MemorySegment key = validateId(id); - if (key == null) { - return new Response(Response.BAD_REQUEST, Response.EMPTY); - } - - String node = consistentHashing.getNode(id); - if (!node.equals(this.selfUrl)) { - return proxyRequest(request, node, id, null); - } - - Entry entry = new BaseEntry<>( - key, - null - ); - - dao.upsert(entry); - - return new Response(Response.ACCEPTED, Response.EMPTY); - } - - @Path(PATH) - public Response otherMethods() { - return new Response(Response.METHOD_NOT_ALLOWED, Response.EMPTY); - } - - @Override - public void handleDefault(Request request, HttpSession session) throws IOException { - Response response = new Response(Response.BAD_REQUEST, Response.EMPTY); - session.sendResponse(response); - } - - private MemorySegment validateId(String id) { - return (id == null || id.isEmpty()) ? null : MemorySegment.ofArray(id.getBytes(StandardCharsets.UTF_8)); - } - - @Override - public void handleRequest(Request request, HttpSession session) throws IOException { - long createdAt = System.nanoTime(); - try { - executorService.execute( - () -> { - if (System.nanoTime() - createdAt > MAX_RESPONSE_TIME) { - try { - session.sendResponse(new Response(Response.REQUEST_TIMEOUT, Response.EMPTY)); - return; - } catch (IOException e) { - log.error("Exception while handing request", e); - session.scheduleClose(); - return; - } - } - - try { - super.handleRequest(request, session); - } catch (Exception e) { - handleRequestException(session, e); - } - } - ); - } catch (RejectedExecutionException e) { - log.error("Pool queue overflow", e); - session.sendResponse(new Response(NewResponseCodes.TOO_MANY_REQUESTS.getCode(), Response.EMPTY)); - } catch (Exception e) { - handleRequestException(session, e); - } - } - - private void handleRequestException(HttpSession session, Exception e) { - try { - if (e instanceof HttpException) { - session.sendResponse(new Response(Response.BAD_REQUEST, Response.EMPTY)); - return; - } - session.sendResponse(new Response(Response.INTERNAL_ERROR, Response.EMPTY)); - } catch (IOException ex) { - log.error("Exception while handing request", e); - session.scheduleClose(); - } - } - - private Response proxyRequest(Request request, String node, String id, byte[] body) throws IOException { - HttpClient httpClient = httpClients.get(node); - HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() - .uri(URI.create(node + PATH + "?id=" + id)); - - switch (request.getMethod()) { - case Request.METHOD_GET: - requestBuilder.GET(); - break; - case Request.METHOD_PUT: - requestBuilder.PUT(HttpRequest.BodyPublishers.ofByteArray(body)); - break; - case Request.METHOD_DELETE: - requestBuilder.DELETE(); - break; - default: - return new Response(Response.METHOD_NOT_ALLOWED, Response.EMPTY); - } - - HttpRequest httpRequest = requestBuilder.build(); - - try { - HttpResponse response = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofByteArray()); - return new Response(String.valueOf(response.statusCode()), response.body()); - } catch (InterruptedException e) { - log.error("Exception while sending request", e); - Thread.currentThread().interrupt(); - return new Response(Response.INTERNAL_ERROR, Response.EMPTY); - } - } -} diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewService.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewService.java deleted file mode 100644 index 99cd9501c..000000000 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/NewService.java +++ /dev/null @@ -1,95 +0,0 @@ -package ru.vk.itmo.test.georgiidalbeev; - -import one.nio.async.CustomThreadFactory; -import ru.vk.itmo.Service; -import ru.vk.itmo.ServiceConfig; -import ru.vk.itmo.dao.Config; -import ru.vk.itmo.dao.Dao; -import ru.vk.itmo.dao.Entry; -import ru.vk.itmo.test.georgiidalbeev.dao.ReferenceDao; - -import java.io.IOException; -import java.lang.foreign.MemorySegment; -import java.net.http.HttpClient; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -public class NewService implements Service { - - private static final long FLUSH_THRESHOLD = 512 * 1024; - private static final int THREADS = 16; - private static final int KEEP_ALIVE_TIME_SECONDS = 60; - private static final int AWAIT_TERMINATION_SECONDS = 60; - private static final int QUEUE_SIZE = 1000; - private volatile boolean isStopped; - private final ServiceConfig config; - private NewServer server; - private Dao> dao; - private ExecutorService executorService; - private List httpClients; - - public NewService(ServiceConfig config) { - this.config = config; - } - - @Override - public CompletableFuture start() throws IOException { - dao = new ReferenceDao(new Config(config.workingDir(), FLUSH_THRESHOLD)); - executorService = createPool(); - - httpClients = config.clusterUrls().stream() - .map(url -> HttpClient.newHttpClient()) - .collect(Collectors.toList()); - - server = new NewServer(config, dao, executorService, config.clusterUrls(), httpClients); - server.start(); - return CompletableFuture.completedFuture(null); - } - - @Override - public CompletableFuture stop() throws IOException { - if (!isStopped) { - server.stop(); - isStopped = true; - } - shutdownExecutorService(); - - for (HttpClient httpClient : httpClients) { - httpClient.close(); - } - - dao.close(); - return CompletableFuture.completedFuture(null); - } - - private void shutdownExecutorService() { - executorService.shutdown(); - try { - if (!executorService.awaitTermination(AWAIT_TERMINATION_SECONDS, TimeUnit.SECONDS)) { - executorService.shutdownNow(); - } - } catch (InterruptedException ex) { - executorService.shutdownNow(); - Thread.currentThread().interrupt(); - } - } - - private ThreadPoolExecutor createPool() { - ThreadPoolExecutor pool = new ThreadPoolExecutor( - THREADS, - THREADS, - KEEP_ALIVE_TIME_SECONDS, - TimeUnit.SECONDS, - new ArrayBlockingQueue<>(QUEUE_SIZE), - new CustomThreadFactory("PoolThread", true), - new ThreadPoolExecutor.AbortPolicy() - ); - pool.prestartAllCoreThreads(); - return pool; - } -} diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/Server.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/Server.java deleted file mode 100644 index a2ec5454e..000000000 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/Server.java +++ /dev/null @@ -1,37 +0,0 @@ -package ru.vk.itmo.test.georgiidalbeev; - -import ru.vk.itmo.ServiceConfig; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; - -public final class Server { - - private static final String DIRECTORY = "tmp/dao1"; - - private Server() { - - } - - @SuppressWarnings("FutureReturnValueIgnored") - public static void main(String[] args) throws IOException { - Path directoryPath = Paths.get(DIRECTORY); - if (!Files.exists(directoryPath)) { - Files.createDirectories(directoryPath); - } - - NewService service = new NewService( - new ServiceConfig( - 8080, - "http://localhost:8080", - List.of("http://localhost:8080", "http://localhost:8081", "http://localhost:8082"), - directoryPath - ) - ); - - service.start(); - } -} diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/LiveFilteringIterator.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/LiveFilteringIterator.java index 86976013a..c3ef7ead4 100644 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/LiveFilteringIterator.java +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/LiveFilteringIterator.java @@ -11,18 +11,18 @@ * * @author incubos */ -final class LiveFilteringIterator implements Iterator> { - private final Iterator> delegate; - private Entry next; +final class LiveFilteringIterator implements Iterator> { + private final Iterator> delegate; + private ReferenceBaseEntry next; - LiveFilteringIterator(final Iterator> delegate) { + LiveFilteringIterator(final Iterator> delegate) { this.delegate = delegate; skipTombstones(); } private void skipTombstones() { while (delegate.hasNext()) { - final Entry entry = delegate.next(); + final ReferenceBaseEntry entry = delegate.next(); if (entry.value() != null) { this.next = entry; break; @@ -36,13 +36,13 @@ public boolean hasNext() { } @Override - public Entry next() { + public ReferenceBaseEntry next() { if (!hasNext()) { throw new NoSuchElementException(); } // Consume - final Entry result = next; + final ReferenceBaseEntry result = next; next = null; skipTombstones(); diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/MemTable.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/MemTable.java index 5eff34656..1422f42c8 100644 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/MemTable.java +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/MemTable.java @@ -1,7 +1,5 @@ package ru.vk.itmo.test.georgiidalbeev.dao; -import ru.vk.itmo.dao.Entry; - import java.lang.foreign.MemorySegment; import java.util.Iterator; import java.util.NavigableMap; @@ -13,7 +11,7 @@ * @author incubos */ final class MemTable { - private final NavigableMap> map = + private final NavigableMap> map = new ConcurrentSkipListMap<>( MemorySegmentComparator.INSTANCE); @@ -21,7 +19,7 @@ boolean isEmpty() { return map.isEmpty(); } - Iterator> get( + Iterator> get( final MemorySegment from, final MemorySegment to) { if (from == null && to == null) { @@ -39,11 +37,11 @@ Iterator> get( } } - Entry get(final MemorySegment key) { + ReferenceBaseEntry get(final MemorySegment key) { return map.get(key); } - Entry upsert(final Entry entry) { + ReferenceBaseEntry upsert(final ReferenceBaseEntry entry) { return map.put(entry.key(), entry); } } diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/MergingEntryIterator.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/MergingEntryIterator.java index 3ad8522f5..b0ff9cbfd 100644 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/MergingEntryIterator.java +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/MergingEntryIterator.java @@ -1,7 +1,5 @@ package ru.vk.itmo.test.georgiidalbeev.dao; -import ru.vk.itmo.dao.Entry; - import java.lang.foreign.MemorySegment; import java.util.Iterator; import java.util.List; @@ -14,7 +12,7 @@ * * @author incubos */ -final class MergingEntryIterator implements Iterator> { +final class MergingEntryIterator implements Iterator> { private final Queue iterators; MergingEntryIterator(final List iterators) { @@ -29,13 +27,13 @@ public boolean hasNext() { } @Override - public Entry next() { + public ReferenceBaseEntry next() { if (!hasNext()) { throw new NoSuchElementException(); } final WeightedPeekingEntryIterator top = iterators.remove(); - final Entry result = top.next(); + final ReferenceBaseEntry result = top.next(); if (top.hasNext()) { // Not exhausted @@ -51,7 +49,7 @@ public Entry next() { } // Skip entries with the same key - final Entry entry = iterator.peek(); + final ReferenceBaseEntry entry = iterator.peek(); if (MemorySegmentComparator.INSTANCE.compare(result.key(), entry.key()) != 0) { // Reached another key break; diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/ReferenceBaseEntry.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/ReferenceBaseEntry.java new file mode 100644 index 000000000..a27c0b4ae --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/ReferenceBaseEntry.java @@ -0,0 +1,10 @@ +package ru.vk.itmo.test.georgiidalbeev.dao; + +import ru.vk.itmo.dao.Entry; + +public record ReferenceBaseEntry(D key, D value, long timestamp) implements Entry { + @Override + public String toString() { + return "{" + key + ":" + value + "," + timestamp + "}"; + } +} diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/ReferenceDao.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/ReferenceDao.java index 5097c1541..d5e0326fe 100644 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/ReferenceDao.java +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/ReferenceDao.java @@ -22,7 +22,7 @@ * * @author incubos */ -public class ReferenceDao implements Dao> { +public class ReferenceDao implements Dao> { private final Config config; private final Arena arena; @@ -63,7 +63,7 @@ public ReferenceDao(final Config config) throws IOException { } @Override - public Iterator> get( + public Iterator> get( final MemorySegment from, final MemorySegment to) { return new LiveFilteringIterator( @@ -73,13 +73,13 @@ public Iterator> get( } @Override - public Entry get(final MemorySegment key) { + public ReferenceBaseEntry get(final MemorySegment key) { // Without lock, just snapshot of table set return tableSet.get(key); } @Override - public void upsert(final Entry entry) { + public void upsert(final ReferenceBaseEntry entry) { final boolean autoFlush; lock.readLock().lock(); try { diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/SSTable.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/SSTable.java index dde19cc32..8a23f682d 100644 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/SSTable.java +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/SSTable.java @@ -1,8 +1,5 @@ package ru.vk.itmo.test.georgiidalbeev.dao; -import ru.vk.itmo.dao.BaseEntry; -import ru.vk.itmo.dao.Entry; - import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; import java.util.Collections; @@ -88,7 +85,7 @@ private long getLength(final long offset) { offset); } - Iterator> get( + Iterator> get( final MemorySegment from, final MemorySegment to) { assert from == null || to == null || MemorySegmentComparator.INSTANCE.compare(from, to) <= 0; @@ -134,7 +131,7 @@ Iterator> get( return new SliceIterator(fromOffset, toOffset); } - Entry get(final MemorySegment key) { + ReferenceBaseEntry get(final MemorySegment key) { final long entry = entryBinarySearch(key); if (entry < 0) { return null; @@ -143,20 +140,23 @@ Entry get(final MemorySegment key) { // Skip key (will reuse the argument) long offset = entryOffset(entry); offset += Long.BYTES + key.byteSize(); + // Extract timestamp + long timestamp = data.get(ValueLayout.OfLong.JAVA_LONG_UNALIGNED, offset); + offset += Long.BYTES; // Extract value length final long valueLength = getLength(offset); if (valueLength == SSTables.TOMBSTONE_VALUE_LENGTH) { // Tombstone encountered - return new BaseEntry<>(key, null); + return new ReferenceBaseEntry<>(key, null, timestamp); } else { // Get value offset += Long.BYTES; final MemorySegment value = data.asSlice(offset, valueLength); - return new BaseEntry<>(key, value); + return new ReferenceBaseEntry<>(key, value, timestamp); } } - private final class SliceIterator implements Iterator> { + private final class SliceIterator implements Iterator> { private long offset; private final long toOffset; @@ -173,7 +173,7 @@ public boolean hasNext() { } @Override - public Entry next() { + public ReferenceBaseEntry next() { if (!hasNext()) { throw new NoSuchElementException(); } @@ -186,6 +186,10 @@ public Entry next() { final MemorySegment key = data.asSlice(offset, keyLength); offset += keyLength; + // Read timestamp + long timestamp = data.get(ValueLayout.OfLong.JAVA_LONG_UNALIGNED, offset); + offset += Long.BYTES; + // Read value length final long valueLength = getLength(offset); offset += Long.BYTES; @@ -193,11 +197,11 @@ public Entry next() { // Read value if (valueLength == SSTables.TOMBSTONE_VALUE_LENGTH) { // Tombstone encountered - return new BaseEntry<>(key, null); + return new ReferenceBaseEntry<>(key, null, timestamp); } else { final MemorySegment value = data.asSlice(offset, valueLength); offset += valueLength; - return new BaseEntry<>(key, value); + return new ReferenceBaseEntry<>(key, value, timestamp); } } } diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/SSTableWriter.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/SSTableWriter.java index 196527145..2be2b1bd4 100644 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/SSTableWriter.java +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/SSTableWriter.java @@ -1,7 +1,5 @@ package ru.vk.itmo.test.georgiidalbeev.dao; -import ru.vk.itmo.dao.Entry; - import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; @@ -15,7 +13,7 @@ import java.util.Iterator; /** - * Writes {@link Entry} {@link Iterator} to SSTable on disk. + * Writes {@link ReferenceBaseEntry} {@link Iterator} to SSTable on disk. * *

Index file {@code .index} contains {@code long} offsets to entries in data file: * {@code [offset0, offset1, ...]} @@ -40,7 +38,7 @@ final class SSTableWriter { void write( final Path baseDir, final int sequence, - final Iterator> entries) throws IOException { + final Iterator> entries) throws IOException { // Write to temporary files final Path tempIndexName = SSTables.tempIndexName(baseDir, sequence); final Path tempDataName = SSTables.tempDataName(baseDir, sequence); @@ -71,7 +69,7 @@ void write( writeLong(entryOffset, index); // Then write the entry - final Entry entry = entries.next(); + final ReferenceBaseEntry entry = entries.next(); entryOffset += writeEntry(entry, data); } } @@ -127,15 +125,16 @@ private void writeSegment( } /** - * Writes {@link Entry} to {@link FileChannel}. + * Writes {@link ReferenceBaseEntry} to {@link FileChannel}. * * @return written bytes */ private long writeEntry( - final Entry entry, + final ReferenceBaseEntry entry, final OutputStream os) throws IOException { final MemorySegment key = entry.key(); final MemorySegment value = entry.value(); + final long timestamp = entry.timestamp(); long result = 0L; // Key size @@ -146,6 +145,10 @@ private long writeEntry( writeSegment(key, os); result += key.byteSize(); + // timestamp + writeLong(timestamp, os); + result += Long.BYTES; + // Value size and possibly value if (value == null) { // Tombstone diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/TableSet.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/TableSet.java index cb908eee1..b6034666a 100644 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/TableSet.java +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/TableSet.java @@ -1,7 +1,5 @@ package ru.vk.itmo.test.georgiidalbeev.dao; -import ru.vk.itmo.dao.Entry; - import java.lang.foreign.MemorySegment; import java.util.ArrayList; import java.util.Collections; @@ -98,14 +96,14 @@ TableSet compacted( newSsTables); } - Iterator> get( + Iterator> get( final MemorySegment from, final MemorySegment to) { final List iterators = new ArrayList<>(2 + ssTables.size()); // MemTable goes first - final Iterator> memTableIterator = + final Iterator> memTableIterator = memTable.get(from, to); if (memTableIterator.hasNext()) { iterators.add( @@ -116,7 +114,7 @@ Iterator> get( // Then goes flushing if (flushingTable != null) { - final Iterator> flushingIterator = + final Iterator> flushingIterator = flushingTable.get(from, to); if (flushingIterator.hasNext()) { iterators.add( @@ -129,7 +127,7 @@ Iterator> get( // Then go all the SSTables for (int i = 0; i < ssTables.size(); i++) { final SSTable ssTable = ssTables.get(i); - final Iterator> ssTableIterator = + final Iterator> ssTableIterator = ssTable.get(from, to); if (ssTableIterator.hasNext()) { iterators.add( @@ -146,14 +144,14 @@ Iterator> get( }; } - Entry get(final MemorySegment key) { + ReferenceBaseEntry get(final MemorySegment key) { // Slightly optimized version not to pollute the heap // First check MemTable - Entry result = memTable.get(key); + ReferenceBaseEntry result = memTable.get(key); if (result != null) { // Transform tombstone - return swallowTombstone(result); + return result; } // Then check flushing @@ -161,7 +159,7 @@ Entry get(final MemorySegment key) { result = flushingTable.get(key); if (result != null) { // Transform tombstone - return swallowTombstone(result); + return result; } } @@ -170,7 +168,7 @@ Entry get(final MemorySegment key) { result = ssTable.get(key); if (result != null) { // Transform tombstone - return swallowTombstone(result); + return result; } } @@ -178,21 +176,17 @@ Entry get(final MemorySegment key) { return null; } - private static Entry swallowTombstone(final Entry entry) { - return entry.value() == null ? null : entry; - } - - Entry upsert(final Entry entry) { + ReferenceBaseEntry upsert(final ReferenceBaseEntry entry) { return memTable.upsert(entry); } - Iterator> allSSTableEntries() { + Iterator> allSSTableEntries() { final List iterators = new ArrayList<>(ssTables.size()); for (int i = 0; i < ssTables.size(); i++) { final SSTable ssTable = ssTables.get(i); - final Iterator> ssTableIterator = + final Iterator> ssTableIterator = ssTable.get(null, null); iterators.add( new WeightedPeekingEntryIterator( diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/WeightedPeekingEntryIterator.java b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/WeightedPeekingEntryIterator.java index 551e9d90b..6d843a27f 100644 --- a/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/WeightedPeekingEntryIterator.java +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/dao/WeightedPeekingEntryIterator.java @@ -1,7 +1,5 @@ package ru.vk.itmo.test.georgiidalbeev.dao; -import ru.vk.itmo.dao.Entry; - import java.lang.foreign.MemorySegment; import java.util.Iterator; import java.util.NoSuchElementException; @@ -12,15 +10,15 @@ * @author incubos */ final class WeightedPeekingEntryIterator - implements Iterator>, + implements Iterator>, Comparable { private final int weight; - private final Iterator> delegate; - private Entry next; + private final Iterator> delegate; + private ReferenceBaseEntry next; WeightedPeekingEntryIterator( final int weight, - final Iterator> delegate) { + final Iterator> delegate) { this.weight = weight; this.delegate = delegate; this.next = delegate.hasNext() ? delegate.next() : null; @@ -32,17 +30,17 @@ public boolean hasNext() { } @Override - public Entry next() { + public ReferenceBaseEntry next() { if (!hasNext()) { throw new NoSuchElementException(); } - final Entry result = next; + final ReferenceBaseEntry result = next; next = delegate.hasNext() ? delegate.next() : null; return result; } - Entry peek() { + ReferenceBaseEntry peek() { if (!hasNext()) { throw new NoSuchElementException(); } diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/get_alloc.html b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/get_alloc.html new file mode 100644 index 000000000..4381ca633 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/get_alloc.html @@ -0,0 +1,25771 @@ + + + + + + + +

Allocation profile

+
  
+
Produced by async-profiler
+ +
+

+

Matched:

+ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/get_cpu.html b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/get_cpu.html new file mode 100644 index 000000000..a2b719f9d --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/get_cpu.html @@ -0,0 +1,23590 @@ + + + + + + + +

CPU profile

+
  
+
Produced by async-profiler
+ +
+

+

Matched:

+ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/get_lock.html b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/get_lock.html new file mode 100644 index 000000000..0a7655e0c --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/get_lock.html @@ -0,0 +1,4892 @@ + + + + + + + +

Lock profile

+
  
+
Produced by async-profiler
+ +
+

+

Matched:

+ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/put_alloc.html b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/put_alloc.html new file mode 100644 index 000000000..b3220fadf --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/put_alloc.html @@ -0,0 +1,26726 @@ + + + + + + + +

Allocation profile

+
  
+
Produced by async-profiler
+ +
+

+

Matched:

+ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/put_cpu.html b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/put_cpu.html new file mode 100644 index 000000000..eaa90ded0 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/put_cpu.html @@ -0,0 +1,25040 @@ + + + + + + + +

CPU profile

+
  
+
Produced by async-profiler
+ +
+

+

Matched:

+ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/put_lock.html b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/put_lock.html new file mode 100644 index 000000000..81e5b3b66 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/async_profiler_result/put_lock.html @@ -0,0 +1,4851 @@ + + + + + + + +

Lock profile

+
  
+
Produced by async-profiler
+ +
+

+

Matched:

+ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/scripts/fill.lua b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/scripts/fill.lua new file mode 100644 index 000000000..d3573bceb --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/scripts/fill.lua @@ -0,0 +1,20 @@ +local random = require("math").random +local char = require("string").char + +local function randomString(n) + local result = {} + for i = 1, n do + result[i] = char(random(33, 126)) -- ASCII символы с 33 по 126 + end + return table.concat(result) +end + +counter = 0 +function request() + counter = counter + 1 + local headers = {} + headers["Host"] = "localhost:8080" + local key = "key" .. counter + local value = "value$" .. randomString(100) + return wrk.format("PUT", "/v0/entity?id=" .. key .. "&ack=3&from=3", headers, value) +end \ No newline at end of file diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/scripts/get.lua b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/scripts/get.lua new file mode 100644 index 000000000..0dd0303ac --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/scripts/get.lua @@ -0,0 +1,7 @@ +function request() + local headers = {} + headers["Host"] = "localhost:8080" + local id = math.random(1, 10000) + local key = "key" .. id + return wrk.format("GET", "/v0/entity?id=" .. key .. "&ack=3&from=3", headers) +end \ No newline at end of file diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_get_result.txt b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_get_result.txt new file mode 100644 index 000000000..13354bce7 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_get_result.txt @@ -0,0 +1,108 @@ + Thread Stats Avg Stdev Max +/- Stdev + Latency 44.91ms 33.99ms 142.85ms 52.62% + Req/Sec -nan -nan 0.00 0.00% + Latency Distribution (HdrHistogram - Recorded Latency) + 50.000% 44.61ms + 75.000% 74.24ms + 90.000% 90.62ms + 99.000% 114.50ms + 99.900% 129.15ms + 99.990% 138.24ms + 99.999% 141.57ms +100.000% 142.98ms + + Detailed Percentile spectrum: + Value Percentile TotalCount 1/(1-Percentile) + + 0.664 0.000000 1 1.00 + 3.191 0.100000 8305 1.11 + 5.719 0.200000 16611 1.25 + 14.503 0.300000 24912 1.43 + 28.143 0.400000 33212 1.67 + 44.607 0.500000 41518 2.00 + 52.511 0.550000 45672 2.22 + 58.911 0.600000 49835 2.50 + 64.319 0.650000 53979 2.86 + 69.375 0.700000 58171 3.33 + 74.239 0.750000 62318 4.00 + 76.799 0.775000 64399 4.44 + 79.167 0.800000 66452 5.00 + 81.791 0.825000 68508 5.71 + 84.671 0.850000 70591 6.67 + 87.487 0.875000 72666 8.00 + 89.087 0.887500 73733 8.89 + 90.623 0.900000 74735 10.00 + 92.351 0.912500 75785 11.43 + 93.951 0.925000 76812 13.33 + 95.935 0.937500 77871 16.00 + 97.023 0.943750 78377 17.78 + 98.239 0.950000 78890 20.00 + 99.583 0.956250 79398 22.86 + 101.247 0.962500 79921 26.67 + 103.039 0.968750 80444 32.00 + 104.063 0.971875 80699 35.56 + 105.151 0.975000 80961 40.00 + 106.431 0.978125 81217 45.71 + 107.967 0.981250 81481 53.33 + 110.079 0.984375 81735 64.00 + 111.487 0.985938 81870 71.11 + 112.639 0.987500 81994 80.00 + 113.791 0.989062 82122 91.43 + 115.135 0.990625 82257 106.67 + 116.287 0.992188 82384 128.00 + 116.991 0.992969 82447 142.22 + 117.695 0.993750 82513 160.00 + 118.399 0.994531 82576 182.86 + 119.487 0.995313 82644 213.33 + 120.767 0.996094 82708 256.00 + 121.343 0.996484 82740 284.44 + 122.111 0.996875 82774 320.00 + 122.751 0.997266 82803 365.71 + 123.711 0.997656 82837 426.67 + 124.671 0.998047 82869 512.00 + 125.503 0.998242 82885 568.89 + 126.399 0.998437 82903 640.00 + 127.167 0.998633 82917 731.43 + 128.063 0.998828 82934 853.33 + 129.343 0.999023 82949 1024.00 + 130.175 0.999121 82958 1137.78 + 131.071 0.999219 82966 1280.00 + 131.711 0.999316 82974 1462.86 + 132.479 0.999414 82982 1706.67 + 133.759 0.999512 82990 2048.00 + 134.271 0.999561 82995 2275.56 + 134.655 0.999609 82998 2560.00 + 135.167 0.999658 83002 2925.71 + 135.679 0.999707 83007 3413.33 + 136.063 0.999756 83010 4096.00 + 136.319 0.999780 83012 4551.11 + 136.447 0.999805 83014 5120.00 + 136.959 0.999829 83016 5851.43 + 137.855 0.999854 83018 6826.67 + 137.983 0.999878 83020 8192.00 + 138.239 0.999890 83023 9102.22 + 138.239 0.999902 83023 10240.00 + 138.239 0.999915 83023 11702.86 + 138.495 0.999927 83024 13653.33 + 139.391 0.999939 83025 16384.00 + 139.775 0.999945 83026 18204.44 + 139.775 0.999951 83026 20480.00 + 140.159 0.999957 83027 23405.71 + 140.159 0.999963 83027 27306.67 + 140.287 0.999969 83028 32768.00 + 140.287 0.999973 83028 36408.89 + 140.287 0.999976 83028 40960.00 + 141.567 0.999979 83029 46811.43 + 141.567 0.999982 83029 54613.33 + 141.567 0.999985 83029 65536.00 + 141.567 0.999986 83029 72817.78 + 141.567 0.999988 83029 81920.00 + 142.975 0.999989 83030 93622.86 + 142.975 1.000000 83030 inf +#[Mean = 44.908, StdDeviation = 33.987] +#[Max = 142.848, Total count = 83030] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 94196 requests in 9.88s, 15.27MB read +Requests/sec: 9532.71 +Transfer/sec: 1.55MB diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_get_result_ack2.txt b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_get_result_ack2.txt new file mode 100644 index 000000000..817261331 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_get_result_ack2.txt @@ -0,0 +1,111 @@ + Thread Stats Avg Stdev Max +/- Stdev + Latency 96.85ms 42.12ms 217.22ms 70.21% + Req/Sec -nan -nan 0.00 0.00% + Latency Distribution (HdrHistogram - Recorded Latency) + 50.000% 95.93ms + 75.000% 126.59ms + 90.000% 150.01ms + 99.000% 188.67ms + 99.900% 209.41ms + 99.990% 215.55ms + 99.999% 216.83ms +100.000% 217.34ms + + Detailed Percentile spectrum: + Value Percentile TotalCount 1/(1-Percentile) + + 0.410 0.000000 1 1.00 + 33.247 0.100000 13618 1.11 + 68.671 0.200000 27257 1.25 + 79.807 0.300000 40869 1.43 + 87.871 0.400000 54555 1.67 + 95.935 0.500000 68157 2.00 + 100.671 0.550000 74914 2.22 + 106.239 0.600000 81705 2.50 + 112.959 0.650000 88498 2.86 + 119.871 0.700000 95322 3.33 + 126.591 0.750000 102128 4.00 + 129.983 0.775000 105535 4.44 + 133.631 0.800000 108993 5.00 + 137.215 0.825000 112313 5.71 + 141.183 0.850000 115772 6.67 + 145.407 0.875000 119219 8.00 + 147.583 0.887500 120885 8.89 + 150.015 0.900000 122577 10.00 + 152.447 0.912500 124227 11.43 + 155.263 0.925000 125940 13.33 + 158.591 0.937500 127657 16.00 + 160.511 0.943750 128513 17.78 + 162.687 0.950000 129351 20.00 + 164.863 0.956250 130181 22.86 + 167.295 0.962500 131045 26.67 + 170.367 0.968750 131881 32.00 + 172.031 0.971875 132310 35.56 + 173.823 0.975000 132752 40.00 + 175.871 0.978125 133167 45.71 + 178.303 0.981250 133594 53.33 + 181.887 0.984375 134019 64.00 + 183.807 0.985938 134233 71.11 + 185.855 0.987500 134439 80.00 + 187.647 0.989062 134654 91.43 + 189.567 0.990625 134857 106.67 + 191.743 0.992188 135075 128.00 + 193.023 0.992969 135177 142.22 + 194.175 0.993750 135282 160.00 + 195.327 0.994531 135391 182.86 + 197.375 0.995313 135495 213.33 + 199.807 0.996094 135603 256.00 + 201.087 0.996484 135658 284.44 + 202.111 0.996875 135710 320.00 + 203.391 0.997266 135764 365.71 + 204.543 0.997656 135819 426.67 + 205.695 0.998047 135869 512.00 + 206.207 0.998242 135900 568.89 + 207.103 0.998437 135923 640.00 + 207.743 0.998633 135947 731.43 + 208.639 0.998828 135975 853.33 + 209.535 0.999023 136001 1024.00 + 210.047 0.999121 136015 1137.78 + 210.431 0.999219 136029 1280.00 + 210.943 0.999316 136039 1462.86 + 211.583 0.999414 136053 1706.67 + 212.095 0.999512 136067 2048.00 + 212.607 0.999561 136075 2275.56 + 212.863 0.999609 136079 2560.00 + 213.375 0.999658 136086 2925.71 + 213.759 0.999707 136093 3413.33 + 214.399 0.999756 136099 4096.00 + 214.655 0.999780 136105 4551.11 + 214.911 0.999805 136110 5120.00 + 214.911 0.999829 136110 5851.43 + 215.167 0.999854 136113 6826.67 + 215.423 0.999878 136116 8192.00 + 215.551 0.999890 136119 9102.22 + 215.551 0.999902 136119 10240.00 + 215.679 0.999915 136121 11702.86 + 215.935 0.999927 136123 13653.33 + 216.063 0.999939 136125 16384.00 + 216.063 0.999945 136125 18204.44 + 216.319 0.999951 136127 20480.00 + 216.319 0.999957 136127 23405.71 + 216.447 0.999963 136129 27306.67 + 216.447 0.999969 136129 32768.00 + 216.447 0.999973 136129 36408.89 + 216.447 0.999976 136129 40960.00 + 216.703 0.999979 136130 46811.43 + 216.703 0.999982 136130 54613.33 + 216.703 0.999985 136130 65536.00 + 216.831 0.999986 136131 72817.78 + 216.831 0.999988 136131 81920.00 + 216.831 0.999989 136131 93622.86 + 216.831 0.999991 136131 109226.67 + 216.831 0.999992 136131 131072.00 + 217.343 0.999993 136132 145635.56 + 217.343 1.000000 136132 inf +#[Mean = 96.854, StdDeviation = 42.125] +#[Max = 217.216, Total count = 136132] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 142960 requests in 9.89s, 23.18MB read +Requests/sec: 14452.83 +Transfer/sec: 2.34MB diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_put_result.txt b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_put_result.txt new file mode 100644 index 000000000..c99ba2991 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_put_result.txt @@ -0,0 +1,108 @@ + Thread Stats Avg Stdev Max +/- Stdev + Latency 37.12ms 47.28ms 190.34ms 80.55% + Req/Sec -nan -nan 0.00 0.00% + Latency Distribution (HdrHistogram - Recorded Latency) + 50.000% 8.73ms + 75.000% 73.41ms + 90.000% 119.29ms + 99.000% 162.69ms + 99.900% 178.43ms + 99.990% 187.39ms + 99.999% 190.08ms +100.000% 190.46ms + + Detailed Percentile spectrum: + Value Percentile TotalCount 1/(1-Percentile) + + 0.623 0.000000 1 1.00 + 2.351 0.100000 8234 1.11 + 3.605 0.200000 16462 1.25 + 4.919 0.300000 24698 1.43 + 6.447 0.400000 32938 1.67 + 8.735 0.500000 41162 2.00 + 10.695 0.550000 45272 2.22 + 15.591 0.600000 49376 2.50 + 22.095 0.650000 53493 2.86 + 59.007 0.700000 57613 3.33 + 73.407 0.750000 61732 4.00 + 78.463 0.775000 63788 4.44 + 83.391 0.800000 65841 5.00 + 88.383 0.825000 67895 5.71 + 94.783 0.850000 69952 6.67 + 103.231 0.875000 72007 8.00 + 111.935 0.887500 73040 8.89 + 119.295 0.900000 74067 10.00 + 124.991 0.912500 75093 11.43 + 129.407 0.925000 76133 13.33 + 133.887 0.937500 77181 16.00 + 136.191 0.943750 77668 17.78 + 138.623 0.950000 78181 20.00 + 141.439 0.956250 78707 22.86 + 144.255 0.962500 79208 26.67 + 147.199 0.968750 79727 32.00 + 148.991 0.971875 79979 35.56 + 150.911 0.975000 80247 40.00 + 153.087 0.978125 80501 45.71 + 155.519 0.981250 80764 53.33 + 157.695 0.984375 81011 64.00 + 158.975 0.985938 81144 71.11 + 160.383 0.987500 81275 80.00 + 161.663 0.989062 81401 91.43 + 163.455 0.990625 81536 106.67 + 165.631 0.992188 81658 128.00 + 166.911 0.992969 81722 142.22 + 168.319 0.993750 81780 160.00 + 169.855 0.994531 81843 182.86 + 171.391 0.995313 81911 213.33 + 172.927 0.996094 81973 256.00 + 173.567 0.996484 82006 284.44 + 174.079 0.996875 82038 320.00 + 174.591 0.997266 82073 365.71 + 175.487 0.997656 82110 426.67 + 176.127 0.998047 82140 512.00 + 176.511 0.998242 82155 568.89 + 177.023 0.998437 82166 640.00 + 177.663 0.998633 82187 731.43 + 178.047 0.998828 82201 853.33 + 178.559 0.999023 82216 1024.00 + 178.815 0.999121 82221 1137.78 + 179.327 0.999219 82230 1280.00 + 179.839 0.999316 82237 1462.86 + 180.735 0.999414 82246 1706.67 + 181.503 0.999512 82253 2048.00 + 182.143 0.999561 82259 2275.56 + 182.783 0.999609 82261 2560.00 + 183.423 0.999658 82265 2925.71 + 184.063 0.999707 82270 3413.33 + 184.447 0.999756 82273 4096.00 + 184.959 0.999780 82275 4551.11 + 185.087 0.999805 82277 5120.00 + 185.215 0.999829 82279 5851.43 + 185.855 0.999854 82282 6826.67 + 186.495 0.999878 82283 8192.00 + 187.263 0.999890 82284 9102.22 + 187.391 0.999902 82285 10240.00 + 187.519 0.999915 82286 11702.86 + 187.647 0.999927 82287 13653.33 + 188.159 0.999939 82288 16384.00 + 188.799 0.999945 82289 18204.44 + 188.799 0.999951 82289 20480.00 + 188.927 0.999957 82290 23405.71 + 188.927 0.999963 82290 27306.67 + 189.183 0.999969 82291 32768.00 + 189.183 0.999973 82291 36408.89 + 189.183 0.999976 82291 40960.00 + 190.079 0.999979 82292 46811.43 + 190.079 0.999982 82292 54613.33 + 190.079 0.999985 82292 65536.00 + 190.079 0.999986 82292 72817.78 + 190.079 0.999988 82292 81920.00 + 190.463 0.999989 82293 93622.86 + 190.463 1.000000 82293 inf +#[Mean = 37.116, StdDeviation = 47.281] +#[Max = 190.336, Total count = 82293] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 95902 requests in 9.90s, 6.13MB read +Requests/sec: 9683.85 +Transfer/sec: 633.61KB diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_put_result_ack2.txt b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_put_result_ack2.txt new file mode 100644 index 000000000..adb0cc17f --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/full_result/full_put_result_ack2.txt @@ -0,0 +1,111 @@ + Thread Stats Avg Stdev Max +/- Stdev + Latency 68.08ms 40.66ms 183.94ms 65.04% + Req/Sec -nan -nan 0.00 0.00% + Latency Distribution (HdrHistogram - Recorded Latency) + 50.000% 66.05ms + 75.000% 95.29ms + 90.000% 124.74ms + 99.000% 163.33ms + 99.900% 175.74ms + 99.990% 181.63ms + 99.999% 183.55ms +100.000% 184.06ms + + Detailed Percentile spectrum: + Value Percentile TotalCount 1/(1-Percentile) + + 0.405 0.000000 1 1.00 + 16.943 0.100000 14186 1.11 + 29.231 0.200000 28361 1.25 + 40.927 0.300000 42547 1.43 + 53.343 0.400000 56736 1.67 + 66.047 0.500000 70967 2.00 + 72.191 0.550000 78066 2.22 + 77.823 0.600000 85128 2.50 + 83.839 0.650000 92211 2.86 + 89.535 0.700000 99264 3.33 + 95.295 0.750000 106380 4.00 + 98.687 0.775000 109914 4.44 + 102.655 0.800000 113450 5.00 + 107.199 0.825000 117012 5.71 + 112.127 0.850000 120524 6.67 + 117.887 0.875000 124081 8.00 + 121.023 0.887500 125835 8.89 + 124.735 0.900000 127615 10.00 + 128.703 0.912500 129398 11.43 + 132.863 0.925000 131152 13.33 + 137.983 0.937500 132921 16.00 + 140.927 0.943750 133813 17.78 + 143.743 0.950000 134702 20.00 + 146.431 0.956250 135581 22.86 + 149.247 0.962500 136502 26.67 + 151.935 0.968750 137375 32.00 + 153.343 0.971875 137791 35.56 + 154.879 0.975000 138253 40.00 + 156.415 0.978125 138702 45.71 + 158.079 0.981250 139154 53.33 + 159.743 0.984375 139566 64.00 + 160.639 0.985938 139790 71.11 + 161.663 0.987500 140032 80.00 + 162.687 0.989062 140244 91.43 + 163.711 0.990625 140451 106.67 + 164.991 0.992188 140680 128.00 + 165.631 0.992969 140783 142.22 + 166.399 0.993750 140907 160.00 + 167.167 0.994531 141012 182.86 + 168.191 0.995313 141119 213.33 + 169.343 0.996094 141228 256.00 + 169.983 0.996484 141283 284.44 + 170.623 0.996875 141346 320.00 + 171.519 0.997266 141394 365.71 + 172.287 0.997656 141450 426.67 + 173.055 0.998047 141503 512.00 + 173.439 0.998242 141529 568.89 + 174.079 0.998437 141561 640.00 + 174.463 0.998633 141586 731.43 + 175.103 0.998828 141614 853.33 + 175.743 0.999023 141641 1024.00 + 176.127 0.999121 141657 1137.78 + 176.511 0.999219 141669 1280.00 + 176.895 0.999316 141682 1462.86 + 177.407 0.999414 141699 1706.67 + 177.791 0.999512 141709 2048.00 + 178.303 0.999561 141717 2275.56 + 178.943 0.999609 141725 2560.00 + 179.199 0.999658 141734 2925.71 + 179.327 0.999707 141737 3413.33 + 179.967 0.999756 141746 4096.00 + 180.095 0.999780 141748 4551.11 + 180.223 0.999805 141751 5120.00 + 180.351 0.999829 141755 5851.43 + 180.991 0.999854 141758 6826.67 + 181.503 0.999878 141762 8192.00 + 181.631 0.999890 141764 9102.22 + 181.759 0.999902 141766 10240.00 + 181.759 0.999915 141766 11702.86 + 181.887 0.999927 141768 13653.33 + 182.271 0.999939 141770 16384.00 + 182.655 0.999945 141771 18204.44 + 182.783 0.999951 141772 20480.00 + 182.783 0.999957 141772 23405.71 + 182.911 0.999963 141773 27306.67 + 183.039 0.999969 141774 32768.00 + 183.423 0.999973 141776 36408.89 + 183.423 0.999976 141776 40960.00 + 183.423 0.999979 141776 46811.43 + 183.423 0.999982 141776 54613.33 + 183.423 0.999985 141776 65536.00 + 183.551 0.999986 141777 72817.78 + 183.551 0.999988 141777 81920.00 + 183.551 0.999989 141777 93622.86 + 183.551 0.999991 141777 109226.67 + 183.551 0.999992 141777 131072.00 + 184.063 0.999993 141778 145635.56 + 184.063 1.000000 141778 inf +#[Mean = 68.085, StdDeviation = 40.657] +#[Max = 183.936, Total count = 141778] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 143025 requests in 9.88s, 9.14MB read +Requests/sec: 14478.74 +Transfer/sec: 0.93MB diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get.png b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get.png new file mode 100644 index 000000000..eca738eee Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get.png differ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get_ack2.png b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get_ack2.png new file mode 100644 index 000000000..03af36c9b Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get_ack2.png differ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get_result.txt b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get_result.txt new file mode 100644 index 000000000..7f55f1485 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get_result.txt @@ -0,0 +1,87 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 0.664 0.000000 1 1.00 + 3.191 0.100000 8305 1.11 + 5.719 0.200000 16611 1.25 + 14.503 0.300000 24912 1.43 + 28.143 0.400000 33212 1.67 + 44.607 0.500000 41518 2.00 + 52.511 0.550000 45672 2.22 + 58.911 0.600000 49835 2.50 + 64.319 0.650000 53979 2.86 + 69.375 0.700000 58171 3.33 + 74.239 0.750000 62318 4.00 + 76.799 0.775000 64399 4.44 + 79.167 0.800000 66452 5.00 + 81.791 0.825000 68508 5.71 + 84.671 0.850000 70591 6.67 + 87.487 0.875000 72666 8.00 + 89.087 0.887500 73733 8.89 + 90.623 0.900000 74735 10.00 + 92.351 0.912500 75785 11.43 + 93.951 0.925000 76812 13.33 + 95.935 0.937500 77871 16.00 + 97.023 0.943750 78377 17.78 + 98.239 0.950000 78890 20.00 + 99.583 0.956250 79398 22.86 + 101.247 0.962500 79921 26.67 + 103.039 0.968750 80444 32.00 + 104.063 0.971875 80699 35.56 + 105.151 0.975000 80961 40.00 + 106.431 0.978125 81217 45.71 + 107.967 0.981250 81481 53.33 + 110.079 0.984375 81735 64.00 + 111.487 0.985938 81870 71.11 + 112.639 0.987500 81994 80.00 + 113.791 0.989062 82122 91.43 + 115.135 0.990625 82257 106.67 + 116.287 0.992188 82384 128.00 + 116.991 0.992969 82447 142.22 + 117.695 0.993750 82513 160.00 + 118.399 0.994531 82576 182.86 + 119.487 0.995313 82644 213.33 + 120.767 0.996094 82708 256.00 + 121.343 0.996484 82740 284.44 + 122.111 0.996875 82774 320.00 + 122.751 0.997266 82803 365.71 + 123.711 0.997656 82837 426.67 + 124.671 0.998047 82869 512.00 + 125.503 0.998242 82885 568.89 + 126.399 0.998437 82903 640.00 + 127.167 0.998633 82917 731.43 + 128.063 0.998828 82934 853.33 + 129.343 0.999023 82949 1024.00 + 130.175 0.999121 82958 1137.78 + 131.071 0.999219 82966 1280.00 + 131.711 0.999316 82974 1462.86 + 132.479 0.999414 82982 1706.67 + 133.759 0.999512 82990 2048.00 + 134.271 0.999561 82995 2275.56 + 134.655 0.999609 82998 2560.00 + 135.167 0.999658 83002 2925.71 + 135.679 0.999707 83007 3413.33 + 136.063 0.999756 83010 4096.00 + 136.319 0.999780 83012 4551.11 + 136.447 0.999805 83014 5120.00 + 136.959 0.999829 83016 5851.43 + 137.855 0.999854 83018 6826.67 + 137.983 0.999878 83020 8192.00 + 138.239 0.999890 83023 9102.22 + 138.239 0.999902 83023 10240.00 + 138.239 0.999915 83023 11702.86 + 138.495 0.999927 83024 13653.33 + 139.391 0.999939 83025 16384.00 + 139.775 0.999945 83026 18204.44 + 139.775 0.999951 83026 20480.00 + 140.159 0.999957 83027 23405.71 + 140.159 0.999963 83027 27306.67 + 140.287 0.999969 83028 32768.00 + 140.287 0.999973 83028 36408.89 + 140.287 0.999976 83028 40960.00 + 141.567 0.999979 83029 46811.43 + 141.567 0.999982 83029 54613.33 + 141.567 0.999985 83029 65536.00 + 141.567 0.999986 83029 72817.78 + 141.567 0.999988 83029 81920.00 + 142.975 0.999989 83030 93622.86 + 142.975 1.000000 83030 inf diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get_result_ack2.txt b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get_result_ack2.txt new file mode 100644 index 000000000..49ffb554c --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/get_result_ack2.txt @@ -0,0 +1,90 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 0.410 0.000000 1 1.00 + 33.247 0.100000 13618 1.11 + 68.671 0.200000 27257 1.25 + 79.807 0.300000 40869 1.43 + 87.871 0.400000 54555 1.67 + 95.935 0.500000 68157 2.00 + 100.671 0.550000 74914 2.22 + 106.239 0.600000 81705 2.50 + 112.959 0.650000 88498 2.86 + 119.871 0.700000 95322 3.33 + 126.591 0.750000 102128 4.00 + 129.983 0.775000 105535 4.44 + 133.631 0.800000 108993 5.00 + 137.215 0.825000 112313 5.71 + 141.183 0.850000 115772 6.67 + 145.407 0.875000 119219 8.00 + 147.583 0.887500 120885 8.89 + 150.015 0.900000 122577 10.00 + 152.447 0.912500 124227 11.43 + 155.263 0.925000 125940 13.33 + 158.591 0.937500 127657 16.00 + 160.511 0.943750 128513 17.78 + 162.687 0.950000 129351 20.00 + 164.863 0.956250 130181 22.86 + 167.295 0.962500 131045 26.67 + 170.367 0.968750 131881 32.00 + 172.031 0.971875 132310 35.56 + 173.823 0.975000 132752 40.00 + 175.871 0.978125 133167 45.71 + 178.303 0.981250 133594 53.33 + 181.887 0.984375 134019 64.00 + 183.807 0.985938 134233 71.11 + 185.855 0.987500 134439 80.00 + 187.647 0.989062 134654 91.43 + 189.567 0.990625 134857 106.67 + 191.743 0.992188 135075 128.00 + 193.023 0.992969 135177 142.22 + 194.175 0.993750 135282 160.00 + 195.327 0.994531 135391 182.86 + 197.375 0.995313 135495 213.33 + 199.807 0.996094 135603 256.00 + 201.087 0.996484 135658 284.44 + 202.111 0.996875 135710 320.00 + 203.391 0.997266 135764 365.71 + 204.543 0.997656 135819 426.67 + 205.695 0.998047 135869 512.00 + 206.207 0.998242 135900 568.89 + 207.103 0.998437 135923 640.00 + 207.743 0.998633 135947 731.43 + 208.639 0.998828 135975 853.33 + 209.535 0.999023 136001 1024.00 + 210.047 0.999121 136015 1137.78 + 210.431 0.999219 136029 1280.00 + 210.943 0.999316 136039 1462.86 + 211.583 0.999414 136053 1706.67 + 212.095 0.999512 136067 2048.00 + 212.607 0.999561 136075 2275.56 + 212.863 0.999609 136079 2560.00 + 213.375 0.999658 136086 2925.71 + 213.759 0.999707 136093 3413.33 + 214.399 0.999756 136099 4096.00 + 214.655 0.999780 136105 4551.11 + 214.911 0.999805 136110 5120.00 + 214.911 0.999829 136110 5851.43 + 215.167 0.999854 136113 6826.67 + 215.423 0.999878 136116 8192.00 + 215.551 0.999890 136119 9102.22 + 215.551 0.999902 136119 10240.00 + 215.679 0.999915 136121 11702.86 + 215.935 0.999927 136123 13653.33 + 216.063 0.999939 136125 16384.00 + 216.063 0.999945 136125 18204.44 + 216.319 0.999951 136127 20480.00 + 216.319 0.999957 136127 23405.71 + 216.447 0.999963 136129 27306.67 + 216.447 0.999969 136129 32768.00 + 216.447 0.999973 136129 36408.89 + 216.447 0.999976 136129 40960.00 + 216.703 0.999979 136130 46811.43 + 216.703 0.999982 136130 54613.33 + 216.703 0.999985 136130 65536.00 + 216.831 0.999986 136131 72817.78 + 216.831 0.999988 136131 81920.00 + 216.831 0.999989 136131 93622.86 + 216.831 0.999991 136131 109226.67 + 216.831 0.999992 136131 131072.00 + 217.343 0.999993 136132 145635.56 + 217.343 1.000000 136132 inf \ No newline at end of file diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put.png b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put.png new file mode 100644 index 000000000..f010094e8 Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put.png differ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put_ack2.png b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put_ack2.png new file mode 100644 index 000000000..9563edeca Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put_ack2.png differ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put_result.txt b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put_result.txt new file mode 100644 index 000000000..48c006df1 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put_result.txt @@ -0,0 +1,87 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 0.623 0.000000 1 1.00 + 2.351 0.100000 8234 1.11 + 3.605 0.200000 16462 1.25 + 4.919 0.300000 24698 1.43 + 6.447 0.400000 32938 1.67 + 8.735 0.500000 41162 2.00 + 10.695 0.550000 45272 2.22 + 15.591 0.600000 49376 2.50 + 22.095 0.650000 53493 2.86 + 59.007 0.700000 57613 3.33 + 73.407 0.750000 61732 4.00 + 78.463 0.775000 63788 4.44 + 83.391 0.800000 65841 5.00 + 88.383 0.825000 67895 5.71 + 94.783 0.850000 69952 6.67 + 103.231 0.875000 72007 8.00 + 111.935 0.887500 73040 8.89 + 119.295 0.900000 74067 10.00 + 124.991 0.912500 75093 11.43 + 129.407 0.925000 76133 13.33 + 133.887 0.937500 77181 16.00 + 136.191 0.943750 77668 17.78 + 138.623 0.950000 78181 20.00 + 141.439 0.956250 78707 22.86 + 144.255 0.962500 79208 26.67 + 147.199 0.968750 79727 32.00 + 148.991 0.971875 79979 35.56 + 150.911 0.975000 80247 40.00 + 153.087 0.978125 80501 45.71 + 155.519 0.981250 80764 53.33 + 157.695 0.984375 81011 64.00 + 158.975 0.985938 81144 71.11 + 160.383 0.987500 81275 80.00 + 161.663 0.989062 81401 91.43 + 163.455 0.990625 81536 106.67 + 165.631 0.992188 81658 128.00 + 166.911 0.992969 81722 142.22 + 168.319 0.993750 81780 160.00 + 169.855 0.994531 81843 182.86 + 171.391 0.995313 81911 213.33 + 172.927 0.996094 81973 256.00 + 173.567 0.996484 82006 284.44 + 174.079 0.996875 82038 320.00 + 174.591 0.997266 82073 365.71 + 175.487 0.997656 82110 426.67 + 176.127 0.998047 82140 512.00 + 176.511 0.998242 82155 568.89 + 177.023 0.998437 82166 640.00 + 177.663 0.998633 82187 731.43 + 178.047 0.998828 82201 853.33 + 178.559 0.999023 82216 1024.00 + 178.815 0.999121 82221 1137.78 + 179.327 0.999219 82230 1280.00 + 179.839 0.999316 82237 1462.86 + 180.735 0.999414 82246 1706.67 + 181.503 0.999512 82253 2048.00 + 182.143 0.999561 82259 2275.56 + 182.783 0.999609 82261 2560.00 + 183.423 0.999658 82265 2925.71 + 184.063 0.999707 82270 3413.33 + 184.447 0.999756 82273 4096.00 + 184.959 0.999780 82275 4551.11 + 185.087 0.999805 82277 5120.00 + 185.215 0.999829 82279 5851.43 + 185.855 0.999854 82282 6826.67 + 186.495 0.999878 82283 8192.00 + 187.263 0.999890 82284 9102.22 + 187.391 0.999902 82285 10240.00 + 187.519 0.999915 82286 11702.86 + 187.647 0.999927 82287 13653.33 + 188.159 0.999939 82288 16384.00 + 188.799 0.999945 82289 18204.44 + 188.799 0.999951 82289 20480.00 + 188.927 0.999957 82290 23405.71 + 188.927 0.999963 82290 27306.67 + 189.183 0.999969 82291 32768.00 + 189.183 0.999973 82291 36408.89 + 189.183 0.999976 82291 40960.00 + 190.079 0.999979 82292 46811.43 + 190.079 0.999982 82292 54613.33 + 190.079 0.999985 82292 65536.00 + 190.079 0.999986 82292 72817.78 + 190.079 0.999988 82292 81920.00 + 190.463 0.999989 82293 93622.86 + 190.463 1.000000 82293 inf diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put_result_ack2.txt b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put_result_ack2.txt new file mode 100644 index 000000000..9123c128e --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab4/wrk_result/put_result_ack2.txt @@ -0,0 +1,90 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 0.405 0.000000 1 1.00 + 16.943 0.100000 14186 1.11 + 29.231 0.200000 28361 1.25 + 40.927 0.300000 42547 1.43 + 53.343 0.400000 56736 1.67 + 66.047 0.500000 70967 2.00 + 72.191 0.550000 78066 2.22 + 77.823 0.600000 85128 2.50 + 83.839 0.650000 92211 2.86 + 89.535 0.700000 99264 3.33 + 95.295 0.750000 106380 4.00 + 98.687 0.775000 109914 4.44 + 102.655 0.800000 113450 5.00 + 107.199 0.825000 117012 5.71 + 112.127 0.850000 120524 6.67 + 117.887 0.875000 124081 8.00 + 121.023 0.887500 125835 8.89 + 124.735 0.900000 127615 10.00 + 128.703 0.912500 129398 11.43 + 132.863 0.925000 131152 13.33 + 137.983 0.937500 132921 16.00 + 140.927 0.943750 133813 17.78 + 143.743 0.950000 134702 20.00 + 146.431 0.956250 135581 22.86 + 149.247 0.962500 136502 26.67 + 151.935 0.968750 137375 32.00 + 153.343 0.971875 137791 35.56 + 154.879 0.975000 138253 40.00 + 156.415 0.978125 138702 45.71 + 158.079 0.981250 139154 53.33 + 159.743 0.984375 139566 64.00 + 160.639 0.985938 139790 71.11 + 161.663 0.987500 140032 80.00 + 162.687 0.989062 140244 91.43 + 163.711 0.990625 140451 106.67 + 164.991 0.992188 140680 128.00 + 165.631 0.992969 140783 142.22 + 166.399 0.993750 140907 160.00 + 167.167 0.994531 141012 182.86 + 168.191 0.995313 141119 213.33 + 169.343 0.996094 141228 256.00 + 169.983 0.996484 141283 284.44 + 170.623 0.996875 141346 320.00 + 171.519 0.997266 141394 365.71 + 172.287 0.997656 141450 426.67 + 173.055 0.998047 141503 512.00 + 173.439 0.998242 141529 568.89 + 174.079 0.998437 141561 640.00 + 174.463 0.998633 141586 731.43 + 175.103 0.998828 141614 853.33 + 175.743 0.999023 141641 1024.00 + 176.127 0.999121 141657 1137.78 + 176.511 0.999219 141669 1280.00 + 176.895 0.999316 141682 1462.86 + 177.407 0.999414 141699 1706.67 + 177.791 0.999512 141709 2048.00 + 178.303 0.999561 141717 2275.56 + 178.943 0.999609 141725 2560.00 + 179.199 0.999658 141734 2925.71 + 179.327 0.999707 141737 3413.33 + 179.967 0.999756 141746 4096.00 + 180.095 0.999780 141748 4551.11 + 180.223 0.999805 141751 5120.00 + 180.351 0.999829 141755 5851.43 + 180.991 0.999854 141758 6826.67 + 181.503 0.999878 141762 8192.00 + 181.631 0.999890 141764 9102.22 + 181.759 0.999902 141766 10240.00 + 181.759 0.999915 141766 11702.86 + 181.887 0.999927 141768 13653.33 + 182.271 0.999939 141770 16384.00 + 182.655 0.999945 141771 18204.44 + 182.783 0.999951 141772 20480.00 + 182.783 0.999957 141772 23405.71 + 182.911 0.999963 141773 27306.67 + 183.039 0.999969 141774 32768.00 + 183.423 0.999973 141776 36408.89 + 183.423 0.999976 141776 40960.00 + 183.423 0.999979 141776 46811.43 + 183.423 0.999982 141776 54613.33 + 183.423 0.999985 141776 65536.00 + 183.551 0.999986 141777 72817.78 + 183.551 0.999988 141777 81920.00 + 183.551 0.999989 141777 93622.86 + 183.551 0.999991 141777 109226.67 + 183.551 0.999992 141777 131072.00 + 184.063 0.999993 141778 145635.56 + 184.063 1.000000 141778 inf \ No newline at end of file diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/async_profiler_result/get.jfr b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/async_profiler_result/get.jfr new file mode 100644 index 000000000..86ed4110b Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/async_profiler_result/get.jfr differ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/async_profiler_result/put.jfr b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/async_profiler_result/put.jfr new file mode 100644 index 000000000..729f25adf Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/async_profiler_result/put.jfr differ diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/scripts/fill.lua b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/scripts/fill.lua new file mode 100644 index 000000000..8e33ede77 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/scripts/fill.lua @@ -0,0 +1,20 @@ +local random = require("math").random +local char = require("string").char + +local function randomString(n) + local result = {} + for i = 1, n do + result[i] = char(random(33, 126)) -- ASCII символы с 33 по 126 + end + return table.concat(result) +end + +counter = 0 +function request() + counter = counter + 1 + local headers = {} + headers["Host"] = "localhost:8080" + local key = "key" .. counter + local value = "value$" .. randomString(100) + return wrk.format("PUT", "/v0/entity?id=" .. key .. "&ack=2&from=3", headers, value) +end \ No newline at end of file diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/scripts/get.lua b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/scripts/get.lua new file mode 100644 index 000000000..0dd0303ac --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/scripts/get.lua @@ -0,0 +1,7 @@ +function request() + local headers = {} + headers["Host"] = "localhost:8080" + local id = math.random(1, 10000) + local key = "key" .. id + return wrk.format("GET", "/v0/entity?id=" .. key .. "&ack=3&from=3", headers) +end \ No newline at end of file diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/wrk_result/get_result.txt b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/wrk_result/get_result.txt new file mode 100644 index 000000000..300e4d803 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/wrk_result/get_result.txt @@ -0,0 +1,91 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 0.474 0.000000 1 1.00 + 1.630 0.100000 15521 1.11 + 2.053 0.200000 31043 1.25 + 2.533 0.300000 46522 1.43 + 3.331 0.400000 61977 1.67 + 4.647 0.500000 77489 2.00 + 5.531 0.550000 85208 2.22 + 6.627 0.600000 92971 2.50 + 7.955 0.650000 100699 2.86 + 9.487 0.700000 108449 3.33 + 11.303 0.750000 116216 4.00 + 12.351 0.775000 120070 4.44 + 13.567 0.800000 123937 5.00 + 14.967 0.825000 127809 5.71 + 16.671 0.850000 131707 6.67 + 18.671 0.875000 135568 8.00 + 19.791 0.887500 137500 8.89 + 20.991 0.900000 139427 10.00 + 22.319 0.912500 141371 11.43 + 23.807 0.925000 143309 13.33 + 25.487 0.937500 145239 16.00 + 26.447 0.943750 146204 17.78 + 27.535 0.950000 147185 20.00 + 28.639 0.956250 148144 22.86 + 29.935 0.962500 149113 26.67 + 31.375 0.968750 150078 32.00 + 32.159 0.971875 150561 35.56 + 33.119 0.975000 151058 40.00 + 34.175 0.978125 151540 45.71 + 35.295 0.981250 152020 53.33 + 36.575 0.984375 152510 64.00 + 37.279 0.985938 152753 71.11 + 38.015 0.987500 152989 80.00 + 39.007 0.989062 153231 91.43 + 40.063 0.990625 153469 106.67 + 41.279 0.992188 153712 128.00 + 41.983 0.992969 153833 142.22 + 42.847 0.993750 153953 160.00 + 43.679 0.994531 154074 182.86 + 44.767 0.995313 154197 213.33 + 45.919 0.996094 154315 256.00 + 46.495 0.996484 154374 284.44 + 47.103 0.996875 154438 320.00 + 47.711 0.997266 154495 365.71 + 48.447 0.997656 154555 426.67 + 49.311 0.998047 154618 512.00 + 49.663 0.998242 154648 568.89 + 50.239 0.998437 154678 640.00 + 50.815 0.998633 154707 731.43 + 51.615 0.998828 154738 853.33 + 52.479 0.999023 154767 1024.00 + 52.863 0.999121 154783 1137.78 + 53.215 0.999219 154799 1280.00 + 53.759 0.999316 154814 1462.86 + 54.335 0.999414 154828 1706.67 + 55.135 0.999512 154844 2048.00 + 55.231 0.999561 154850 2275.56 + 55.551 0.999609 154858 2560.00 + 56.191 0.999658 154866 2925.71 + 56.895 0.999707 154873 3413.33 + 57.695 0.999756 154881 4096.00 + 57.759 0.999780 154884 4551.11 + 58.079 0.999805 154888 5120.00 + 58.815 0.999829 154892 5851.43 + 59.423 0.999854 154896 6826.67 + 59.903 0.999878 154900 8192.00 + 60.095 0.999890 154902 9102.22 + 60.223 0.999902 154904 10240.00 + 60.255 0.999915 154905 11702.86 + 60.799 0.999927 154908 13653.33 + 60.863 0.999939 154909 16384.00 + 60.991 0.999945 154910 18204.44 + 61.279 0.999951 154911 20480.00 + 61.567 0.999957 154912 23405.71 + 62.111 0.999963 154913 27306.67 + 62.239 0.999969 154914 32768.00 + 62.239 0.999973 154914 36408.89 + 62.367 0.999976 154915 40960.00 + 62.367 0.999979 154915 46811.43 + 62.751 0.999982 154916 54613.33 + 62.751 0.999985 154916 65536.00 + 62.751 0.999986 154916 72817.78 + 63.391 0.999988 154917 81920.00 + 63.391 0.999989 154917 93622.86 + 63.391 0.999991 154917 109226.67 + 63.391 0.999992 154917 131072.00 + 63.391 0.999993 154917 145635.56 + 63.743 0.999994 154918 163840.00 + 63.743 1.000000 154918 inf diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/wrk_result/put_result.txt b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/wrk_result/put_result.txt new file mode 100644 index 000000000..6241de4f4 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/lab5/wrk_result/put_result.txt @@ -0,0 +1,98 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 0.103 0.000000 1 1.00 + 1.050 0.100000 79953 1.11 + 1.683 0.200000 159758 1.25 + 3.405 0.300000 239697 1.43 + 6.191 0.400000 319526 1.67 + 9.935 0.500000 399356 2.00 + 12.471 0.550000 439360 2.22 + 15.407 0.600000 479217 2.50 + 17.967 0.650000 519173 2.86 + 20.655 0.700000 559092 3.33 + 23.615 0.750000 599092 4.00 + 25.407 0.775000 619128 4.44 + 27.359 0.800000 638947 5.00 + 30.143 0.825000 658938 5.71 + 33.919 0.850000 678924 6.67 + 38.559 0.875000 698878 8.00 + 41.919 0.887500 708888 8.89 + 46.143 0.900000 718869 10.00 + 52.191 0.912500 728831 11.43 + 58.815 0.925000 738798 13.33 + 63.999 0.937500 748792 16.00 + 66.431 0.943750 753845 17.78 + 68.735 0.950000 758905 20.00 + 70.783 0.956250 763746 22.86 + 72.703 0.962500 768774 26.67 + 74.559 0.968750 773784 32.00 + 75.519 0.971875 776324 35.56 + 76.415 0.975000 778725 40.00 + 77.439 0.978125 781342 45.71 + 78.527 0.981250 783755 53.33 + 79.807 0.984375 786203 64.00 + 80.511 0.985938 787485 71.11 + 81.343 0.987500 788705 80.00 + 82.303 0.989062 789969 91.43 + 83.391 0.990625 791257 106.67 + 84.479 0.992188 792456 128.00 + 85.119 0.992969 793084 142.22 + 85.759 0.993750 793698 160.00 + 86.463 0.994531 794315 182.86 + 87.231 0.995313 794964 213.33 + 88.063 0.996094 795578 256.00 + 88.575 0.996484 795899 284.44 + 89.023 0.996875 796185 320.00 + 89.599 0.997266 796503 365.71 + 90.239 0.997656 796813 426.67 + 90.943 0.998047 797125 512.00 + 91.391 0.998242 797269 568.89 + 91.967 0.998437 797442 640.00 + 92.607 0.998633 797583 731.43 + 93.375 0.998828 797747 853.33 + 94.207 0.999023 797898 1024.00 + 94.655 0.999121 797983 1137.78 + 95.103 0.999219 798054 1280.00 + 95.615 0.999316 798134 1462.86 + 96.127 0.999414 798209 1706.67 + 96.959 0.999512 798285 2048.00 + 97.471 0.999561 798325 2275.56 + 98.047 0.999609 798363 2560.00 + 98.687 0.999658 798401 2925.71 + 99.327 0.999707 798439 3413.33 + 100.031 0.999756 798480 4096.00 + 100.351 0.999780 798500 4551.11 + 100.671 0.999805 798519 5120.00 + 101.119 0.999829 798538 5851.43 + 101.567 0.999854 798558 6826.67 + 102.015 0.999878 798577 8192.00 + 102.271 0.999890 798586 9102.22 + 102.719 0.999902 798597 10240.00 + 103.167 0.999915 798607 11702.86 + 103.423 0.999927 798615 13653.33 + 103.743 0.999939 798625 16384.00 + 103.935 0.999945 798629 18204.44 + 104.127 0.999951 798634 20480.00 + 104.319 0.999957 798639 23405.71 + 104.575 0.999963 798644 27306.67 + 104.767 0.999969 798648 32768.00 + 105.151 0.999973 798651 36408.89 + 105.215 0.999976 798653 40960.00 + 105.343 0.999979 798657 46811.43 + 105.407 0.999982 798658 54613.33 + 105.599 0.999985 798661 65536.00 + 105.855 0.999986 798662 72817.78 + 105.919 0.999988 798664 81920.00 + 105.919 0.999989 798664 93622.86 + 106.111 0.999991 798666 109226.67 + 106.111 0.999992 798666 131072.00 + 106.559 0.999993 798667 145635.56 + 106.943 0.999994 798668 163840.00 + 106.943 0.999995 798668 187245.71 + 107.071 0.999995 798669 218453.33 + 107.071 0.999996 798669 262144.00 + 107.647 0.999997 798670 291271.11 + 107.647 0.999997 798670 327680.00 + 107.647 0.999997 798670 374491.43 + 107.775 0.999998 798672 436906.67 + 107.775 1.000000 798672 inf \ No newline at end of file diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/results/stage4.md b/src/main/java/ru/vk/itmo/test/georgiidalbeev/results/stage4.md new file mode 100644 index 000000000..4b365775e --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/results/stage4.md @@ -0,0 +1,57 @@ +## Производительность + +- **PUT Запросы:** + + | Запрос | lab3 | lab4 ack2 | lab4 ack3 | + |--------|---------|-----------|-----------| + | rps | 35000 | 14500 | 9750 | + | avg | 15.85ms | 68.08ms | 37.12ms | + | Stdev | 29.97ms | 40.66ms | 47.28ms | + + Произошло снижение производительности примерно в `2.5` раза для `ack = 2` и `3.5` раза для `ack = 3`. + + - `ack = 2` +![put_ack2.png](..%2Flab4%2Fwrk_result%2Fput_ack2.png) + - `ack = 3` +![put.png](..%2Flab4%2Fwrk_result%2Fput.png) + + +- **GET Запросы:** + + | Запрос | lab3 | lab4 ack2 | lab4 ack3 | + |--------|---------|-----------|-----------| + | rps | 40000 | 14500 | 9500 | + | avg | 17.40ms | 96.85ms | 44.91ms | + | Stdev | 20.24ms | 42.12ms | 33.99ms | + + Произошло снижение производительности примерно в `2.75` раза для `ack = 2` и `4` раза для `ack = 3`. + + - `ack = 2` +![get_ack2.png](..%2Flab4%2Fwrk_result%2Fget_ack2.png) + - `ack = 3` +![get.png](..%2Flab4%2Fwrk_result%2Fget.png) + + +## Причины Деградации Производительности + +Снижение производительности происходит из-за необходимости ожидания ответа не только от одного, а сразу от кворума узлов. +Это приводит к последовательному ожиданию ответов от нескольких узлов, что замедляет обработку запросов. + +## Результат профилирования + +- **PUT Запросы:** + - Время на отправку ответов клиенту и ожидание ответов от проксируемых узлов осталось на прежнем уровне. + - Объем работы в воркерах увеличился, особенно заметно на `ThreadPoolExecutor.runWorker`. +- **GET Запросы:** + - Заметно увеличение работы в воркерах, особенно на этапе `Server.processRequest`, где происходит параллельное ожидание +ответов от кворума узлов. + +## Выводы +При использовании значений ack = 3 и from = 3, произошло существенное снижение производительности системы. +Это связано с необходимостью ожидания ответа не только от одного, а сразу от кворума узлов. Это приводит +к увеличению времени обработки запросов из-за последовательного ожидания ответов от нескольких узлов. +Но для придания системе отказоустойчивости, приходится жертвовать быстродействием. При неполадках с одним или несколькими узлами, +данные остаются доступными, если количество активных узлов превышает или равно значению from - ack + 1. В данном случае +оптимальными значениями будут являться ack = 2 и from = 3, позволяя восстановить данные в случае неполадок с одним из узлов +и увеличить показатель rps. + diff --git a/src/main/java/ru/vk/itmo/test/georgiidalbeev/results/stage5.md b/src/main/java/ru/vk/itmo/test/georgiidalbeev/results/stage5.md new file mode 100644 index 000000000..c9fa6b0a8 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/georgiidalbeev/results/stage5.md @@ -0,0 +1,47 @@ +## Производительность + +- **PUT Запросы:** + + | Запрос | lab3 | lab4 | lab5 | + |--------|---------|---------|---------| + | rps | 35000 | 14500 | 17000 | + | avg | 15.85ms | 68.08ms | 45.28ms | + | Stdev | 29.97ms | 40.66ms | 33.32ms | + + Произошло снижение производительности примерно на `~17%` и уменьшение задержки на `~30%`. + +- **GET Запросы:** + + | Запрос | lab3 | lab4 | lab5 | + |--------|---------|---------|---------| + | rps | 40000 | 14500 | 18000 | + | avg | 17.40ms | 96.85ms | 63.81ms | + | Stdev | 20.24ms | 42.12ms | 34.65ms | + + Произошло снижение производительности примерно на `~24%` и уменьшение задержки на `~30%`. + +## Профилирование + +### PUT + +В процессе профилирования были обнаружены следующие изменения: +- **CPU**: Класс `CompletableFuture` занимает `~15%` от общего времени CPU. Это связано с тем, что запросы теперь + обрабатываются асинхронно. +- **ALLOC**: `CompletableFuture` занимает `~33%` от общего объема выделенной памяти. Это связано с созданием новых + экземпляров `CompletableFuture` для каждого асинхронного запроса. +- **LOCK**: `~37%` времени занимают операции с блокировками, связанные с обработкой `CompletableFuture`. + +### GET + +Аналогичные изменения наблюдаются и при обработке GET запросов: +- **CPU**: В процессе выполнения запросов появился новый класс `CompletableFuture`, который занимает `~12%` от общего +времени CPU. Это связано с тем, что теперь запросы обрабатываются асинхронно. +- **ALLOC**: Класс `CompletableFuture` также заметно влияет на распределение памяти. Он занимает `~28%` от общего объема +выделенной памяти. +- **LOCK**: `~30%` времени занимают операции с блокировками, связанные с обработкой `CompletableFuture`. + +## Выводы + +При использовании `CompletableFuture` для асинхронной обработки запросов, мы смогли добиться некоторого увеличения +производительности. Это связано с тем, что запросы теперь обрабатываются +параллельно, и клиент не должен ждать завершения всех запросов, что приводит к уменьшению задержки. \ No newline at end of file