aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.benchmarks/src
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit.benchmarks/src')
-rw-r--r--org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/CreateFileSnapshotBenchmark.java75
-rw-r--r--org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/FileMoveBenchmark.java134
-rw-r--r--org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java200
-rw-r--r--org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/LookupFileStoreBenchmark.java61
-rw-r--r--org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/RawTextBenchmark.java454
-rw-r--r--org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/SHA1Benchmark.java99
-rw-r--r--org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/SimpleLruCacheBenchmark.java77
-rw-r--r--org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/revwalk/DateRevQueueBenchmark.java137
8 files changed, 1237 insertions, 0 deletions
diff --git a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/CreateFileSnapshotBenchmark.java b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/CreateFileSnapshotBenchmark.java
new file mode 100644
index 0000000000..913ca5a9e8
--- /dev/null
+++ b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/CreateFileSnapshotBenchmark.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019, Matthias Sohn <matthias.sohn@sap.com> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.benchmarks;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jgit.internal.storage.file.FileSnapshot;
+import org.eclipse.jgit.util.FileUtils;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@State(Scope.Thread)
+public class CreateFileSnapshotBenchmark {
+
+ Path path;
+
+ Path testDir;
+
+ @Setup
+ public void setupBenchmark() throws IOException {
+ testDir = Files.createTempDirectory("dir");
+ path = testDir.resolve("toSnapshot");
+ Files.createFile(path);
+ }
+
+ @TearDown
+ public void teardown() throws IOException {
+ FileUtils.delete(testDir.toFile(), FileUtils.RECURSIVE | FileUtils.RETRY);
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @Warmup(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+ @Measurement(iterations = 5, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+ public Path testCreateFile() throws IOException {
+ return Files.createTempFile(testDir, "create", "");
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public FileSnapshot testCreateFileSnapshot() {
+ return FileSnapshot.save(path.toFile());
+ }
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include(CreateFileSnapshotBenchmark.class.getSimpleName())
+ .forks(1).jvmArgs("-ea").build();
+ new Runner(opt).run();
+ }
+}
diff --git a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/FileMoveBenchmark.java b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/FileMoveBenchmark.java
new file mode 100644
index 0000000000..2ec5f1f19a
--- /dev/null
+++ b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/FileMoveBenchmark.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2020, Matthias Sohn <matthias.sohn@sap.com> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.benchmarks;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jgit.util.FileUtils;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@State(Scope.Thread)
+public class FileMoveBenchmark {
+ int i;
+
+ Path testDir;
+
+ Path targetDir;
+
+ @Setup
+ public void setupBenchmark() throws IOException {
+ testDir = Files.createTempDirectory("dir");
+ targetDir = testDir.resolve("target");
+ Files.createDirectory(targetDir);
+ }
+
+ @TearDown
+ public void teardown() throws IOException {
+ FileUtils.delete(testDir.toFile(),
+ FileUtils.RECURSIVE | FileUtils.RETRY);
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ @Warmup(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
+ @Measurement(iterations = 5, time = 5000, timeUnit = TimeUnit.MILLISECONDS)
+ public Path moveFileToExistingDir() throws IOException {
+ i++;
+ Path tmp = testDir.resolve("tmp" + i++);
+ Files.createFile(tmp);
+ Path targetDirectory = targetDir;
+ Path targetFile = targetDirectory.resolve("tmp" + i);
+ try {
+ return Files.move(tmp, targetFile, StandardCopyOption.ATOMIC_MOVE);
+ } catch (NoSuchFileException e) {
+ Files.createDirectory(targetDirectory);
+ return Files.move(tmp, targetFile, StandardCopyOption.ATOMIC_MOVE);
+ }
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ @Warmup(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
+ @Measurement(iterations = 5, time = 5000, timeUnit = TimeUnit.MILLISECONDS)
+ public Path moveFileToExistingDirExists() throws IOException {
+ Path tmp = testDir.resolve("tmp" + i++);
+ Files.createFile(tmp);
+ Path targetDirectory = targetDir;
+ Path targetFile = targetDir.resolve("tmp" + i);
+ if (!targetDirectory.toFile().exists()) {
+ Files.createDirectory(targetDirectory);
+ }
+ return Files.move(tmp, targetFile, StandardCopyOption.ATOMIC_MOVE);
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ @Warmup(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
+ @Measurement(iterations = 5, time = 5000, timeUnit = TimeUnit.MILLISECONDS)
+ public Path moveFileToMissingDir() throws IOException {
+ i++;
+ Path tmp = testDir.resolve("tmp" + i);
+ Files.createFile(tmp);
+ Path targetDirectory = testDir.resolve("target" + i);
+ Path targetFile = targetDirectory.resolve("tmp" + i);
+ try {
+ return Files.move(tmp, targetFile, StandardCopyOption.ATOMIC_MOVE);
+ } catch (NoSuchFileException e) {
+ Files.createDirectory(targetDirectory);
+ return Files.move(tmp, targetFile, StandardCopyOption.ATOMIC_MOVE);
+ }
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ @Warmup(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS)
+ @Measurement(iterations = 5, time = 5000, timeUnit = TimeUnit.MILLISECONDS)
+ public Path moveFileToMissingDirExists() throws IOException {
+ i++;
+ Path tmp = testDir.resolve("tmp" + i);
+ Files.createFile(tmp);
+ Path targetDirectory = testDir.resolve("target" + i);
+ Path targetFile = targetDirectory.resolve("tmp" + i);
+ if (!targetDirectory.toFile().exists()) {
+ Files.createDirectory(targetDirectory);
+ }
+ return Files.move(tmp, targetFile, StandardCopyOption.ATOMIC_MOVE);
+ }
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include(FileMoveBenchmark.class
+ .getSimpleName())
+ .forks(1).jvmArgs("-ea").build();
+ new Runner(opt).run();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java
new file mode 100644
index 0000000000..44e862e7c8
--- /dev/null
+++ b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/GetRefsBenchmark.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2021, Luca Milanesio <luca.milanesio@gmail.com> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.benchmarks;
+
+import static org.eclipse.jgit.transport.ReceiveCommand.Type.CREATE;
+
+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.List;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.internal.storage.file.FileReftableDatabase;
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.lib.BatchRefUpdate;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.CoreConfig.TrustStat;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RepositoryCache;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.lib.TextProgressMonitor;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.ReceiveCommand;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.FileUtils;
+import org.junit.Assume;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@State(Scope.Thread)
+public class GetRefsBenchmark {
+
+ ThreadLocalRandom branchIndex = ThreadLocalRandom.current();
+
+ @State(Scope.Benchmark)
+ public static class BenchmarkState {
+
+ @Param({ "true", "false" })
+ boolean useRefTable;
+
+ @Param({ "true", "false" })
+ boolean autoRefresh;
+
+ @Param({ "100", "1000", "10000", "100000" })
+ int numBranches;
+
+ @Param({ "ALWAYS", "AFTER_OPEN", "NEVER" })
+ TrustStat trustStat;
+
+ List<String> branches = new ArrayList<>(numBranches);
+
+ Path testDir;
+
+ Repository repo;
+
+ @Setup
+ @SuppressWarnings("boxing")
+ public void setupBenchmark() throws IOException, GitAPIException {
+ // if we use RefDirectory skip autoRefresh = false
+ Assume.assumeTrue(useRefTable || autoRefresh);
+
+ String firstBranch = "firstbranch";
+ testDir = Files.createDirectory(Paths.get("testrepos"));
+ String repoName = "branches-" + numBranches + "-trustStat-"
+ + trustStat + "-" + refDatabaseType();
+ Path workDir = testDir.resolve(repoName);
+ Path repoPath = workDir.resolve(".git");
+ Git git = Git.init().setDirectory(workDir.toFile()).call();
+ RevCommit firstCommit = git.commit().setMessage("First commit")
+ .call();
+ git.branchCreate().setName(firstBranch).call();
+
+ StoredConfig cfg = git.getRepository().getConfig();
+ if (useRefTable) {
+ ((FileRepository) git.getRepository()).convertRefStorage(
+ ConfigConstants.CONFIG_REF_STORAGE_REFTABLE, false,
+ false);
+ FileReftableDatabase refdb = (FileReftableDatabase) git
+ .getRepository().getRefDatabase();
+ refdb.setAutoRefresh(autoRefresh);
+ } else {
+ cfg.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_TRUST_STAT,
+ trustStat);
+ }
+ cfg.setInt(ConfigConstants.CONFIG_RECEIVE_SECTION, null,
+ "maxCommandBytes", Integer.MAX_VALUE);
+ cfg.save();
+
+ repo = RepositoryCache.open(RepositoryCache.FileKey
+ .lenient(repoPath.toFile(), FS.DETECTED));
+
+ System.out.println("Preparing test");
+ System.out.println("- repository: \t\t" + repoPath);
+ System.out.println("- refDatabase: \t\t" + refDatabaseType());
+ System.out.println("- autoRefresh: \t\t" + autoRefresh);
+ System.out.println("- trustStat: \t" + trustStat);
+ System.out.println("- branches: \t\t" + numBranches);
+
+ BatchRefUpdate u = repo.getRefDatabase().newBatchUpdate();
+
+ branches = IntStream.range(0, numBranches)
+ .mapToObj(i -> "branch/" + i % 100 + "/" + i)
+ .collect(Collectors.toList());
+ for (String branch : branches) {
+ u.addCommand(new ReceiveCommand(ObjectId.zeroId(),
+ firstCommit.toObjectId(), Constants.R_HEADS + branch,
+ CREATE));
+ }
+
+ System.out.println();
+ System.out.print(
+ String.format("Creating %d branches ... ", numBranches));
+
+ try (RevWalk rw = new RevWalk(repo)) {
+ u.execute(rw, new TextProgressMonitor());
+ }
+ System.out.println("DONE");
+ }
+
+ private String refDatabaseType() {
+ return useRefTable ? "reftable" : "refdir";
+ }
+
+ @TearDown
+ public void teardown() throws IOException {
+ repo.close();
+ FileUtils.delete(testDir.toFile(),
+ FileUtils.RECURSIVE | FileUtils.RETRY);
+ }
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ @Warmup(iterations = 2, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(2)
+ public void testGetExactRef(Blackhole blackhole, BenchmarkState state)
+ throws IOException {
+ String branchName = state.branches
+ .get(branchIndex.nextInt(state.numBranches));
+ blackhole.consume(state.repo.exactRef(branchName));
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ @Warmup(iterations = 2, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(2)
+ public void testGetRefsByPrefix(Blackhole blackhole, BenchmarkState state)
+ throws IOException {
+ String branchPrefix = "refs/heads/branch/" + branchIndex.nextInt(100)
+ + "/";
+ blackhole.consume(
+ state.repo.getRefDatabase().getRefsByPrefix(branchPrefix));
+ }
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include(GetRefsBenchmark.class.getSimpleName())
+ // .addProfiler(StackProfiler.class)
+ // .addProfiler(GCProfiler.class)
+ .forks(1).jvmArgs("-ea").build();
+ new Runner(opt).run();
+ }
+}
diff --git a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/LookupFileStoreBenchmark.java b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/LookupFileStoreBenchmark.java
new file mode 100644
index 0000000000..e9c9ef36a0
--- /dev/null
+++ b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/LookupFileStoreBenchmark.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019, Matthias Sohn <matthias.sohn@sap.com> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.benchmarks;
+
+import java.io.IOException;
+import java.nio.file.FileStore;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jgit.util.FileUtils;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@State(Scope.Thread)
+public class LookupFileStoreBenchmark {
+
+ Path path;
+
+ @Setup
+ public void setupBenchmark() throws IOException {
+ path = Files.createTempFile("test", "x");
+ }
+
+ @TearDown
+ public void teardown() throws IOException {
+ FileUtils.delete(path.toFile(), FileUtils.RETRY);
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public FileStore testLookupFileStore() throws IOException {
+ FileStore fs = Files.getFileStore(path);
+ return fs;
+ }
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include(LookupFileStoreBenchmark.class.getSimpleName())
+ .forks(1).jvmArgs("-ea").build();
+ new Runner(opt).run();
+ }
+}
diff --git a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/RawTextBenchmark.java b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/RawTextBenchmark.java
new file mode 100644
index 0000000000..19297ebebb
--- /dev/null
+++ b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/RawTextBenchmark.java
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2022, Matthias Sohn <matthias.sohn@sap.com> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.benchmarks;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.eclipse.jgit.diff.RawText.getBufferSize;
+import static org.eclipse.jgit.diff.RawText.isBinary;
+import static org.eclipse.jgit.diff.RawText.isCrLfText;
+
+@State(Scope.Thread)
+public class RawTextBenchmark {
+
+ @State(Scope.Benchmark)
+ public static class BenchmarkState {
+
+ @Param({"1", "2", "3", "4", "5", "6"})
+ int testIndex;
+
+ @Param({"false", "true"})
+ boolean complete;
+
+ byte[] bytes;
+
+ @Setup
+ public void setupBenchmark() {
+ switch (testIndex) {
+ case 1: {
+ byte[] tmpBytes = "a".repeat(102400).getBytes();
+ bytes = tmpBytes;
+ break;
+ }
+ case 2: {
+ byte[] tmpBytes = "a".repeat(102400).getBytes();
+ byte[] tmpBytes2 = new byte[tmpBytes.length + 1];
+ System.arraycopy(tmpBytes, 0, tmpBytes2, 0, tmpBytes.length);
+ tmpBytes2[500] = '\0';
+ tmpBytes2[tmpBytes.length] = '\0';
+ bytes = tmpBytes2;
+ break;
+ }
+ case 3: {
+ byte[] tmpBytes = "a".repeat(102400).getBytes();
+ byte[] tmpBytes2 = new byte[tmpBytes.length + 1];
+ System.arraycopy(tmpBytes, 0, tmpBytes2, 0, tmpBytes.length);
+ tmpBytes2[500] = '\r';
+ tmpBytes2[tmpBytes.length] = '\r';
+ bytes = tmpBytes2;
+ break;
+ }
+ case 4: {
+ byte[] tmpBytes = "a".repeat(102400).getBytes();
+ byte[] tmpBytes2 = new byte[tmpBytes.length + 1];
+ System.arraycopy(tmpBytes, 0, tmpBytes2, 0, tmpBytes.length);
+ tmpBytes2[499] = '\r';
+ tmpBytes2[500] = '\n';
+ tmpBytes2[tmpBytes.length - 1] = '\r';
+ tmpBytes2[tmpBytes.length] = '\n';
+ bytes = tmpBytes2;
+ break;
+ }
+ case 5: {
+ byte[] tmpBytes = "a".repeat(102400).getBytes();
+ tmpBytes[0] = '\0';
+ bytes = tmpBytes;
+ break;
+ }
+ case 6: {
+ byte[] tmpBytes = "a".repeat(102400).getBytes();
+ tmpBytes[0] = '\r';
+ bytes = tmpBytes;
+ break;
+ }
+ default:
+ }
+ }
+
+ @TearDown
+ public void teardown() {
+ }
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @Warmup(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(1)
+ public void testIsCrLfTextOld(Blackhole blackhole, BenchmarkState state) {
+ blackhole.consume(
+ isCrLfTextOld(
+ state.bytes,
+ state.bytes.length,
+ state.complete
+ )
+ );
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @Warmup(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(1)
+ public void testIsCrLfTextNewCandidate1(Blackhole blackhole, BenchmarkState state) {
+ blackhole.consume(
+ isCrLfTextNewCandidate1(
+ state.bytes,
+ state.bytes.length,
+ state.complete
+ )
+ );
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @Warmup(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(1)
+ public void testIsCrLfTextNewCandidate2(Blackhole blackhole, BenchmarkState state) {
+ blackhole.consume(
+ isCrLfTextNewCandidate2(
+ state.bytes,
+ state.bytes.length,
+ state.complete
+ )
+ );
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @Warmup(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(1)
+ public void testIsCrLfTextNewCandidate3(Blackhole blackhole, BenchmarkState state) {
+ blackhole.consume(
+ isCrLfTextNewCandidate3(
+ state.bytes,
+ state.bytes.length,
+ state.complete
+ )
+ );
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @Warmup(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(1)
+ public void testIsCrLfTextNew(Blackhole blackhole, BenchmarkState state) {
+ blackhole.consume(
+ isCrLfText(
+ state.bytes,
+ state.bytes.length,
+ state.complete
+ )
+ );
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @Warmup(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(1)
+ public void testIsBinaryOld(Blackhole blackhole, BenchmarkState state) {
+ blackhole.consume(
+ isBinaryOld(
+ state.bytes,
+ state.bytes.length,
+ state.complete
+ )
+ );
+ }
+
+
+ @Benchmark
+ @BenchmarkMode({Mode.AverageTime})
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @Warmup(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(1)
+ public void testIsBinaryNew(Blackhole blackhole, BenchmarkState state) {
+ blackhole.consume(
+ isBinary(
+ state.bytes,
+ state.bytes.length,
+ state.complete
+ )
+ );
+ }
+
+
+ /**
+ * Determine heuristically whether a byte array represents binary (as
+ * opposed to text) content.
+ *
+ * @param raw
+ * the raw file content.
+ * @param length
+ * number of bytes in {@code raw} to evaluate. This should be
+ * {@code raw.length} unless {@code raw} was over-allocated by
+ * the caller.
+ * @param complete
+ * whether {@code raw} contains the whole data
+ * @return true if raw is likely to be a binary file, false otherwise
+ * @since 6.0
+ */
+ public static boolean isBinaryOld(byte[] raw, int length, boolean complete) {
+ // Similar heuristic as C Git. Differences:
+ // - limited buffer size; may be only the beginning of a large blob
+ // - no counting of printable vs. non-printable bytes < 0x20 and 0x7F
+ int maxLength = getBufferSize();
+ boolean isComplete = complete;
+ if (length > maxLength) {
+ // We restrict the length in all cases to getBufferSize() to get
+ // predictable behavior. Sometimes we load streams, and sometimes we
+ // have the full data in memory. With streams, we never look at more
+ // than the first getBufferSize() bytes. If we looked at more when
+ // we have the full data, different code paths in JGit might come to
+ // different conclusions.
+ length = maxLength;
+ isComplete = false;
+ }
+ byte last = 'x'; // Just something inconspicuous.
+ for (int ptr = 0; ptr < length; ptr++) {
+ byte curr = raw[ptr];
+ if (isBinary(curr, last)) {
+ return true;
+ }
+ last = curr;
+ }
+ if (isComplete) {
+ // Buffer contains everything...
+ return last == '\r'; // ... so this must be a lone CR
+ }
+ return false;
+ }
+
+ /**
+ * Determine heuristically whether a byte array represents text content
+ * using CR-LF as line separator.
+ *
+ * @param raw the raw file content.
+ * @param length number of bytes in {@code raw} to evaluate.
+ * @param complete whether {@code raw} contains the whole data
+ * @return {@code true} if raw is likely to be CR-LF delimited text,
+ * {@code false} otherwise
+ * @since 6.0
+ */
+ public static boolean isCrLfTextOld(byte[] raw, int length, boolean complete) {
+ boolean has_crlf = false;
+ byte last = 'x'; // Just something inconspicuous
+ for (int ptr = 0; ptr < length; ptr++) {
+ byte curr = raw[ptr];
+ if (isBinary(curr, last)) {
+ return false;
+ }
+ if (curr == '\n' && last == '\r') {
+ has_crlf = true;
+ }
+ last = curr;
+ }
+ if (last == '\r') {
+ if (complete) {
+ // Lone CR: it's binary after all.
+ return false;
+ }
+ // Tough call. If the next byte, which we don't have, would be a
+ // '\n', it'd be a CR-LF text, otherwise it'd be binary. Just decide
+ // based on what we already scanned; it wasn't binary until now.
+ }
+ return has_crlf;
+ }
+
+ /**
+ * Determine heuristically whether a byte array represents text content
+ * using CR-LF as line separator.
+ *
+ * @param raw
+ * the raw file content.
+ * @param length
+ * number of bytes in {@code raw} to evaluate.
+ * @return {@code true} if raw is likely to be CR-LF delimited text,
+ * {@code false} otherwise
+ * @param complete
+ * whether {@code raw} contains the whole data
+ * @since 6.0
+ */
+ public static boolean isCrLfTextNewCandidate1(byte[] raw, int length, boolean complete) {
+ boolean has_crlf = false;
+
+ // first detect empty
+ if (length <= 0) {
+ return false;
+ }
+
+ // next detect '\0'
+ for (int reversePtr = length - 1; reversePtr >= 0; --reversePtr) {
+ if (raw[reversePtr] == '\0') {
+ return false;
+ }
+ }
+
+ // if '\r' be last, then if complete then return non-crlf
+ if (raw[length - 1] == '\r' && complete) {
+ return false;
+ }
+
+ for (int ptr = 0; ptr < length - 1; ptr++) {
+ byte curr = raw[ptr];
+ if (curr == '\r') {
+ byte next = raw[ptr + 1];
+ if (next != '\n') {
+ return false;
+ }
+ // else
+ // we have crlf here
+ has_crlf = true;
+ // as next is '\n', it can never be '\r', just skip it from next check
+ ++ptr;
+ }
+ }
+
+ return has_crlf;
+ }
+
+ /**
+ * Determine heuristically whether a byte array represents text content
+ * using CR-LF as line separator.
+ *
+ * @param raw
+ * the raw file content.
+ * @param length
+ * number of bytes in {@code raw} to evaluate.
+ * @return {@code true} if raw is likely to be CR-LF delimited text,
+ * {@code false} otherwise
+ * @param complete
+ * whether {@code raw} contains the whole data
+ * @since 6.0
+ */
+ public static boolean isCrLfTextNewCandidate2(byte[] raw, int length, boolean complete) {
+ boolean has_crlf = false;
+
+ // first detect empty
+ if (length <= 0) {
+ return false;
+ }
+
+ // if '\r' be last, then if complete then return non-crlf
+ byte last = raw[length - 1];
+ if (last == '\0' || last == '\r' && complete) {
+ return false;
+ }
+
+ for (int ptr = 0; ptr < length - 1; ptr++) {
+ byte b = raw[ptr];
+ switch (b) {
+ case '\0':
+ return false;
+ case '\r': {
+ ++ptr;
+ b = raw[ptr];
+ if (b != '\n') {
+ return false;
+ }
+ // else
+ // we have crlf here
+ has_crlf = true;
+ // as next is '\n', it can never be '\r', just skip it from next check
+ break;
+ }
+ default:
+ // do nothing;
+ break;
+ }
+ }
+
+ return has_crlf;
+ }
+
+ /**
+ * Determine heuristically whether a byte array represents text content
+ * using CR-LF as line separator.
+ *
+ * @param raw
+ * the raw file content.
+ * @param length
+ * number of bytes in {@code raw} to evaluate.
+ * @return {@code true} if raw is likely to be CR-LF delimited text,
+ * {@code false} otherwise
+ * @param complete
+ * whether {@code raw} contains the whole data
+ * @since 6.0
+ */
+ public static boolean isCrLfTextNewCandidate3(byte[] raw, int length, boolean complete) {
+ boolean has_crlf = false;
+
+ int ptr = -1;
+ byte current;
+ while (ptr < length - 2) {
+ current = raw[++ptr];
+ if ('\0' == current || '\r' == current && (raw[++ptr] != '\n' || !(has_crlf = true))) {
+ return false;
+ }
+ }
+
+ if (ptr == length - 2) {
+ // if '\r' be last, then if isComplete then return binary
+ current = raw[++ptr];
+ if('\0' == current || '\r' == current && complete){
+ return false;
+ }
+ }
+
+ return has_crlf;
+ }
+
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include(RawTextBenchmark.class.getSimpleName())
+ .forks(1).jvmArgs("-ea").build();
+ new Runner(opt).run();
+ }
+}
diff --git a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/SHA1Benchmark.java b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/SHA1Benchmark.java
new file mode 100644
index 0000000000..a2b59339bb
--- /dev/null
+++ b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/SHA1Benchmark.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022, Matthias Sohn <matthias.sohn@sap.com> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.benchmarks;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jgit.junit.MockSystemReader;
+import org.eclipse.jgit.util.SystemReader;
+import org.eclipse.jgit.util.sha1.SHA1;
+import org.eclipse.jgit.util.sha1.SHA1.Sha1Implementation;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@State(Scope.Thread)
+public class SHA1Benchmark {
+
+ @State(Scope.Benchmark)
+ public static class BenchmarkState {
+
+ @Param({ "1", "2", "4", "8", "16", "32", "64" })
+ int size;
+
+ @Param({ "false", "true" })
+ boolean detectCollision;
+
+ @Param({ "java", "jdkNative" })
+ String impl;
+
+ private SecureRandom rnd;
+
+ byte[] content;
+
+ @Setup
+ public void setupBenchmark() {
+ SystemReader.setInstance(new MockSystemReader());
+ if (impl.equalsIgnoreCase(Sha1Implementation.JDKNATIVE.name())) {
+ System.setProperty("org.eclipse.jgit.util.sha1.implementation",
+ Sha1Implementation.JDKNATIVE.name());
+ }
+ content = new byte[size * 1024];
+ try {
+ rnd = SecureRandom.getInstanceStrong();
+ } catch (NoSuchAlgorithmException e) {
+ // ignore
+ }
+ rnd.nextBytes(content);
+ }
+
+ @TearDown
+ public void teardown() {
+ SystemReader.setInstance(null);
+ rnd = null;
+ }
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.MICROSECONDS)
+ @Warmup(iterations = 2, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+ @Measurement(iterations = 2, time = 5, timeUnit = TimeUnit.SECONDS)
+ @Fork(1)
+ public void testSHA1(Blackhole blackhole, BenchmarkState state) {
+ SHA1 hash = SHA1.newInstance();
+ hash.setDetectCollision(state.detectCollision);
+ hash.update(state.content);
+ blackhole.consume(hash.digest());
+ }
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include(SHA1Benchmark.class.getSimpleName())
+ .forks(1).jvmArgs("-ea").build();
+ new Runner(opt).run();
+ }
+}
diff --git a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/SimpleLruCacheBenchmark.java b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/SimpleLruCacheBenchmark.java
new file mode 100644
index 0000000000..caefd75d9b
--- /dev/null
+++ b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/benchmarks/SimpleLruCacheBenchmark.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019, Matthias Sohn <matthias.sohn@sap.com> and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.benchmarks;
+
+import java.security.SecureRandom;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jgit.util.SimpleLruCache;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Group;
+import org.openjdk.jmh.annotations.GroupThreads;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@State(Scope.Benchmark)
+public class SimpleLruCacheBenchmark {
+
+ SecureRandom rnd = new SecureRandom();
+
+ private volatile SimpleLruCache<String, String> cache = new SimpleLruCache<>(
+ 100, 0.2f);
+
+ private volatile int i;
+
+ @Setup
+ public void setupBenchmark() {
+ i = rnd.nextInt(250);
+ }
+
+ @TearDown
+ public void teardown() {
+ cache = null;
+ }
+
+ @Benchmark
+ @Group("readwrite")
+ @GroupThreads(1)
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public SimpleLruCache<String, String> testCacheWrite() {
+ cache.put("k" + i, "v" + i);
+ return cache;
+ }
+
+ @Benchmark
+ @Group("readwrite")
+ @GroupThreads(1)
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ public SimpleLruCache<String, String> testCacheRead() {
+ cache.get("k" + i);
+ return cache;
+ }
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include(SimpleLruCacheBenchmark.class.getSimpleName())
+ .forks(1).jvmArgs("-ea").build();
+ new Runner(opt).run();
+ }
+}
diff --git a/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/revwalk/DateRevQueueBenchmark.java b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/revwalk/DateRevQueueBenchmark.java
new file mode 100644
index 0000000000..71075a8b4c
--- /dev/null
+++ b/org.eclipse.jgit.benchmarks/src/org/eclipse/jgit/revwalk/DateRevQueueBenchmark.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2023, GerritForge Ltd
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.revwalk;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.util.FileUtils;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Param;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@State(Scope.Thread)
+public class DateRevQueueBenchmark {
+
+ ThreadLocalRandom commitsIndex = ThreadLocalRandom.current();
+
+ @State(Scope.Benchmark)
+ public static class BenchmarkState {
+
+ @Param({ "5", "10", "50", "100", "500", "1000", "5000", "10000",
+ "50000", "100000", "500000" })
+ int numCommits;
+
+ @Param({ "true", "false" })
+ boolean usePriorityQueue;
+
+ int low, count;
+
+ RevCommit[] commits = new RevCommit[numCommits];
+
+ private Path testDir;
+
+ private TestRepository<Repository> repoUtil;
+
+ DateRevQueue queue;
+
+ @Setup
+ public void setupBenchmark() throws Exception {
+ testDir = Files.createTempDirectory("testrepos");
+ String repoName = "commits-" + numCommits + "-usePriorityQueue-"
+ + usePriorityQueue;
+ Path workDir = testDir.resolve(repoName);
+ Git git = Git.init().setDirectory(workDir.toFile()).call();
+ repoUtil = new TestRepository<>(git.getRepository());
+
+ RevCommit parent = repoUtil.commit().create();
+ commits = new RevCommit[numCommits];
+ commits[0] = parent;
+ for (int i = 1; i < numCommits; i++) {
+ parent = repoUtil.parseBody(repoUtil.commit(i, parent));
+ commits[i] = parent;
+ if (i % 10000 == 0) {
+ System.out.println(" " + i + " done");
+ }
+ }
+
+ if (usePriorityQueue) {
+ queue = new DateRevPriorityQueue(false);
+ } else {
+ queue = new DateRevQueue(false);
+ }
+
+ low = 9 * numCommits / 10;
+ ThreadLocalRandom random = ThreadLocalRandom.current();
+ // add 90% * numCommits commits, benchmark adding commits from
+ // 90-100%
+ for (int i = 0; i < low; i++) {
+ RevCommit commit = commits[random.nextInt(numCommits)];
+ queue.add(commit);
+ ++count;
+ }
+ }
+
+ @TearDown(Level.Invocation)
+ public void check() {
+ // if queue is full remove 10% of its entries
+ if (++count == numCommits) {
+ do {
+ queue.next();
+ } while (--count > low);
+ }
+ }
+
+ @TearDown
+ public void teardown() throws IOException {
+ repoUtil.close();
+ FileUtils.delete(testDir.toFile(),
+ FileUtils.RECURSIVE | FileUtils.RETRY);
+ }
+ }
+
+ @Benchmark
+ @BenchmarkMode({ Mode.AverageTime })
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @Warmup(iterations = 2, time = 100, timeUnit = TimeUnit.MILLISECONDS)
+ @Measurement(iterations = 10, time = 10, timeUnit = TimeUnit.SECONDS)
+ public void testDataRevQueue(BenchmarkState state) throws Exception {
+ RevCommit commit = state.commits[commitsIndex
+ .nextInt(state.numCommits)];
+ state.queue.add(commit);
+ }
+
+ public static void main(String[] args) throws RunnerException {
+ Options opt = new OptionsBuilder()
+ .include(DateRevQueueBenchmark.class.getSimpleName()).forks(1)
+ .jvmArgs("-ea").build();
+ new Runner(opt).run();
+ }
+
+}