1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.pgm.debug;
12
13 import static java.nio.charset.StandardCharsets.UTF_8;
14 import static org.eclipse.jgit.lib.Constants.HEAD;
15 import static org.eclipse.jgit.lib.Constants.MASTER;
16 import static org.eclipse.jgit.lib.Constants.R_HEADS;
17 import static org.eclipse.jgit.lib.Ref.Storage.NEW;
18 import static org.eclipse.jgit.lib.Ref.Storage.PACKED;
19
20 import java.io.BufferedReader;
21 import java.io.File;
22 import java.io.FileInputStream;
23 import java.io.FileNotFoundException;
24 import java.io.IOException;
25 import java.io.InputStreamReader;
26 import java.util.List;
27
28 import org.eclipse.jgit.internal.storage.file.FileReftableStack;
29 import org.eclipse.jgit.internal.storage.io.BlockSource;
30 import org.eclipse.jgit.internal.storage.reftable.RefCursor;
31 import org.eclipse.jgit.internal.storage.reftable.ReftableReader;
32 import org.eclipse.jgit.lib.Config;
33 import org.eclipse.jgit.lib.ObjectId;
34 import org.eclipse.jgit.lib.ObjectIdRef;
35 import org.eclipse.jgit.lib.Ref;
36 import org.eclipse.jgit.lib.SymbolicRef;
37 import org.eclipse.jgit.pgm.Command;
38 import org.eclipse.jgit.pgm.TextBuiltin;
39 import org.eclipse.jgit.util.RefList;
40 import org.kohsuke.args4j.Argument;
41 import org.kohsuke.args4j.Option;
42
43 @Command
44 class BenchmarkReftable extends TextBuiltin {
45 enum Test {
46 SCAN,
47 SEEK_COLD, SEEK_HOT,
48 BY_ID_COLD, BY_ID_HOT,
49 WRITE_STACK,
50 }
51
52 @Option(name = "--tries")
53 private int tries = 10;
54
55 @Option(name = "--test")
56 private Test test = Test.SCAN;
57
58 @Option(name = "--ref")
59 private String ref;
60
61 @Option(name = "--object-id")
62 private String objectId;
63
64 @Argument(index = 0)
65 private String lsRemotePath;
66
67 @Argument(index = 1)
68 private String reftablePath;
69
70
71 @Override
72 protected void run() throws Exception {
73 switch (test) {
74 case SCAN:
75 scan();
76 break;
77
78 case SEEK_COLD:
79 seekCold(ref);
80 break;
81 case SEEK_HOT:
82 seekHot(ref);
83 break;
84
85 case BY_ID_COLD:
86 byIdCold(ObjectId.fromString(objectId));
87 break;
88 case BY_ID_HOT:
89 byIdHot(ObjectId.fromString(objectId));
90 break;
91 case WRITE_STACK:
92 writeStack();
93 break;
94 }
95 }
96
97 private void printf(String fmt, Object... args) throws IOException {
98 errw.println(String.format(fmt, args));
99 }
100
101 @SuppressWarnings({ "nls", "boxing" })
102 private void writeStack() throws Exception {
103 File dir = new File(reftablePath);
104 File stackFile = new File(reftablePath + ".stack");
105
106 dir.mkdirs();
107
108 long start = System.currentTimeMillis();
109 try (FileReftableStack stack = new FileReftableStack(stackFile, dir,
110 null, () -> new Config())) {
111
112 List<Ref> refs = readLsRemote().asList();
113 for (Ref r : refs) {
114 final long j = stack.getMergedReftable().maxUpdateIndex() + 1;
115 if (!stack.addReftable(w -> {
116 w.setMaxUpdateIndex(j).setMinUpdateIndex(j).begin()
117 .writeRef(r);
118 })) {
119 throw new IOException("should succeed");
120 }
121 }
122 long dt = System.currentTimeMillis() - start;
123 printf("%12s %10d ms avg %6d us/write", "reftable", dt,
124 (dt * 1000) / refs.size());
125 }
126 }
127
128 @SuppressWarnings({ "nls", "boxing" })
129 private void scan() throws Exception {
130 long start, tot;
131
132 start = System.currentTimeMillis();
133 for (int i = 0; i < tries; i++) {
134 readLsRemote();
135 }
136 tot = System.currentTimeMillis() - start;
137 printf("%12s %10d ms %6d ms/run", "packed-refs", tot, tot / tries);
138
139 start = System.currentTimeMillis();
140 for (int i = 0; i < tries; i++) {
141 try (FileInputStream in = new FileInputStream(reftablePath);
142 BlockSource src = BlockSource.from(in);
143 ReftableReader reader = new ReftableReader(src)) {
144 try (RefCursor rc = reader.allRefs()) {
145 while (rc.next()) {
146 rc.getRef();
147 }
148 }
149 }
150 }
151 tot = System.currentTimeMillis() - start;
152 printf("%12s %10d ms %6d ms/run", "reftable", tot, tot / tries);
153 }
154
155 private RefList<Ref> readLsRemote()
156 throws IOException, FileNotFoundException {
157 RefList.Builder<Ref> list = new RefList.Builder<>();
158 try (BufferedReader br = new BufferedReader(new InputStreamReader(
159 new FileInputStream(lsRemotePath), UTF_8))) {
160 Ref last = null;
161 String line;
162 while ((line = br.readLine()) != null) {
163 ObjectId id = ObjectId.fromString(line.substring(0, 40));
164 String name = line.substring(41, line.length());
165 if (last != null && name.endsWith("^{}")) {
166 last = new ObjectIdRef.PeeledTag(PACKED, last.getName(),
167 last.getObjectId(), id);
168 list.set(list.size() - 1, last);
169 continue;
170 }
171
172 if (name.equals(HEAD)) {
173 last = new SymbolicRef(name, new ObjectIdRef.Unpeeled(NEW,
174 R_HEADS + MASTER, null));
175 } else {
176 last = new ObjectIdRef.PeeledNonTag(PACKED, name, id);
177 }
178 list.add(last);
179 }
180 }
181 list.sort();
182 return list.toRefList();
183 }
184
185 @SuppressWarnings({ "nls", "boxing" })
186 private void seekCold(String refName) throws Exception {
187 long start, tot;
188
189 int lsTries = Math.min(tries, 64);
190 start = System.nanoTime();
191 for (int i = 0; i < lsTries; i++) {
192 readLsRemote().get(refName);
193 }
194 tot = System.nanoTime() - start;
195 printf("%12s %10d usec %9.1f usec/run %5d runs", "packed-refs",
196 tot / 1000,
197 (((double) tot) / lsTries) / 1000,
198 lsTries);
199
200 start = System.nanoTime();
201 for (int i = 0; i < tries; i++) {
202 try (FileInputStream in = new FileInputStream(reftablePath);
203 BlockSource src = BlockSource.from(in);
204 ReftableReader reader = new ReftableReader(src)) {
205 try (RefCursor rc = reader.seekRef(refName)) {
206 while (rc.next()) {
207 rc.getRef();
208 }
209 }
210 }
211 }
212 tot = System.nanoTime() - start;
213 printf("%12s %10d usec %9.1f usec/run %5d runs", "reftable",
214 tot / 1000,
215 (((double) tot) / tries) / 1000,
216 tries);
217 }
218
219 @SuppressWarnings({ "nls", "boxing" })
220 private void seekHot(String refName) throws Exception {
221 long start, tot;
222
223 int lsTries = Math.min(tries, 64);
224 start = System.nanoTime();
225 RefList<Ref> lsRemote = readLsRemote();
226 for (int i = 0; i < lsTries; i++) {
227 lsRemote.get(refName);
228 }
229 tot = System.nanoTime() - start;
230 printf("%12s %10d usec %9.1f usec/run %5d runs", "packed-refs",
231 tot / 1000, (((double) tot) / lsTries) / 1000, lsTries);
232
233 start = System.nanoTime();
234 try (FileInputStream in = new FileInputStream(reftablePath);
235 BlockSource src = BlockSource.from(in);
236 ReftableReader reader = new ReftableReader(src)) {
237 for (int i = 0; i < tries; i++) {
238 try (RefCursor rc = reader.seekRef(refName)) {
239 while (rc.next()) {
240 rc.getRef();
241 }
242 }
243 }
244 }
245 tot = System.nanoTime() - start;
246 printf("%12s %10d usec %9.1f usec/run %5d runs", "reftable",
247 tot / 1000, (((double) tot) / tries) / 1000, tries);
248 }
249
250 @SuppressWarnings({ "nls", "boxing" })
251 private void byIdCold(ObjectId id) throws Exception {
252 long start, tot;
253
254 int lsTries = Math.min(tries, 64);
255 start = System.nanoTime();
256 for (int i = 0; i < lsTries; i++) {
257 for (Ref r : readLsRemote()) {
258 if (id.equals(r.getObjectId())) {
259 continue;
260 }
261 }
262 }
263 tot = System.nanoTime() - start;
264 printf("%12s %10d usec %9.1f usec/run %5d runs", "packed-refs",
265 tot / 1000, (((double) tot) / lsTries) / 1000, lsTries);
266
267 start = System.nanoTime();
268 for (int i = 0; i < tries; i++) {
269 try (FileInputStream in = new FileInputStream(reftablePath);
270 BlockSource src = BlockSource.from(in);
271 ReftableReader reader = new ReftableReader(src)) {
272 try (RefCursor rc = reader.byObjectId(id)) {
273 while (rc.next()) {
274 rc.getRef();
275 }
276 }
277 }
278 }
279 tot = System.nanoTime() - start;
280 printf("%12s %10d usec %9.1f usec/run %5d runs", "reftable",
281 tot / 1000, (((double) tot) / tries) / 1000, tries);
282 }
283
284 @SuppressWarnings({ "nls", "boxing" })
285 private void byIdHot(ObjectId id) throws Exception {
286 long start, tot;
287
288 int lsTries = Math.min(tries, 64);
289 start = System.nanoTime();
290 RefList<Ref> lsRemote = readLsRemote();
291 for (int i = 0; i < lsTries; i++) {
292 for (Ref r : lsRemote) {
293 if (id.equals(r.getObjectId())) {
294 continue;
295 }
296 }
297 }
298 tot = System.nanoTime() - start;
299 printf("%12s %10d usec %9.1f usec/run %5d runs", "packed-refs",
300 tot / 1000, (((double) tot) / lsTries) / 1000, lsTries);
301
302 start = System.nanoTime();
303 try (FileInputStream in = new FileInputStream(reftablePath);
304 BlockSource src = BlockSource.from(in);
305 ReftableReader reader = new ReftableReader(src)) {
306 for (int i = 0; i < tries; i++) {
307 try (RefCursor rc = reader.byObjectId(id)) {
308 while (rc.next()) {
309 rc.getRef();
310 }
311 }
312 }
313 }
314 tot = System.nanoTime() - start;
315 printf("%12s %10d usec %9.1f usec/run %5d runs", "reftable",
316 tot / 1000, (((double) tot) / tries) / 1000, tries);
317 }
318 }