/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.activemq.artemis.tests.extras.benchmarks.journal; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import net.openhft.chronicle.core.jlbh.JLBH; import net.openhft.chronicle.core.jlbh.JLBHOptions; import net.openhft.chronicle.core.jlbh.JLBHTask; import org.apache.activemq.artemis.api.core.ActiveMQBuffer; import org.apache.activemq.artemis.core.io.IOCriticalErrorListener; import org.apache.activemq.artemis.core.io.SequentialFileFactory; import org.apache.activemq.artemis.core.io.mapped.MappedSequentialFileFactory; import org.apache.activemq.artemis.core.io.nio.NIOSequentialFileFactory; import org.apache.activemq.artemis.core.journal.EncodingSupport; import org.apache.activemq.artemis.core.journal.Journal; import org.apache.activemq.artemis.core.journal.RecordInfo; import org.apache.activemq.artemis.core.journal.impl.JournalImpl; public class JournalImplLatencyBench implements JLBHTask { private static final int FILE_SIZE = 1024 * 1024 * 1024; private static final JournalType JOURNAL_TYPE = JournalType.MAPPED; private static final int ITERATIONS = 100_000; private static final int WARMUP_ITERATIONS = 20_000; private static final int TARGET_THROUGHPUT = 50_000; private static final int TESTS = 5; private static int TOTAL_MESSAGES = (ITERATIONS * TESTS + WARMUP_ITERATIONS); private static int ENCODED_SIZE = 8; private static int CHUNK_BYTES = FILE_SIZE; private static int OVERLAP_BYTES = CHUNK_BYTES / 4; private final SequentialFileFactory sequentialFileFactory; private Journal journal; private EncodingSupport encodingSupport; private JLBH jlbh; private long id; public JournalImplLatencyBench(SequentialFileFactory sequentialFileFactory) { this.sequentialFileFactory = sequentialFileFactory; } public static void main(String[] args) throws IOException { final File journalDir = Files.createTempDirectory("seq_files").toFile(); journalDir.deleteOnExit(); final boolean buffered = false; final int bufferSize = 4096; final int bufferTimeout = 0; final int maxIO = -1; final boolean logRates = false; final IOCriticalErrorListener criticalErrorListener = null; final SequentialFileFactory sequentialFileFactory; switch (JOURNAL_TYPE) { case MAPPED: sequentialFileFactory = new MappedSequentialFileFactory(journalDir, criticalErrorListener).chunkBytes(CHUNK_BYTES).overlapBytes(OVERLAP_BYTES); break; case NIO: sequentialFileFactory = new NIOSequentialFileFactory(journalDir, buffered, bufferSize, bufferTimeout, maxIO, logRates, criticalErrorListener); break; default: throw new AssertionError("!?"); } final JLBHOptions lth = new JLBHOptions().warmUpIterations(WARMUP_ITERATIONS).iterations(ITERATIONS).throughput(TARGET_THROUGHPUT).runs(TESTS).recordOSJitter(true).accountForCoordinatedOmmission(true).jlbhTask(new JournalImplLatencyBench(sequentialFileFactory)); new JLBH(lth).start(); } @Override public void init(JLBH jlbh) { id = 0; this.jlbh = jlbh; int numFiles = (int) ((TOTAL_MESSAGES * 1024 + 512) / FILE_SIZE * 1.3); if (numFiles < 2) { numFiles = 2; } this.journal = new JournalImpl(FILE_SIZE, numFiles, numFiles, 0, 0, sequentialFileFactory, "activemq-data", "amq", Integer.MAX_VALUE); this.encodingSupport = NilEncodingSupport.Instance; try { journal.start(); journal.load(new ArrayList<RecordInfo>(), null, null); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void run(long startTimeNS) { id++; try { journal.appendAddRecord(id, (byte) 0, encodingSupport, false); } catch (Exception e) { throw new RuntimeException(e); } jlbh.sample(System.nanoTime() - startTimeNS); } @Override public void complete() { try { journal.stop(); for (File journalFile : sequentialFileFactory.getDirectory().listFiles()) { journalFile.deleteOnExit(); } } catch (Exception e) { throw new RuntimeException(e); } } private enum JournalType { MAPPED, NIO } private enum NilEncodingSupport implements EncodingSupport { Instance; @Override public int getEncodeSize() { return ENCODED_SIZE; } @Override public void encode(ActiveMQBuffer buffer) { final int writerIndex = buffer.writerIndex(); for (int i = 0; i < ENCODED_SIZE; i++) { buffer.writeByte((byte) 0); } buffer.writerIndex(writerIndex + ENCODED_SIZE); } @Override public void decode(ActiveMQBuffer buffer) { throw new UnsupportedOperationException(); } } }