diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/ServerImplementation.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/ServerImplementation.java new file mode 100644 index 000000000..16da3c31e --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/ServerImplementation.java @@ -0,0 +1,109 @@ +package ru.vk.itmo.test.tyapuevdmitrij; + +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 ru.vk.itmo.ServiceConfig; +import ru.vk.itmo.dao.BaseEntry; +import ru.vk.itmo.dao.Config; +import ru.vk.itmo.dao.Entry; +import ru.vk.itmo.test.tyapuevdmitrij.dao.DAOException; +import ru.vk.itmo.test.tyapuevdmitrij.dao.MemorySegmentDao; + +import java.io.IOException; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.nio.charset.StandardCharsets; + +public class ServerImplementation extends HttpServer { + + private final MemorySegmentDao memorySegmentDao; + + private static final String ENTITY_PATH = "/v0/entity"; + private static final long FLUSH_THRESHOLD_BYTES = 1 << 20; // 1 MB + + public ServerImplementation(ServiceConfig config) throws IOException { + super(createServerConfig(config)); + memorySegmentDao = new MemorySegmentDao(new Config(config.workingDir(), FLUSH_THRESHOLD_BYTES)); + } + + private static HttpServerConfig createServerConfig(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("/v0/status") + public Response status() { + return Response.ok("OK"); + } + + @Path(ENTITY_PATH) + @RequestMethod(Request.METHOD_GET) + public Response get(@Param(value = "id", required = true) String id) { + if (id == null || id.isEmpty()) { + return new Response(Response.BAD_REQUEST, Response.EMPTY); + } + MemorySegment key = MemorySegment.ofArray(id.getBytes(StandardCharsets.UTF_8)); + Entry entry = memorySegmentDao.get(key); + if (entry == null) { + return new Response(Response.NOT_FOUND, Response.EMPTY); + } + return Response.ok(entry.value().toArray(ValueLayout.JAVA_BYTE)); + } + + @Path(ENTITY_PATH) + @RequestMethod(Request.METHOD_PUT) + public Response put(@Param(value = "id", required = true) String id, Request request) { + if (id == null || id.isEmpty()) { + return new Response(Response.BAD_REQUEST, Response.EMPTY); + } + Entry entry = new BaseEntry<>(MemorySegment.ofArray(id.getBytes(StandardCharsets.UTF_8)), + MemorySegment.ofArray(request.getBody())); + memorySegmentDao.upsert(entry); + return new Response(Response.CREATED, Response.EMPTY); + } + + @Path(ENTITY_PATH) + @RequestMethod(Request.METHOD_DELETE) + public Response delete(@Param(value = "id", required = true) String id) { + if (id == null || id.isEmpty()) { + return new Response(Response.BAD_REQUEST, Response.EMPTY); + } + Entry entry = new BaseEntry<>(MemorySegment.ofArray(id.getBytes(StandardCharsets.UTF_8)), null); + memorySegmentDao.upsert(entry); + return new Response(Response.ACCEPTED, Response.EMPTY); + } + + public void closeDAO() { + try { + memorySegmentDao.close(); + } catch (IOException e) { + throw new DAOException("can't close DAO", e); + } + } + + @Override + public void handleDefault(Request request, HttpSession session) throws IOException { + Response response = new Response(Response.BAD_REQUEST, Response.EMPTY); + session.sendResponse(response); + } + + @Path(ENTITY_PATH) + public Response unsupportedMethods() { + return new Response(Response.METHOD_NOT_ALLOWED, Response.EMPTY); + } + +} + + diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/ServerStarter.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/ServerStarter.java new file mode 100644 index 000000000..fc227c444 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/ServerStarter.java @@ -0,0 +1,22 @@ +package ru.vk.itmo.test.tyapuevdmitrij; + +import ru.vk.itmo.ServiceConfig; + +import java.io.IOException; +import java.nio.file.Files; +import java.util.List; + +public final class ServerStarter { + + private ServerStarter() { + + } + + public static void main(String[] args) throws IOException { + ServerImplementation server = new ServerImplementation(new ServiceConfig(8080, + "http://localhost", + List.of("http://localhost"), + Files.createTempDirectory("DaoServer"))); + server.start(); + } +} diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/ServiceImplementation.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/ServiceImplementation.java new file mode 100644 index 000000000..dfdcd1c89 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/ServiceImplementation.java @@ -0,0 +1,45 @@ +package ru.vk.itmo.test.tyapuevdmitrij; + +import ru.vk.itmo.ServiceConfig; +import ru.vk.itmo.test.ServiceFactory; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.concurrent.CompletableFuture; + +public class ServiceImplementation implements ru.vk.itmo.Service { + + private ServerImplementation server; + private final ServiceConfig config; + + public ServiceImplementation(ServiceConfig config) { + this.config = config; + } + + @Override + public CompletableFuture start() throws IOException { + try { + server = new ServerImplementation(config); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + server.start(); + return CompletableFuture.completedFuture(null); + } + + @Override + public CompletableFuture stop() throws IOException { + server.stop(); + server.closeDAO(); + return CompletableFuture.completedFuture(null); + } + + @ServiceFactory(stage = 1) + public static class Factory implements ServiceFactory.Factory { + + @Override + public ru.vk.itmo.Service create(ServiceConfig config) { + return new ServiceImplementation(config); + } + } +} diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/DAOException.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/DAOException.java new file mode 100644 index 000000000..aeb05554e --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/DAOException.java @@ -0,0 +1,11 @@ +package ru.vk.itmo.test.tyapuevdmitrij.dao; + +public class DAOException extends RuntimeException { + public DAOException(String message, Throwable cause) { + super(message, cause); + } + + public DAOException(String message) { + super(message); + } +} diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/MemorySegmentComparator.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/MemorySegmentComparator.java new file mode 100644 index 000000000..8c53fc8a5 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/MemorySegmentComparator.java @@ -0,0 +1,28 @@ +package ru.vk.itmo.test.tyapuevdmitrij.dao; + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.util.Comparator; + +public final class MemorySegmentComparator { + private MemorySegmentComparator() { + throw new IllegalStateException("Utility class"); + } + + static Comparator getMemorySegmentComparator() { + return (segment1, segment2) -> { + long offset = segment1.mismatch(segment2); + if (offset == -1) { + return 0; + } + if (offset == segment1.byteSize()) { + return -1; + } + if (offset == segment2.byteSize()) { + return 1; + } + return segment1.get(ValueLayout.JAVA_BYTE, offset) - segment2.get(ValueLayout.JAVA_BYTE, offset); + }; + } +} + diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/MemorySegmentDao.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/MemorySegmentDao.java new file mode 100644 index 000000000..077351ff0 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/MemorySegmentDao.java @@ -0,0 +1,234 @@ +package ru.vk.itmo.test.tyapuevdmitrij.dao; + +import ru.vk.itmo.dao.Config; +import ru.vk.itmo.dao.Dao; +import ru.vk.itmo.dao.Entry; + +import java.io.IOException; +import java.lang.foreign.MemorySegment; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.NavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class MemorySegmentDao implements Dao> { + private final Path ssTablePath; + private final Config config; + private State state; + private final ExecutorService flusher = + Executors.newSingleThreadExecutor(r -> { + final Thread result = new Thread(r); + result.setName("flusher"); + return result; + }); + private final ExecutorService compactor = + Executors.newSingleThreadExecutor(r -> { + final Thread result = new Thread(r); + result.setName("compactor"); + return result; + }); + private final ReadWriteLock upsertLock = new ReentrantReadWriteLock(); + AtomicBoolean closed = new AtomicBoolean(); + + public MemorySegmentDao(Config config) { + ssTablePath = config.basePath(); + state = new State(new ConcurrentSkipListMap<>(MemorySegmentComparator.getMemorySegmentComparator()), + null, new AtomicLong(), + new Storage(ssTablePath)); + this.config = config; + } + + @Override + public Iterator> get(MemorySegment from, MemorySegment to) { + State currentState = this.state; + List>> iterators = new ArrayList<>(); + iterators.add(getMemTableIterator(from, to, currentState.flushMemTable)); + iterators.add(getMemTableIterator(from, to, currentState.memTable)); + if (currentState.storage.ssTablesQuantity == 0) { + return new MergeIterator(iterators, Comparator.comparing(Entry::key, + MemorySegmentComparator.getMemorySegmentComparator())); + } else { + return currentState.storage.range(iterators.get(0), + iterators.get(1), + from, + to, + MemorySegmentComparator.getMemorySegmentComparator()); + } + } + + private Iterator> getMemTableIterator(MemorySegment from, MemorySegment to, + NavigableMap> memTable) { + if (memTable == null) { + return Collections.emptyIterator(); + } + if (from == null && to == null) { + return memTable.values().iterator(); + } + if (from == null) { + return memTable.headMap(to).values().iterator(); + } + if (to == null) { + return memTable.tailMap(from).values().iterator(); + } + return memTable.subMap(from, to).values().iterator(); + } + + @Override + public Entry get(MemorySegment key) { + State currentState = this.state; + Entry value = currentState.memTable.get(key); + if (value != null && value.value() == null) { + return null; + } + if (value == null && currentState.flushMemTable != null) { + value = currentState.flushMemTable.get(key); + } + if (value != null && value.value() == null) { + return null; + } + if (value != null || currentState.storage.ssTables == null) { + return value; + } + Iterator> iterator = currentState.storage.range(Collections.emptyIterator(), + Collections.emptyIterator(), + key, + null, + MemorySegmentComparator.getMemorySegmentComparator()); + + if (!iterator.hasNext()) { + return null; + } + Entry next = iterator.next(); + if (MemorySegmentComparator.getMemorySegmentComparator().compare(next.key(), key) == 0) { + return next; + } + return null; + } + + @Override + public void upsert(Entry entry) { + final boolean autoFlush; + upsertLock.readLock().lock(); + try { + if (state.memoryUsage.get() > config.flushThresholdBytes() + && state.flushMemTable != null) { + throw new IllegalStateException("Can't keep up with flushing!"); + } + + // Upsert + final Entry previous = state.memTable.put(entry.key(), entry); + + // Update size estimate + final long size = state.memoryUsage.addAndGet(StorageHelper.sizeOf(entry) - StorageHelper.sizeOf(previous)); + autoFlush = size > config.flushThresholdBytes(); + } finally { + upsertLock.readLock().unlock(); + } + + if (autoFlush) { + flushing(true); + } + } + + @Override + public void flush() throws IOException { + flushing(false); + } + + public void flushing(final boolean auto) { + flusher.submit(() -> { + final State currentState; + upsertLock.writeLock().lock(); + try { + if (this.state.memTable.isEmpty()) { + // Nothing to flush + return; + } + + if (auto && this.state.memoryUsage.get() < config.flushThresholdBytes()) { + // Not enough data to flush + return; + } + + // Switch memTable to flushing + currentState = this.state.prepareToFlash(); + this.state = currentState; + } finally { + upsertLock.writeLock().unlock(); + } + int ssTablesQuantity = state.storage.ssTablesQuantity; + // Write + try { + state.storage.save(state.flushMemTable.values(), ssTablePath, state.storage); + } catch (IOException e) { + Runtime.getRuntime().halt(-1); + return; + } + + // Open + final MemorySegment flushed; + Path flushedPath = ssTablePath.resolve(StorageHelper.SS_TABLE_FILE_NAME + ssTablesQuantity); + flushed = NmapBuffer.getReadBufferFromSsTable(flushedPath, state.storage.readArena); + + // Switch + upsertLock.writeLock().lock(); + try { + this.state = this.state.afterFLush(flushed); + } finally { + upsertLock.writeLock().unlock(); + } + }).state(); + } + + @Override + public void compact() throws IOException { + State currentState = this.state; + if (currentState.storage.ssTablesQuantity <= 1) { + return; + } + Future submit = compactor.submit(() -> { + State stateNow = this.state; + if (!currentState.storage.readArena.scope().isAlive()) { + return; + } + stateNow.storage.storageHelper.saveDataForCompaction(stateNow, ssTablePath); + stateNow.storage.storageHelper.deleteOldSsTables(ssTablePath); + stateNow.storage.storageHelper.renameCompactedSsTable(ssTablePath); + Storage load = new Storage(ssTablePath); + upsertLock.writeLock().lock(); + try { + this.state = new State(this.state.memTable, this.state.flushMemTable, state.memoryUsage, load); + } finally { + upsertLock.writeLock().unlock(); + } + }); + if (submit.isCancelled()) { + throw new DAOException("compact error"); + } + } + + @Override + public synchronized void close() throws IOException { + if (closed.getAndSet(true)) { + return; + } + flush(); + flusher.close(); + compactor.close(); + + // Close arena + state.storage.readArena.close(); + } +} diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/MergeIterator.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/MergeIterator.java new file mode 100644 index 000000000..3ad5e2e09 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/MergeIterator.java @@ -0,0 +1,145 @@ +package ru.vk.itmo.test.tyapuevdmitrij.dao; + +import ru.vk.itmo.dao.Entry; + +import java.lang.foreign.MemorySegment; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.PriorityQueue; + +public class MergeIterator implements Iterator> { + + private final PriorityQueue priorityQueue; + private final Comparator> comparator; + PeekIterator tableIterator; + + private static class PeekIterator implements Iterator> { + + public final int id; + private final Iterator> delegate; + private Entry memorySegmentsEntry; + + private PeekIterator(int id, Iterator> delegate) { + this.id = id; + this.delegate = delegate; + } + + @Override + public boolean hasNext() { + if (memorySegmentsEntry == null) { + return delegate.hasNext(); + } + return true; + } + + @Override + public Entry next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + Entry peek = peek(); + this.memorySegmentsEntry = null; + return peek; + } + + private Entry peek() { + if (memorySegmentsEntry == null) { + if (!delegate.hasNext()) { + return null; + } + memorySegmentsEntry = delegate.next(); + } + return memorySegmentsEntry; + } + } + + public MergeIterator(Collection>> iterators, + Comparator> comparator) { + this.comparator = comparator; + Comparator peekComp = (o1, o2) -> comparator.compare(o1.peek(), o2.peek()); + priorityQueue = new PriorityQueue<>( + iterators.size(), + peekComp.thenComparing(o -> -o.id) + ); + + int id = 0; + for (Iterator> iterator : iterators) { + if (iterator.hasNext()) { + priorityQueue.add(new PeekIterator(id++, iterator)); + } + } + } + + private PeekIterator peek() { + while (tableIterator == null) { + tableIterator = priorityQueue.poll(); + if (tableIterator == null) { + return null; + } + peekFromPriorityQueue(); + if (tableIterator.peek() == null) { + tableIterator = null; + continue; + } + + if (skip(tableIterator.peek())) { + tableIterator.next(); + if (tableIterator.hasNext()) { + priorityQueue.add(tableIterator); + } + tableIterator = null; + } + } + + return tableIterator; + } + + private void peekFromPriorityQueue() { + while (true) { + PeekIterator next = priorityQueue.peek(); + if (next == null) { + break; + } + int compare = comparator.compare(tableIterator.peek(), next.peek()); + if (compare == 0) { + PeekIterator poll = priorityQueue.poll(); + if (poll != null) { + poll.next(); + if (poll.hasNext()) { + priorityQueue.add(poll); + } + } + } else { + break; + } + } + } + + protected boolean skip(Entry entry) { + if (entry != null) { + return entry.value() == null; + } + return false; + } + + @Override + public boolean hasNext() { + return peek() != null; + } + + @Override + public Entry next() { + PeekIterator entryIterator = peek(); + if (entryIterator == null) { + throw new NoSuchElementException(); + } + Entry next = entryIterator.next(); + this.tableIterator = null; + if (entryIterator.hasNext()) { + priorityQueue.add(entryIterator); + } + return next; + } +} diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/NmapBuffer.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/NmapBuffer.java new file mode 100644 index 000000000..3830ed475 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/NmapBuffer.java @@ -0,0 +1,51 @@ +package ru.vk.itmo.test.tyapuevdmitrij.dao; + +import java.io.IOException; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.nio.channels.FileChannel; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.EnumSet; + +public final class NmapBuffer { + + private NmapBuffer() { + throw new IllegalStateException("Utility class"); + } + + static MemorySegment getReadBufferFromSsTable(Path ssTablePath, Arena readArena) { + MemorySegment buffer; + boolean created = false; + try (FileChannel channel = FileChannel.open(ssTablePath, StandardOpenOption.READ)) { + buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, Files.size(ssTablePath), readArena); + created = true; + } catch (IOException e) { + buffer = null; + } finally { + if (!created) { + readArena.close(); + } + } + return buffer; + } + + static MemorySegment getWriteBufferToSsTable(Long writeBytes, + Path path, + Arena writeArena + ) throws IOException { + MemorySegment buffer; + try ( + FileChannel channel = FileChannel.open(path, EnumSet.of(StandardOpenOption.READ, + StandardOpenOption.WRITE, + StandardOpenOption.CREATE, + StandardOpenOption.TRUNCATE_EXISTING))) { + buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, + writeBytes, writeArena); + } + return buffer; + } +} + + diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/State.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/State.java new file mode 100644 index 000000000..50ef47a9f --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/State.java @@ -0,0 +1,46 @@ +package ru.vk.itmo.test.tyapuevdmitrij.dao; + +import ru.vk.itmo.dao.Entry; + +import java.lang.foreign.MemorySegment; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentNavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.atomic.AtomicLong; + +public class State { + final ConcurrentNavigableMap> memTable; + final ConcurrentNavigableMap> flushMemTable; + final AtomicLong memoryUsage; + final Storage storage; + + State(ConcurrentNavigableMap> memTable, + ConcurrentNavigableMap> flushMemTable, AtomicLong memoryUsage, + Storage storage) { + this.memTable = memTable; + this.flushMemTable = flushMemTable; + this.memoryUsage = memoryUsage; + this.storage = storage; + } + + public State prepareToFlash() { + return new State(new ConcurrentSkipListMap<>(MemorySegmentComparator.getMemorySegmentComparator()), + this.memTable, + new AtomicLong(), + this.storage); + } + + public State afterFLush(MemorySegment flushedTable) { + List newSsTables = new ArrayList<>(storage.ssTables.size() + 1); + newSsTables.addAll(storage.ssTables); + newSsTables.add(flushedTable); + Storage newStorage = new Storage(storage.storageHelper, + storage.ssTablesQuantity + 1, + newSsTables, + storage.readArena); + return new State(this.memTable, null, this.memoryUsage, newStorage); + } +} + + diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/Storage.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/Storage.java new file mode 100644 index 000000000..30d4c9429 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/Storage.java @@ -0,0 +1,209 @@ +package ru.vk.itmo.test.tyapuevdmitrij.dao; + +import ru.vk.itmo.dao.BaseEntry; +import ru.vk.itmo.dao.Entry; + +import java.io.IOException; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +public class Storage { + protected final StorageHelper storageHelper; + protected int ssTablesQuantity; + protected List ssTables; + protected final Arena readArena; + + public Storage(Path ssTablePath) { + storageHelper = new StorageHelper(); + ssTablesQuantity = storageHelper.findSsTablesQuantity(ssTablePath); + ssTables = new ArrayList<>(ssTablesQuantity); + readArena = Arena.ofShared(); + for (int i = 0; i < ssTablesQuantity; i++) { + Path path = ssTablePath.resolve(StorageHelper.SS_TABLE_FILE_NAME + i); + ssTables.add(NmapBuffer.getReadBufferFromSsTable(path, readArena)); + } + } + + public Storage(StorageHelper storageHelper, int ssTablesQuantity, List ssTables, Arena readArena) { + this.storageHelper = storageHelper; + this.ssTablesQuantity = ssTablesQuantity; + this.ssTables = ssTables; + this.readArena = readArena; + } + + public void save(Collection> memTableEntries, + Path ssTablePath, + Storage prevState) throws IOException { + if (memTableEntries.isEmpty()) { + return; + } + Path path = ssTablePath.resolve(StorageHelper.TEMP_SS_TABLE_FILE_NAME + prevState.ssTablesQuantity); + try (Arena writeArena = Arena.ofConfined()) { + MemorySegment buffer; + buffer = NmapBuffer.getWriteBufferToSsTable(prevState.storageHelper.getSsTableDataByteSize(memTableEntries), + path, writeArena); + prevState.writeMemTableDataToFile(buffer, memTableEntries, prevState); + } + Path newPath = ssTablePath.resolve(StorageHelper.SS_TABLE_FILE_NAME + prevState.ssTablesQuantity); + try { + Files.move( + path, + newPath, + StandardCopyOption.ATOMIC_MOVE, + StandardCopyOption.REPLACE_EXISTING + ); + } catch (IOException e) { + throw new DAOException("Can't rename file", e); + } + } + + private void writeMemTableDataToFile(MemorySegment buffer, + Iterable> memTableEntries, + Storage prevState) { + long offset = 0; + long bufferByteSize = buffer.byteSize(); + long writeIndexPosition; + writeIndexPosition = bufferByteSize - prevState.storageHelper.memTableEntriesCount * 2L * Long.BYTES + - Long.BYTES; + //write to the end of file size of memTable + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, + bufferByteSize - Long.BYTES, + prevState.storageHelper.memTableEntriesCount); + for (Entry entry : memTableEntries) { + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, offset, entry.key().byteSize()); + // write keyByteSizeOffsetPosition to the end of buffer + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, writeIndexPosition, offset); + writeIndexPosition += Long.BYTES; + offset += Long.BYTES; + MemorySegment.copy(entry.key(), 0, buffer, offset, entry.key().byteSize()); + offset += entry.key().byteSize(); + // write valueByteSizeOffsetPosition to the end of buffer next to the keyByteSizeOffsetPosition + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, writeIndexPosition, offset); + writeIndexPosition += Long.BYTES; + if (entry.value() == null) { + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, offset, tombstone(offset)); + offset += Long.BYTES; + } else { + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, offset, entry.value().byteSize()); + offset += Long.BYTES; + MemorySegment.copy(entry.value(), 0, buffer, offset, entry.value().byteSize()); + offset += entry.value().byteSize(); + } + } + } + + private long getSsTableIndexByKey(MemorySegment ssTable, MemorySegment key, + Comparator memorySegmentComparator) { + long memTableSize = ssTable.get(ValueLayout.JAVA_LONG_UNALIGNED, ssTable.byteSize() - Long.BYTES); + long left = 0; + long right = memTableSize - 1L; + long lastKeyIndexOffset = ssTable.byteSize() - 3 * Long.BYTES; + while (left <= right) { + long mid = (left + right) >>> 1; + long midOffset = lastKeyIndexOffset - (memTableSize - 1L) * Long.BYTES * 2L + mid * 2L * Long.BYTES; + MemorySegment readKey = getKeyByOffset(ssTable, midOffset); + int res = memorySegmentComparator.compare(readKey, key); + if (res == 0) { + return mid; + } + if (res > 0) { + right = mid - 1; + } else { + left = mid + 1; + } + } + return left; + } + + private Entry getSsTableEntryByIndex(MemorySegment ssTable, long index) { + long memTableSize = ssTable.get(ValueLayout.JAVA_LONG_UNALIGNED, ssTable.byteSize() - Long.BYTES); + if (index > memTableSize - 1 || index < 0) { + return null; + } + long keyIndexOffset = ssTable.byteSize() - 3 * Long.BYTES + - (memTableSize - 1L) * Long.BYTES * 2L + index * 2L * Long.BYTES; + MemorySegment readKey = getKeyByOffset(ssTable, keyIndexOffset); + MemorySegment readValue = getValueByOffset(ssTable, keyIndexOffset + Long.BYTES); + return new BaseEntry<>(readKey, readValue); + } + + private MemorySegment getKeyByOffset(MemorySegment ssTable, long offset) { + long keyByteSizeOffset = ssTable.get(ValueLayout.JAVA_LONG_UNALIGNED, offset); + long keyByteSize = ssTable.get(ValueLayout.JAVA_LONG_UNALIGNED, keyByteSizeOffset); + long keyOffset = keyByteSizeOffset + Long.BYTES; + return ssTable.asSlice(keyOffset, keyByteSize); + } + + private MemorySegment getValueByOffset(MemorySegment ssTable, long offset) { + long valueByteSizeOffset = ssTable.get(ValueLayout.JAVA_LONG_UNALIGNED, offset); + long valueByteSize = ssTable.get(ValueLayout.JAVA_LONG_UNALIGNED, valueByteSizeOffset); + if (valueByteSize < 0) { + return null; + } + long valueOffset = valueByteSizeOffset + Long.BYTES; + return ssTable.asSlice(valueOffset, valueByteSize); + } + + public Iterator> range( + Iterator> flushMemTableIterator, + Iterator> memTableIterator, + MemorySegment from, + MemorySegment to, Comparator memorySegmentComparator) { + List>> iterators = new ArrayList<>(ssTablesQuantity + 2); + for (MemorySegment memorySegment : ssTables) { + iterators.add(iterator(memorySegment, from, to, memorySegmentComparator)); + } + iterators.add(flushMemTableIterator); + iterators.add(memTableIterator); + return new MergeIterator(iterators, Comparator.comparing(Entry::key, memorySegmentComparator)); + } + + private Iterator> iterator(MemorySegment ssTable, MemorySegment from, MemorySegment to, + Comparator memorySegmentComparator) { + long recordIndexFrom = from == null ? 0 : normalize(getSsTableIndexByKey(ssTable, + from, + memorySegmentComparator)); + long memTableSize = ssTable.get(ValueLayout.JAVA_LONG_UNALIGNED, ssTable.byteSize() - Long.BYTES); + long recordIndexTo = to == null ? memTableSize : normalize(getSsTableIndexByKey(ssTable, + to, + memorySegmentComparator)); + + return new Iterator<>() { + long index = recordIndexFrom; + + @Override + public boolean hasNext() { + return index < recordIndexTo; + } + + @Override + public Entry next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + Entry entry = getSsTableEntryByIndex(ssTable, index); + index++; + return entry; + } + }; + } + + private static long tombstone(long offset) { + return 1L << 63 | offset; + } + + private static long normalize(long value) { + return value & ~(1L << 63); + } + +} diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/StorageHelper.java b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/StorageHelper.java new file mode 100644 index 000000000..e8776b976 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/dao/StorageHelper.java @@ -0,0 +1,150 @@ +package ru.vk.itmo.test.tyapuevdmitrij.dao; + +import ru.vk.itmo.dao.Entry; + +import java.io.File; +import java.io.IOException; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Collections; +import java.util.Iterator; + +public class StorageHelper { + static final String SS_TABLE_FILE_NAME = "ssTable"; + static final String TEMP_SS_TABLE_FILE_NAME = "tempSsTable"; + static final String COMPACTED_FILE_NAME = "compact"; + private long ssTablesEntryQuantity; + protected long memTableEntriesCount; + + public int findSsTablesQuantity(Path ssTablePath) { + File[] files = getDirectoryFiles(ssTablePath); + if (files.length == 0) { + return 0; + } + long countSsTables = 0L; + for (File file : files) { + if (file.isFile() && file.getName().contains(SS_TABLE_FILE_NAME)) { + countSsTables++; + } + } + return (int) countSsTables; + } + + public void deleteOldSsTables(Path ssTablePath) { + File[] files = getDirectoryFiles(ssTablePath); + for (File file : files) { + if (file.getName().contains(SS_TABLE_FILE_NAME)) { + try { + Files.delete(file.toPath()); + } catch (IOException e) { + throw new DAOException("Can't delete file " + file.toPath(), e); + } + } + } + } + + private File[] getDirectoryFiles(Path ssTablePath) { + File directory = new File(ssTablePath.toUri()); + if (!directory.exists() || !directory.isDirectory()) { + return new File[0]; + } + return directory.listFiles(); + } + + public void renameCompactedSsTable(Path ssTablePath) { + Path compactionFile = ssTablePath.resolve(COMPACTED_FILE_NAME); + Path newCompactionFile = ssTablePath.resolve(SS_TABLE_FILE_NAME + 0); + try { + Files.move( + compactionFile, + newCompactionFile, + StandardCopyOption.ATOMIC_MOVE, + StandardCopyOption.REPLACE_EXISTING + ); + } catch (IOException e) { + throw new DAOException("Can't rename file", e); + } + } + + public long getSsTableDataByteSize(Iterable> memTableEntries) { + long ssTableDataByteSize = 0; + long entriesCount = 0; + for (Entry entry : memTableEntries) { + ssTableDataByteSize += entry.key().byteSize(); + if (entry.value() != null) { + ssTableDataByteSize += entry.value().byteSize(); + } + entriesCount++; + } + memTableEntriesCount = entriesCount; + return ssTableDataByteSize + entriesCount * Long.BYTES * 4L + Long.BYTES; + } + + public void saveDataForCompaction(State stateNow, Path ssTablePath) { + Iterator> ssTablesIterator = stateNow.storage.range( + Collections.emptyIterator(), Collections.emptyIterator(), + null, null, MemorySegmentComparator.getMemorySegmentComparator()); + Path compactionPath = ssTablePath.resolve(StorageHelper.COMPACTED_FILE_NAME); + try (Arena writeArena = Arena.ofConfined()) { + MemorySegment buffer = NmapBuffer.getWriteBufferToSsTable(getCompactionTableByteSize(stateNow), + compactionPath, writeArena); + long bufferByteSize = buffer.byteSize(); + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, bufferByteSize - Long.BYTES, ssTablesEntryQuantity); + long dataOffset = 0; + long indexOffset = bufferByteSize - Long.BYTES - ssTablesEntryQuantity * 2L * Long.BYTES; + while (ssTablesIterator.hasNext()) { + Entry entry = ssTablesIterator.next(); + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, indexOffset, dataOffset); + indexOffset += Long.BYTES; + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, dataOffset, entry.key().byteSize()); + dataOffset += Long.BYTES; + MemorySegment.copy(entry.key(), 0, buffer, dataOffset, entry.key().byteSize()); + dataOffset += entry.key().byteSize(); + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, indexOffset, dataOffset); + indexOffset += Long.BYTES; + buffer.set(ValueLayout.JAVA_LONG_UNALIGNED, dataOffset, entry.value().byteSize()); + dataOffset += Long.BYTES; + MemorySegment.copy(entry.value(), 0, buffer, dataOffset, entry.value().byteSize()); + dataOffset += entry.value().byteSize(); + } + } catch (IOException e) { + throw new IllegalStateException(e); + } finally { + stateNow.storage.readArena.close(); + } + } + + private long getCompactionTableByteSize(State stateNow) { + Iterator> dataIterator = stateNow.storage.range(Collections.emptyIterator(), + Collections.emptyIterator(), + null, + null, + MemorySegmentComparator.getMemorySegmentComparator()); + long compactionTableByteSize = 0; + long countEntry = 0; + while (dataIterator.hasNext()) { + Entry entry = dataIterator.next(); + compactionTableByteSize += entry.key().byteSize(); + compactionTableByteSize += entry.value().byteSize(); + countEntry++; + } + ssTablesEntryQuantity = countEntry; + return compactionTableByteSize + countEntry * 4L * Long.BYTES + Long.BYTES; + } + + public static long sizeOf(final Entry entry) { + if (entry == null) { + return 0L; + } + + if (entry.value() == null) { + return entry.key().byteSize(); + } + + return entry.key().byteSize() + entry.value().byteSize(); + } +} diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/get_1000rs.jfr b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/get_1000rs.jfr new file mode 100644 index 000000000..9b256a8eb Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/get_1000rs.jfr differ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/get_1000rs_alloc.html b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/get_1000rs_alloc.html new file mode 100644 index 000000000..27cadb153 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/get_1000rs_alloc.html @@ -0,0 +1,547 @@ + + + + + + + +

Flame Graph

+
  
+
Produced by async-profiler
+ +
+

+

Matched:

+ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/get_1000rs_cpu.html b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/get_1000rs_cpu.html new file mode 100644 index 000000000..02637c0ab --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/get_1000rs_cpu.html @@ -0,0 +1,1112 @@ + + + + + + + +

Flame Graph

+
  
+
Produced by async-profiler
+ +
+

+

Matched:

+ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/put_5000rs.jfr b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/put_5000rs.jfr new file mode 100644 index 000000000..71738aa75 Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/put_5000rs.jfr differ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/put_5000rs_alloc.html b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/put_5000rs_alloc.html new file mode 100644 index 000000000..5f82fd3a7 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/put_5000rs_alloc.html @@ -0,0 +1,392 @@ + + + + + + + +

Flame Graph

+
  
+
Produced by async-profiler
+ +
+

+

Matched:

+ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/put_5000rs_cpu.html b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/put_5000rs_cpu.html new file mode 100644 index 000000000..69146301b --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/profiler_results/put_5000rs_cpu.html @@ -0,0 +1,1009 @@ + + + + + + + +

Flame Graph

+
  
+
Produced by async-profiler
+ +
+

+

Matched:

+ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/get_1000rs.png b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/get_1000rs.png new file mode 100644 index 000000000..432cc4044 Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/get_1000rs.png differ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/get_3000rs.png b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/get_3000rs.png new file mode 100644 index 000000000..cbe3d597b Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/get_3000rs.png differ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/put_10000rs.png b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/put_10000rs.png new file mode 100644 index 000000000..52beb58d5 Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/put_10000rs.png differ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/put_3000rs.png b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/put_3000rs.png new file mode 100644 index 000000000..ea662836b Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/put_3000rs.png differ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/put_5000rs.png b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/put_5000rs.png new file mode 100644 index 000000000..c0a45b85a Binary files /dev/null and b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/put_5000rs.png differ diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/report.md b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/report.md new file mode 100644 index 000000000..5494020c7 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/reports/stage1/report.md @@ -0,0 +1,65 @@ +#Отчет +Для проведения экспериментов были написаны 2 скрипта: get.lua и put.lua. + +## Нагрузочное тестирование put + +В каждом запросе был добавлен случайный ключ в диапазоне от 1 до 1000000. А также значение случайной длины от 5 до 20, +состоящее из букв латинского алфавита(строчных или заглавных). + +1. 3000 запросов в секунду на протяжении 1 минуты: Сервер без проблем держит нагрузку, stables накапливаются. + ![put_3000rs.png](put_3000rs.png) +2. 5000 запросов в секунду на протяжении 1 минуты: Сервер без проблем держит нагрузку, stables накапливаются. + ![put_5000rs.png](put_5000rs.png) +3. 10000 запросов в секунду на протяжении 1 минуты: У сервера появились проблемы. На последнем персентиль +резко возрастает время. Однако все время пока остается в пределах 100мс. + ![put_10000rs.png](put_10000rs.png) +4. 30000 запросов в секунду на протяжении 1 минуты: Сервер перестал справляться. +``` +dmitrij@MY-PC ~/Д/J/w/wrk2 (master)> ./wrk -d 60 -t 1 -c 1 -R 30000 -L -s +/home/dmitrij/Документы/JavaProjects/highload/2024-highload-dht/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/ +wrk2_scripts/put.lua http://localhost:8080 + Running 1m test @ http://localhost:8080 + 1 threads and 1 connections + Thread calibration: mean lat.: 552.170ms, rate sampling interval: 2988ms + Thread Stats Avg Stdev Max +/- Stdev + Latency 4.24s 1.91s 7.18s 56.74% + Req/Sec 26.38k 5.15k 35.56k 43.75% + Latency Distribution (HdrHistogram - Recorded Latency) + 50.000% 4.22s + 75.000% 5.87s + 90.000% 6.67s + 99.000% 7.12s + 99.900% 7.18s + 99.990% 7.18s + 99.999% 7.18s + 100.000% 7.18s +``` +## Нагрузочное тестирование get + В каждом запросе проверялся случайный ключ в диапазоне от 1 до 1000000. Эксперименты проводились на заполненной базе. + +1. 1000 запросов в секунду на протяжении 1 минуты: Сервер без проблем держит нагрузку. + ![get_1000rs.png](get_1000rs.png) +2. 3000 запросов в секунду на протяжении 1 минуты: У сервера появились проблемы. На последних 10 персентиль + резко возрастает время. Однако все время пока остается в пределах 100мс. + ![get_3000rs.png](get_3000rs.png) +3. 10000 запросов в секунду на протяжении 1 минуты: Сервер перестал справляться +``` +Latency Distribution (HdrHistogram - Recorded Latency) + 50.000% 23.6s + 75.000% 31.93s + 90.000% 36.92s + 99.000% 39.97s + 99.900% 40.18s + 99.990% 40.2s + 99.999% 40.23s + 100.000% 40.28s + +``` +Из-за большого количества накопленных данных почти все время процессора уходит поиск нужного ключа в куче разных фалов. +Как раз при этом и обнаружились серьезные аллокации при создании итератора по таблицам на диске и при поиске ключа по +смещению +(тут все занимает MemorySegment.asSlice). + +## Вывод +По результатам экспериментов выяснилось, что база может гораздо лучше принимать данные, чем их искать. Необходима +оптимизация поиска данных diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_10000rs_1min.txt b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_10000rs_1min.txt new file mode 100644 index 000000000..dbf1cd51c --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_10000rs_1min.txt @@ -0,0 +1,69 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 6791.167 0.000000 17 1.00 + 10133.503 0.100000 16568 1.11 + 13484.031 0.200000 33070 1.25 + 16859.135 0.300000 49603 1.43 + 20234.239 0.400000 66123 1.67 + 23609.343 0.500000 82714 2.00 + 25264.127 0.550000 90905 2.22 + 26918.911 0.600000 99174 2.50 + 28590.079 0.650000 107489 2.86 + 30277.631 0.700000 115779 3.33 + 31932.415 0.750000 123989 4.00 + 32784.383 0.775000 128155 4.44 + 33652.735 0.800000 132374 5.00 + 34439.167 0.825000 136465 5.71 + 35258.367 0.850000 140568 6.67 + 36110.335 0.875000 144729 8.00 + 36536.319 0.887500 146820 8.89 + 36929.535 0.900000 148758 10.00 + 37355.519 0.912500 150876 11.43 + 37781.503 0.925000 152951 13.33 + 38207.487 0.937500 155083 16.00 + 38404.095 0.943750 156020 17.78 + 38633.471 0.950000 157133 20.00 + 38830.079 0.956250 158125 22.86 + 39026.687 0.962500 159113 26.67 + 39256.063 0.968750 160245 32.00 + 39354.367 0.971875 160727 35.56 + 39452.671 0.975000 161213 40.00 + 39550.975 0.978125 161710 45.71 + 39649.279 0.981250 162191 53.33 + 39780.351 0.984375 162850 64.00 + 39813.119 0.985938 163022 71.11 + 39878.655 0.987500 163366 80.00 + 39911.423 0.989062 163529 91.43 + 39976.959 0.990625 163860 106.67 + 40009.727 0.992188 164032 128.00 + 40042.495 0.992969 164208 142.22 + 40075.263 0.993750 164380 160.00 + 40075.263 0.994531 164380 182.86 + 40108.031 0.995313 164542 213.33 + 40140.799 0.996094 164712 256.00 + 40140.799 0.996484 164712 284.44 + 40173.567 0.996875 164883 320.00 + 40173.567 0.997266 164883 365.71 + 40206.335 0.997656 165055 426.67 + 40206.335 0.998047 165055 512.00 + 40206.335 0.998242 165055 568.89 + 40206.335 0.998437 165055 640.00 + 40206.335 0.998633 165055 731.43 + 40239.103 0.998828 165206 853.33 + 40239.103 0.999023 165206 1024.00 + 40239.103 0.999121 165206 1137.78 + 40239.103 0.999219 165206 1280.00 + 40239.103 0.999316 165206 1462.86 + 40239.103 0.999414 165206 1706.67 + 40239.103 0.999512 165206 2048.00 + 40239.103 0.999561 165206 2275.56 + 40271.871 0.999609 165276 2560.00 + 40271.871 1.000000 165276 inf +#[Mean = 23550.947, StdDeviation = 9670.107] +#[Max = 40239.104, Total count = 165276] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 197455 requests in 1.00m, 18.13MB read + Non-2xx or 3xx responses: 26509 +Requests/sec: 3290.94 +Transfer/sec: 309.49KB diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_1000rs_1min.txt b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_1000rs_1min.txt new file mode 100644 index 000000000..d166ba3be --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_1000rs_1min.txt @@ -0,0 +1,89 @@ + 0.075 0.000000 1 1.00 + 0.722 0.100000 5034 1.11 + 0.864 0.200000 10013 1.25 + 0.998 0.300000 15036 1.43 + 1.130 0.400000 19999 1.67 + 1.252 0.500000 25023 2.00 + 1.297 0.550000 27510 2.22 + 1.377 0.600000 30026 2.50 + 1.437 0.650000 32537 2.86 + 1.496 0.700000 35046 3.33 + 1.553 0.750000 37498 4.00 + 1.584 0.775000 38776 4.44 + 1.614 0.800000 40003 5.00 + 1.645 0.825000 41274 5.71 + 1.676 0.850000 42515 6.67 + 1.713 0.875000 43765 8.00 + 1.732 0.887500 44405 8.89 + 1.753 0.900000 45001 10.00 + 1.774 0.912500 45638 11.43 + 1.796 0.925000 46256 13.33 + 1.821 0.937500 46903 16.00 + 1.833 0.943750 47191 17.78 + 1.849 0.950000 47496 20.00 + 1.874 0.956250 47819 22.86 + 1.906 0.962500 48125 26.67 + 1.947 0.968750 48438 32.00 + 1.975 0.971875 48591 35.56 + 2.012 0.975000 48750 40.00 + 2.051 0.978125 48906 45.71 + 2.111 0.981250 49063 53.33 + 2.163 0.984375 49216 64.00 + 2.185 0.985938 49300 71.11 + 2.207 0.987500 49373 80.00 + 2.245 0.989062 49451 91.43 + 2.265 0.990625 49530 106.67 + 2.281 0.992188 49605 128.00 + 2.287 0.992969 49645 142.22 + 2.299 0.993750 49683 160.00 + 2.321 0.994531 49723 182.86 + 2.341 0.995313 49763 213.33 + 2.363 0.996094 49800 256.00 + 2.379 0.996484 49821 284.44 + 2.425 0.996875 49839 320.00 + 2.501 0.997266 49860 365.71 + 2.559 0.997656 49878 426.67 + 2.617 0.998047 49898 512.00 + 2.649 0.998242 49908 568.89 + 2.713 0.998437 49917 640.00 + 2.767 0.998633 49927 731.43 + 2.875 0.998828 49937 853.33 + 3.131 0.999023 49947 1024.00 + 3.253 0.999121 49952 1137.78 + 3.451 0.999219 49956 1280.00 + 3.699 0.999316 49961 1462.86 + 3.879 0.999414 49966 1706.67 + 4.017 0.999512 49971 2048.00 + 4.049 0.999561 49974 2275.56 + 4.057 0.999609 49976 2560.00 + 4.069 0.999658 49978 2925.71 + 4.111 0.999707 49981 3413.33 + 4.131 0.999756 49985 4096.00 + 4.131 0.999780 49985 4551.11 + 4.295 0.999805 49986 5120.00 + 4.359 0.999829 49987 5851.43 + 4.439 0.999854 49988 6826.67 + 4.523 0.999878 49989 8192.00 + 4.591 0.999890 49990 9102.22 + 4.627 0.999902 49991 10240.00 + 4.627 0.999915 49991 11702.86 + 4.639 0.999927 49992 13653.33 + 4.639 0.999939 49992 16384.00 + 4.723 0.999945 49993 18204.44 + 4.723 0.999951 49993 20480.00 + 4.723 0.999957 49993 23405.71 + 4.783 0.999963 49994 27306.67 + 4.783 0.999969 49994 32768.00 + 4.783 0.999973 49994 36408.89 + 4.783 0.999976 49994 40960.00 + 4.783 0.999979 49994 46811.43 + 4.811 0.999982 49995 54613.33 + 4.811 1.000000 49995 inf +#[Mean = 1.251, StdDeviation = 0.408] +#[Max = 4.808, Total count = 49995] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 60000 requests in 1.00m, 5.50MB read + Non-2xx or 3xx responses: 8210 +Requests/sec: 999.98 +Transfer/sec: 93.90KB diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_3000rs_1min.txt b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_3000rs_1min.txt new file mode 100644 index 000000000..792f4d740 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_3000rs_1min.txt @@ -0,0 +1,99 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 0.039 0.000000 1 1.00 + 0.461 0.100000 15039 1.11 + 0.629 0.200000 30040 1.25 + 0.782 0.300000 45002 1.43 + 0.947 0.400000 60053 1.67 + 1.092 0.500000 75073 2.00 + 1.168 0.550000 82577 2.22 + 1.244 0.600000 90005 2.50 + 1.313 0.650000 97523 2.86 + 1.382 0.700000 105085 3.33 + 1.472 0.750000 112535 4.00 + 1.521 0.775000 116282 4.44 + 1.586 0.800000 119995 5.00 + 1.681 0.825000 123764 5.71 + 1.922 0.850000 127486 6.67 + 2.375 0.875000 131247 8.00 + 2.721 0.887500 133114 8.89 + 3.373 0.900000 134987 10.00 + 4.061 0.912500 136860 11.43 + 4.771 0.925000 138738 13.33 + 5.583 0.937500 140615 16.00 + 5.935 0.943750 141545 17.78 + 6.299 0.950000 142484 20.00 + 6.639 0.956250 143433 22.86 + 6.951 0.962500 144361 26.67 + 7.275 0.968750 145300 32.00 + 7.435 0.971875 145768 35.56 + 7.651 0.975000 146232 40.00 + 8.011 0.978125 146703 45.71 + 8.559 0.981250 147169 53.33 + 9.087 0.984375 147647 64.00 + 9.431 0.985938 147878 71.11 + 9.887 0.987500 148107 80.00 + 10.863 0.989062 148342 91.43 + 12.335 0.990625 148576 106.67 + 13.959 0.992188 148810 128.00 + 14.703 0.992969 148928 142.22 + 14.991 0.993750 149044 160.00 + 15.623 0.994531 149161 182.86 + 16.927 0.995313 149280 213.33 + 18.511 0.996094 149397 256.00 + 19.023 0.996484 149455 284.44 + 19.647 0.996875 149513 320.00 + 20.335 0.997266 149571 365.71 + 20.751 0.997656 149630 426.67 + 21.023 0.998047 149699 512.00 + 21.055 0.998242 149720 568.89 + 21.311 0.998437 149747 640.00 + 23.263 0.998633 149776 731.43 + 24.431 0.998828 149806 853.33 + 25.199 0.999023 149836 1024.00 + 25.583 0.999121 149851 1137.78 + 26.031 0.999219 149865 1280.00 + 26.687 0.999316 149879 1462.86 + 27.151 0.999414 149895 1706.67 + 27.487 0.999512 149908 2048.00 + 27.647 0.999561 149916 2275.56 + 27.951 0.999609 149923 2560.00 + 28.079 0.999658 149930 2925.71 + 28.255 0.999707 149938 3413.33 + 28.367 0.999756 149945 4096.00 + 28.415 0.999780 149949 4551.11 + 28.447 0.999805 149952 5120.00 + 28.527 0.999829 149956 5851.43 + 28.559 0.999854 149960 6826.67 + 28.623 0.999878 149964 8192.00 + 28.655 0.999890 149965 9102.22 + 28.719 0.999902 149968 10240.00 + 28.735 0.999915 149969 11702.86 + 28.783 0.999927 149972 13653.33 + 28.783 0.999939 149972 16384.00 + 28.799 0.999945 149974 18204.44 + 28.799 0.999951 149974 20480.00 + 28.831 0.999957 149976 23405.71 + 28.831 0.999963 149976 27306.67 + 28.879 0.999969 149979 32768.00 + 28.879 0.999973 149979 36408.89 + 28.879 0.999976 149979 40960.00 + 28.879 0.999979 149979 46811.43 + 28.879 0.999982 149979 54613.33 + 28.879 0.999985 149979 65536.00 + 28.879 0.999986 149979 72817.78 + 28.911 0.999988 149980 81920.00 + 28.911 0.999989 149980 93622.86 + 28.911 0.999991 149980 109226.67 + 28.911 0.999992 149980 131072.00 + 28.911 0.999993 149980 145635.56 + 28.927 0.999994 149981 163840.00 + 28.927 1.000000 149981 inf +#[Mean = 1.679, StdDeviation = 2.320] +#[Max = 28.912, Total count = 149981] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 179993 requests in 1.00m, 16.53MB read + Non-2xx or 3xx responses: 24130 +Requests/sec: 2999.90 +Transfer/sec: 282.04KB diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_4000rs_1min.txt b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_4000rs_1min.txt new file mode 100644 index 000000000..1f2cc8200 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/get_4000rs_1min.txt @@ -0,0 +1,67 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 1694.719 0.000000 15 1.00 + 2498.559 0.100000 16809 1.11 + 3184.639 0.200000 33587 1.25 + 4018.175 0.300000 50372 1.43 + 4853.759 0.400000 67154 1.67 + 5701.631 0.500000 84007 2.00 + 6103.039 0.550000 92331 2.22 + 6504.447 0.600000 100740 2.50 + 6905.855 0.650000 109176 2.86 + 7340.031 0.700000 117536 3.33 + 7741.439 0.750000 125962 4.00 + 7917.567 0.775000 130127 4.44 + 8085.503 0.800000 134323 5.00 + 8249.343 0.825000 138542 5.71 + 8462.335 0.850000 142740 6.67 + 8683.519 0.875000 146984 8.00 + 8798.207 0.887500 149089 8.89 + 8896.511 0.900000 151146 10.00 + 8994.815 0.912500 153259 11.43 + 9109.503 0.925000 155350 13.33 + 9224.191 0.937500 157398 16.00 + 9281.535 0.943750 158493 17.78 + 9338.879 0.950000 159571 20.00 + 9388.031 0.956250 160562 22.86 + 9445.375 0.962500 161698 26.67 + 9494.527 0.968750 162673 32.00 + 9519.103 0.971875 163138 35.56 + 9551.871 0.975000 163683 40.00 + 9584.639 0.978125 164372 45.71 + 9601.023 0.981250 164749 53.33 + 9625.599 0.984375 165418 64.00 + 9633.791 0.985938 165622 71.11 + 9641.983 0.987500 165831 80.00 + 9650.175 0.989062 166043 91.43 + 9666.559 0.990625 166447 106.67 + 9674.751 0.992188 166642 128.00 + 9682.943 0.992969 166843 142.22 + 9682.943 0.993750 166843 160.00 + 9691.135 0.994531 167049 182.86 + 9699.327 0.995313 167272 213.33 + 9699.327 0.996094 167272 256.00 + 9699.327 0.996484 167272 284.44 + 9707.519 0.996875 167425 320.00 + 9707.519 0.997266 167425 365.71 + 9715.711 0.997656 167568 426.67 + 9715.711 0.998047 167568 512.00 + 9715.711 0.998242 167568 568.89 + 9723.903 0.998437 167746 640.00 + 9723.903 0.998633 167746 731.43 + 9723.903 0.998828 167746 853.33 + 9723.903 0.999023 167746 1024.00 + 9723.903 0.999121 167746 1137.78 + 9723.903 0.999219 167746 1280.00 + 9723.903 0.999316 167746 1462.86 + 9723.903 0.999414 167746 1706.67 + 9732.095 0.999512 167839 2048.00 + 9732.095 1.000000 167839 inf +#[Mean = 5678.582, StdDeviation = 2333.851] +#[Max = 9723.904, Total count = 167839] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 201084 requests in 1.00m, 18.46MB read + Non-2xx or 3xx responses: 27115 +Requests/sec: 3351.41 +Transfer/sec: 315.05KB diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_10000rs_1min.txt b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_10000rs_1min.txt new file mode 100644 index 000000000..64382cb2a --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_10000rs_1min.txt @@ -0,0 +1,99 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 0.025 0.000000 5 1.00 + 0.226 0.100000 50110 1.11 + 0.399 0.200000 100298 1.25 + 0.569 0.300000 150136 1.43 + 0.737 0.400000 199986 1.67 + 0.903 0.500000 250243 2.00 + 0.981 0.550000 275105 2.22 + 1.049 0.600000 299984 2.50 + 1.109 0.650000 325078 2.86 + 1.214 0.700000 350095 3.33 + 1.390 0.750000 374994 4.00 + 1.500 0.775000 387568 4.44 + 1.619 0.800000 400008 5.00 + 1.747 0.825000 412550 5.71 + 1.881 0.850000 424976 6.67 + 2.018 0.875000 437509 8.00 + 2.081 0.887500 443825 8.89 + 2.139 0.900000 450084 10.00 + 2.197 0.912500 456377 11.43 + 2.261 0.925000 462659 13.33 + 2.317 0.937500 468716 16.00 + 2.347 0.943750 472008 17.78 + 2.375 0.950000 475031 20.00 + 2.415 0.956250 478158 22.86 + 2.463 0.962500 481244 26.67 + 2.529 0.968750 484338 32.00 + 2.575 0.971875 485953 35.56 + 2.641 0.975000 487491 40.00 + 2.803 0.978125 489033 45.71 + 3.393 0.981250 490583 53.33 + 4.771 0.984375 492148 64.00 + 5.887 0.985938 492928 71.11 + 7.063 0.987500 493710 80.00 + 8.807 0.989062 494493 91.43 + 10.743 0.990625 495275 106.67 + 14.199 0.992188 496053 128.00 + 16.111 0.992969 496442 142.22 + 18.095 0.993750 496834 160.00 + 20.543 0.994531 497223 182.86 + 23.439 0.995313 497614 213.33 + 26.383 0.996094 498005 256.00 + 28.143 0.996484 498200 284.44 + 29.311 0.996875 498396 320.00 + 30.495 0.997266 498590 365.71 + 33.727 0.997656 498787 426.67 + 38.079 0.998047 498981 512.00 + 40.223 0.998242 499080 568.89 + 43.711 0.998437 499176 640.00 + 48.479 0.998633 499274 731.43 + 50.559 0.998828 499373 853.33 + 53.727 0.999023 499469 1024.00 + 55.263 0.999121 499519 1137.78 + 56.191 0.999219 499567 1280.00 + 57.183 0.999316 499617 1462.86 + 58.559 0.999414 499665 1706.67 + 60.383 0.999512 499714 2048.00 + 61.439 0.999561 499738 2275.56 + 62.367 0.999609 499762 2560.00 + 63.167 0.999658 499788 2925.71 + 63.967 0.999707 499811 3413.33 + 64.607 0.999756 499835 4096.00 + 64.863 0.999780 499849 4551.11 + 65.055 0.999805 499861 5120.00 + 65.247 0.999829 499872 5851.43 + 65.407 0.999854 499885 6826.67 + 65.599 0.999878 499900 8192.00 + 65.663 0.999890 499904 9102.22 + 65.727 0.999902 499909 10240.00 + 65.791 0.999915 499915 11702.86 + 65.855 0.999927 499923 13653.33 + 65.919 0.999939 499928 16384.00 + 65.983 0.999945 499936 18204.44 + 65.983 0.999951 499936 20480.00 + 65.983 0.999957 499936 23405.71 + 66.047 0.999963 499941 27306.67 + 66.111 0.999969 499948 32768.00 + 66.111 0.999973 499948 36408.89 + 66.111 0.999976 499948 40960.00 + 66.111 0.999979 499948 46811.43 + 66.111 0.999982 499948 54613.33 + 66.175 0.999985 499954 65536.00 + 66.175 0.999986 499954 72817.78 + 66.175 0.999988 499954 81920.00 + 66.175 0.999989 499954 93622.86 + 66.175 0.999991 499954 109226.67 + 66.175 0.999992 499954 131072.00 + 66.175 0.999993 499954 145635.56 + 66.175 0.999994 499954 163840.00 + 66.239 0.999995 499957 187245.71 + 66.239 1.000000 499957 inf +#[Mean = 1.289, StdDeviation = 3.068] +#[Max = 66.176, Total count = 499957] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 599980 requests in 1.00m, 38.34MB read +Requests/sec: 9999.62 +Transfer/sec: 654.27KB diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_30000rs_1min b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_30000rs_1min new file mode 100644 index 000000000..a67e670e4 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_30000rs_1min @@ -0,0 +1,68 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 988.159 0.000000 109 1.00 + 1499.135 0.100000 133127 1.11 + 2033.663 0.200000 266437 1.25 + 2848.767 0.300000 400046 1.43 + 3672.063 0.400000 532334 1.67 + 4222.975 0.500000 665821 2.00 + 4874.239 0.550000 733572 2.22 + 5017.599 0.600000 798626 2.50 + 5455.871 0.650000 865072 2.86 + 5746.687 0.700000 931630 3.33 + 5865.471 0.750000 999402 4.00 + 5943.295 0.775000 1032089 4.44 + 6230.015 0.800000 1065194 5.00 + 6324.223 0.825000 1099263 5.71 + 6422.527 0.850000 1131430 6.67 + 6541.311 0.875000 1164776 8.00 + 6606.847 0.887500 1181083 8.89 + 6672.383 0.900000 1197783 10.00 + 6868.991 0.912500 1214449 11.43 + 6946.815 0.925000 1231691 13.33 + 7000.063 0.937500 1248166 16.00 + 7020.543 0.943750 1257511 17.78 + 7032.831 0.950000 1264498 20.00 + 7045.119 0.956250 1273235 22.86 + 7057.407 0.962500 1281632 26.67 + 7073.791 0.968750 1290057 32.00 + 7081.983 0.971875 1295954 35.56 + 7086.079 0.975000 1297921 40.00 + 7094.271 0.978125 1302080 45.71 + 7102.463 0.981250 1307071 53.33 + 7106.559 0.984375 1309955 64.00 + 7110.655 0.985938 1312309 71.11 + 7114.751 0.987500 1314935 80.00 + 7118.847 0.989062 1317041 91.43 + 7122.943 0.990625 1318561 106.67 + 7135.231 0.992188 1320991 128.00 + 7139.327 0.992969 1321791 142.22 + 7143.423 0.993750 1322610 160.00 + 7151.615 0.994531 1324193 182.86 + 7155.711 0.995313 1324983 213.33 + 7159.807 0.996094 1325765 256.00 + 7163.903 0.996484 1326528 284.44 + 7167.999 0.996875 1327402 320.00 + 7167.999 0.997266 1327402 365.71 + 7172.095 0.997656 1328272 426.67 + 7172.095 0.998047 1328272 512.00 + 7176.191 0.998242 1329242 568.89 + 7176.191 0.998437 1329242 640.00 + 7176.191 0.998633 1329242 731.43 + 7176.191 0.998828 1329242 853.33 + 7180.287 0.999023 1330180 1024.00 + 7180.287 0.999121 1330180 1137.78 + 7180.287 0.999219 1330180 1280.00 + 7180.287 0.999316 1330180 1462.86 + 7180.287 0.999414 1330180 1706.67 + 7180.287 0.999512 1330180 2048.00 + 7180.287 0.999561 1330180 2275.56 + 7184.383 0.999609 1330728 2560.00 + 7184.383 1.000000 1330728 inf +#[Mean = 4240.484, StdDeviation = 1909.991] +#[Max = 7180.288, Total count = 1330728] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 1594140 requests in 1.00m, 101.86MB read +Requests/sec: 26569.23 +Transfer/sec: 1.70MB diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_3000rs_1min.txt b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_3000rs_1min.txt new file mode 100644 index 000000000..d7b00d8cc --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_3000rs_1min.txt @@ -0,0 +1,98 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 0.032 0.000000 1 1.00 + 0.402 0.100000 15059 1.11 + 0.592 0.200000 30049 1.25 + 0.741 0.300000 45016 1.43 + 0.904 0.400000 60050 1.67 + 1.036 0.500000 75062 2.00 + 1.086 0.550000 82603 2.22 + 1.135 0.600000 90037 2.50 + 1.210 0.650000 97533 2.86 + 1.269 0.700000 105107 3.33 + 1.328 0.750000 112540 4.00 + 1.363 0.775000 116325 4.44 + 1.391 0.800000 120116 5.00 + 1.418 0.825000 123733 5.71 + 1.447 0.850000 127624 6.67 + 1.484 0.875000 131276 8.00 + 1.520 0.887500 133143 8.89 + 1.567 0.900000 134996 10.00 + 1.602 0.912500 136877 11.43 + 1.647 0.925000 138745 13.33 + 1.741 0.937500 140614 16.00 + 1.797 0.943750 141546 17.78 + 1.870 0.950000 142487 20.00 + 1.934 0.956250 143422 22.86 + 1.992 0.962500 144353 26.67 + 2.053 0.968750 145333 32.00 + 2.073 0.971875 145766 35.56 + 2.107 0.975000 146263 40.00 + 2.131 0.978125 146706 45.71 + 2.171 0.981250 147171 53.33 + 2.227 0.984375 147650 64.00 + 2.247 0.985938 147874 71.11 + 2.265 0.987500 148104 80.00 + 2.283 0.989062 148340 91.43 + 2.301 0.990625 148585 106.67 + 2.323 0.992188 148809 128.00 + 2.337 0.992969 148932 142.22 + 2.353 0.993750 149040 160.00 + 2.369 0.994531 149171 182.86 + 2.383 0.995313 149279 213.33 + 2.395 0.996094 149395 256.00 + 2.403 0.996484 149480 284.44 + 2.407 0.996875 149512 320.00 + 2.419 0.997266 149567 365.71 + 2.431 0.997656 149631 426.67 + 2.439 0.998047 149688 512.00 + 2.443 0.998242 149716 568.89 + 2.449 0.998437 149752 640.00 + 2.455 0.998633 149776 731.43 + 2.461 0.998828 149807 853.33 + 2.469 0.999023 149831 1024.00 + 2.477 0.999121 149851 1137.78 + 2.483 0.999219 149861 1280.00 + 2.499 0.999316 149878 1462.86 + 2.539 0.999414 149890 1706.67 + 2.569 0.999512 149904 2048.00 + 2.587 0.999561 149912 2275.56 + 2.601 0.999609 149920 2560.00 + 2.627 0.999658 149926 2925.71 + 2.643 0.999707 149934 3413.33 + 2.697 0.999756 149941 4096.00 + 2.817 0.999780 149945 4551.11 + 3.025 0.999805 149948 5120.00 + 3.291 0.999829 149952 5851.43 + 3.581 0.999854 149956 6826.67 + 3.851 0.999878 149959 8192.00 + 3.997 0.999890 149961 9102.22 + 4.143 0.999902 149963 10240.00 + 4.259 0.999915 149965 11702.86 + 4.399 0.999927 149967 13653.33 + 4.467 0.999939 149968 16384.00 + 4.503 0.999945 149969 18204.44 + 4.523 0.999951 149970 20480.00 + 4.559 0.999957 149971 23405.71 + 4.611 0.999963 149972 27306.67 + 4.647 0.999969 149973 32768.00 + 4.647 0.999973 149973 36408.89 + 4.739 0.999976 149974 40960.00 + 4.739 0.999979 149974 46811.43 + 4.867 0.999982 149975 54613.33 + 4.867 0.999985 149975 65536.00 + 4.867 0.999986 149975 72817.78 + 4.979 0.999988 149976 81920.00 + 4.979 0.999989 149976 93622.86 + 4.979 0.999991 149976 109226.67 + 4.979 0.999992 149976 131072.00 + 4.979 0.999993 149976 145635.56 + 5.051 0.999994 149977 163840.00 + 5.051 1.000000 149977 inf +#[Mean = 1.024, StdDeviation = 0.465] +#[Max = 5.048, Total count = 149977] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 179990 requests in 1.00m, 11.50MB read +Requests/sec: 2999.86 +Transfer/sec: 196.28KB diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_5000rs_1min.txt b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_5000rs_1min.txt new file mode 100644 index 000000000..d7b00d8cc --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_results/put_5000rs_1min.txt @@ -0,0 +1,98 @@ + Value Percentile TotalCount 1/(1-Percentile) + + 0.032 0.000000 1 1.00 + 0.402 0.100000 15059 1.11 + 0.592 0.200000 30049 1.25 + 0.741 0.300000 45016 1.43 + 0.904 0.400000 60050 1.67 + 1.036 0.500000 75062 2.00 + 1.086 0.550000 82603 2.22 + 1.135 0.600000 90037 2.50 + 1.210 0.650000 97533 2.86 + 1.269 0.700000 105107 3.33 + 1.328 0.750000 112540 4.00 + 1.363 0.775000 116325 4.44 + 1.391 0.800000 120116 5.00 + 1.418 0.825000 123733 5.71 + 1.447 0.850000 127624 6.67 + 1.484 0.875000 131276 8.00 + 1.520 0.887500 133143 8.89 + 1.567 0.900000 134996 10.00 + 1.602 0.912500 136877 11.43 + 1.647 0.925000 138745 13.33 + 1.741 0.937500 140614 16.00 + 1.797 0.943750 141546 17.78 + 1.870 0.950000 142487 20.00 + 1.934 0.956250 143422 22.86 + 1.992 0.962500 144353 26.67 + 2.053 0.968750 145333 32.00 + 2.073 0.971875 145766 35.56 + 2.107 0.975000 146263 40.00 + 2.131 0.978125 146706 45.71 + 2.171 0.981250 147171 53.33 + 2.227 0.984375 147650 64.00 + 2.247 0.985938 147874 71.11 + 2.265 0.987500 148104 80.00 + 2.283 0.989062 148340 91.43 + 2.301 0.990625 148585 106.67 + 2.323 0.992188 148809 128.00 + 2.337 0.992969 148932 142.22 + 2.353 0.993750 149040 160.00 + 2.369 0.994531 149171 182.86 + 2.383 0.995313 149279 213.33 + 2.395 0.996094 149395 256.00 + 2.403 0.996484 149480 284.44 + 2.407 0.996875 149512 320.00 + 2.419 0.997266 149567 365.71 + 2.431 0.997656 149631 426.67 + 2.439 0.998047 149688 512.00 + 2.443 0.998242 149716 568.89 + 2.449 0.998437 149752 640.00 + 2.455 0.998633 149776 731.43 + 2.461 0.998828 149807 853.33 + 2.469 0.999023 149831 1024.00 + 2.477 0.999121 149851 1137.78 + 2.483 0.999219 149861 1280.00 + 2.499 0.999316 149878 1462.86 + 2.539 0.999414 149890 1706.67 + 2.569 0.999512 149904 2048.00 + 2.587 0.999561 149912 2275.56 + 2.601 0.999609 149920 2560.00 + 2.627 0.999658 149926 2925.71 + 2.643 0.999707 149934 3413.33 + 2.697 0.999756 149941 4096.00 + 2.817 0.999780 149945 4551.11 + 3.025 0.999805 149948 5120.00 + 3.291 0.999829 149952 5851.43 + 3.581 0.999854 149956 6826.67 + 3.851 0.999878 149959 8192.00 + 3.997 0.999890 149961 9102.22 + 4.143 0.999902 149963 10240.00 + 4.259 0.999915 149965 11702.86 + 4.399 0.999927 149967 13653.33 + 4.467 0.999939 149968 16384.00 + 4.503 0.999945 149969 18204.44 + 4.523 0.999951 149970 20480.00 + 4.559 0.999957 149971 23405.71 + 4.611 0.999963 149972 27306.67 + 4.647 0.999969 149973 32768.00 + 4.647 0.999973 149973 36408.89 + 4.739 0.999976 149974 40960.00 + 4.739 0.999979 149974 46811.43 + 4.867 0.999982 149975 54613.33 + 4.867 0.999985 149975 65536.00 + 4.867 0.999986 149975 72817.78 + 4.979 0.999988 149976 81920.00 + 4.979 0.999989 149976 93622.86 + 4.979 0.999991 149976 109226.67 + 4.979 0.999992 149976 131072.00 + 4.979 0.999993 149976 145635.56 + 5.051 0.999994 149977 163840.00 + 5.051 1.000000 149977 inf +#[Mean = 1.024, StdDeviation = 0.465] +#[Max = 5.048, Total count = 149977] +#[Buckets = 27, SubBuckets = 2048] +---------------------------------------------------------- + 179990 requests in 1.00m, 11.50MB read +Requests/sec: 2999.86 +Transfer/sec: 196.28KB diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_scripts/get.lua b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_scripts/get.lua new file mode 100644 index 000000000..ca1bf2a9e --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_scripts/get.lua @@ -0,0 +1,10 @@ +math.randomseed(os.time()) + +wrk.host = "localhost" +wrk.port = "8080" + +function request() + local id = tostring(math.random(0, 1000000)) + local path = "/v0/entity?id=" .. id + return wrk.format("GET", path) +end diff --git a/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_scripts/put.lua b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_scripts/put.lua new file mode 100644 index 000000000..49cbaf088 --- /dev/null +++ b/src/main/java/ru/vk/itmo/test/tyapuevdmitrij/wrk2_scripts/put.lua @@ -0,0 +1,24 @@ +math.randomseed(os.time()) + +function generate_value(length) + local alphabet = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpRrSsTtUuVvWwXxYyZz" + local result = "" + + for _ = 1, length do + local alphabet_index = math.random(1, #alphabet) + result = result .. tostring(alphabet[alphabet_index]) + end + + return result +end + +wrk.host = "localhost" +wrk.port = "8080" + +function request() + local value_length = math.random(5, 20) + wrk.body = generate_value(value_length) + local id = tostring(math.random(0, 1000000)) + local path = "/v0/entity?id=" .. id + return wrk.format("PUT", path) +end \ No newline at end of file