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