comparison test/org/tmatesoft/hg/test/MapTagsToFileRevisions.java @ 438:0d128e09d70f

Yet another alternative to collect tags for a file
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 19 Apr 2012 19:16:45 +0200
parents 9265f7f4b49b
children 6526d8adbc0f
comparison
equal deleted inserted replaced
437:32184ddcf46d 438:0d128e09d70f
3 import static org.tmatesoft.hg.repo.HgRepository.TIP; 3 import static org.tmatesoft.hg.repo.HgRepository.TIP;
4 4
5 import java.io.File; 5 import java.io.File;
6 import java.util.ArrayList; 6 import java.util.ArrayList;
7 import java.util.Arrays; 7 import java.util.Arrays;
8 import java.util.Collections;
8 import java.util.HashMap; 9 import java.util.HashMap;
9 import java.util.LinkedList; 10 import java.util.LinkedList;
10 import java.util.List; 11 import java.util.List;
11 import java.util.Map; 12 import java.util.Map;
12 13
53 } 54 }
54 55
55 56
56 // revision == 2406 - 5 ms per run (baseRevision == 2406) 57 // revision == 2406 - 5 ms per run (baseRevision == 2406)
57 // revision == 2405 - 69 ms per run (baseRevision == 1403) 58 // revision == 2405 - 69 ms per run (baseRevision == 1403)
58 private void measurePatchAffectsArbitraryRevisionRead() throws Exception { 59 public void measurePatchAffectsArbitraryRevisionRead() throws Exception {
59 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython")); 60 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython"));
60 final DoNothingManifestInspector insp = new DoNothingManifestInspector(); 61 final DoNothingManifestInspector insp = new DoNothingManifestInspector();
61 final int revision = 2405; 62 final int revision = 2405;
62 // warm-up. 63 // warm-up.
63 repository.getManifest().walk(revision, revision, insp); 64 repository.getManifest().walk(revision, revision, insp);
179 * RevisionMap.revisionIndex: ~265 ms (almost 100% in #init()) 180 * RevisionMap.revisionIndex: ~265 ms (almost 100% in #init())
180 * each 1000'th revision, total 71 revision: 1 230 vs 270 181 * each 1000'th revision, total 71 revision: 1 230 vs 270
181 * each 2000'th revision, total 36 revision: 620 vs 270 182 * each 2000'th revision, total 36 revision: 620 vs 270
182 * each 3000'th revision, total 24 revision: 410 vs 275 183 * each 3000'th revision, total 24 revision: 410 vs 275
183 */ 184 */
184 private void revisionMap() throws Exception { 185 public void revisionMap() throws Exception {
185 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython")); 186 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython"));
186 final HgChangelog clog = repository.getChangelog(); 187 final HgChangelog clog = repository.getChangelog();
187 ArrayList<Nodeid> revisions = new ArrayList<Nodeid>(); 188 ArrayList<Nodeid> revisions = new ArrayList<Nodeid>();
188 final int step = 5000; 189 final int step = 5000;
189 for (int i = 0, top = clog.getLastRevision(); i < top; i += step) { 190 for (int i = 0, top = clog.getLastRevision(); i < top; i += step) {
208 } 209 }
209 } 210 }
210 System.out.printf("RevisionMap time: %d ms, of that init() %,d ns\n", (System.nanoTime() - s2) / 1000000, s3 - s2); 211 System.out.printf("RevisionMap time: %d ms, of that init() %,d ns\n", (System.nanoTime() - s2) / 1000000, s3 - s2);
211 } 212 }
212 213
213 private void changelogWalk() throws Exception { 214 public void changelogWalk() throws Exception {
214 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython")); 215 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython"));
215 final long start = System.currentTimeMillis(); 216 final long start = System.currentTimeMillis();
216 repository.getChangelog().all(new HgChangelog.Inspector() { 217 repository.getChangelog().all(new HgChangelog.Inspector() {
217 public int xx = 0; 218 public int xx = 0;
218 219
228 // cpyhton: 13 seconds. Of that, cumulative Patch.apply takes 8.8 seconds, RevlogStream.Inspector.next - 1.8 229 // cpyhton: 13 seconds. Of that, cumulative Patch.apply takes 8.8 seconds, RevlogStream.Inspector.next - 1.8
229 System.out.printf("Total time: %d ms\n", System.currentTimeMillis() - start); 230 System.out.printf("Total time: %d ms\n", System.currentTimeMillis() - start);
230 System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory()); 231 System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory());
231 } 232 }
232 233
233 private void manifestWalk() throws Exception { 234 public void manifestWalk() throws Exception {
234 System.out.println(System.getProperty("java.version")); 235 System.out.println(System.getProperty("java.version"));
235 final long start = System.currentTimeMillis(); 236 final long start = System.currentTimeMillis();
236 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython")); 237 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython"));
237 repository.getManifest().walk(0, 10000, new DoNothingManifestInspector()); 238 repository.getManifest().walk(0, 10000, new DoNothingManifestInspector());
238 // cpython: 1,1 sec for 0..1000, 43 sec for 0..10000, 115 sec for 0..20000 (Pool with HashMap) 239 // cpython: 1,1 sec for 0..1000, 43 sec for 0..10000, 115 sec for 0..20000 (Pool with HashMap)
270 tagLocalRevs = copy; 271 tagLocalRevs = copy;
271 } 272 }
272 return tagLocalRevs; 273 return tagLocalRevs;
273 } 274 }
274 275
275 private void collectTagsPerFile() throws HgException, CancelledException { 276 public void collectTagsPerFile() throws HgException, CancelledException {
276 final long start = System.currentTimeMillis(); 277 final long start = System.currentTimeMillis();
277 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython")); 278 final HgRepository repository = new HgLookup().detect(new File("/home/artem/hg/cpython"));
278 final HgTags tags = repository.getTags(); 279 final HgTags tags = repository.getTags();
279 // 280 //
280 // build cache 281 // build cache
281 // 282 //
282 final TagInfo[] allTags = new TagInfo[tags.getAllTags().size()]; 283 final TagInfo[] allTags = new TagInfo[tags.getAllTags().size()];
293 // 294 //
294 collectTagsPerFile_Approach_1(clogrmap, tagLocalRevs, allTags, targetPath); 295 collectTagsPerFile_Approach_1(clogrmap, tagLocalRevs, allTags, targetPath);
295 System.out.printf("Total time: %d ms\n", System.currentTimeMillis() - start); 296 System.out.printf("Total time: %d ms\n", System.currentTimeMillis() - start);
296 297
297 System.out.println("\nApproach 2"); 298 System.out.println("\nApproach 2");
298 collectTagsPerFile_Approach_2(repository, tagLocalRevs, tagLocalRev2TagInfo, allTags, targetPath); 299 collectTagsPerFile_Approach_2(repository, tagLocalRevs, tagLocalRev2TagInfo, targetPath);
299 } 300 }
300 301
301 // Approach 1. Build map with all files, their revisions and corresponding tags 302 // Approach 1. Build map with all files, their revisions and corresponding tags
302 // 303 //
303 private void collectTagsPerFile_Approach_1(final HgRevisionMap clogrmap, final int[] tagLocalRevs, final TagInfo[] allTags, Path targetPath) throws HgException { 304 private void collectTagsPerFile_Approach_1(final HgRevisionMap<HgChangelog> clogrmap, final int[] tagLocalRevs, final TagInfo[] allTags, Path targetPath) throws HgException {
304 HgRepository repository = clogrmap.getRepo(); 305 HgRepository repository = clogrmap.getRepo();
305 final long start = System.currentTimeMillis(); 306 final long start = System.currentTimeMillis();
306 // file2rev2tag value is array of revisions, always of allTags.length. Revision index in the array 307 // file2rev2tag value is array of revisions, always of allTags.length. Revision index in the array
307 // is index of corresponding TagInfo in allTags; 308 // is index of corresponding TagInfo in allTags;
308 final Map<Path, Nodeid[]> file2rev2tag = new HashMap<Path, Nodeid[]>(); 309 final Map<Path, Nodeid[]> file2rev2tag = new HashMap<Path, Nodeid[]>();
370 } 371 }
371 System.out.printf("%3d%7d%s\n", fileRevIndex, changesetRevIndex, associatedTags); 372 System.out.printf("%3d%7d%s\n", fileRevIndex, changesetRevIndex, associatedTags);
372 } 373 }
373 } 374 }
374 375
375 private void collectTagsPerFile_Approach_2(HgRepository repository, final int[] tagLocalRevs, final IntMap<List<TagInfo>> tagLocalRev2TagInfo, TagInfo[] allTags, Path targetPath) throws HgException { 376 private void collectTagsPerFile_Approach_2(HgRepository repository, final int[] tagLocalRevs, final IntMap<List<TagInfo>> tagRevIndex2TagInfo, Path targetPath) throws HgException {
376 // 377 //
377 // Approach 2. No all-file map. Collect file revisions recorded at the time of tagging, 378 // Approach 2. No all-file map. Collect file revisions recorded at the time of tagging,
378 // then for each file revision check if it is among those above, and if yes, take corresponding tags 379 // then for each file revision check if it is among those above, and if yes, take corresponding tags
379 HgDataFile fileNode = repository.getFileNode(targetPath); 380 HgDataFile fileNode = repository.getFileNode(targetPath);
380 final long start2 = System.nanoTime(); 381 final long start2 = System.nanoTime();
381 final int lastRev = fileNode.getLastRevision();
382 final Map<Integer, Nodeid> fileRevisionAtTagRevision = new HashMap<Integer, Nodeid>(); 382 final Map<Integer, Nodeid> fileRevisionAtTagRevision = new HashMap<Integer, Nodeid>();
383 final Map<Nodeid, List<String>> fileRev2TagNames = new HashMap<Nodeid, List<String>>();
383 HgManifest.Inspector collectFileRevAtCset = new HgManifest.Inspector() { 384 HgManifest.Inspector collectFileRevAtCset = new HgManifest.Inspector() {
384 385
385 private int csetRevIndex; 386 private int csetRevIndex;
386 387
387 public boolean next(Nodeid nid, Path fname, Flags flags) { 388 public boolean next(Nodeid nid, Path fname, Flags flags) {
388 fileRevisionAtTagRevision.put(csetRevIndex, nid); 389 fileRevisionAtTagRevision.put(csetRevIndex, nid);
390 if (tagRevIndex2TagInfo.containsKey(csetRevIndex)) {
391 List<String> tags = fileRev2TagNames.get(nid);
392 if (tags == null) {
393 fileRev2TagNames.put(nid, tags = new ArrayList<String>(3));
394 }
395 for (TagInfo ti : tagRevIndex2TagInfo.get(csetRevIndex)) {
396 tags.add(ti.name());
397 }
398 }
389 return true; 399 return true;
390 } 400 }
391 401
392 public boolean end(int manifestRevision) { 402 public boolean end(int manifestRevision) {
393 return true; 403 return true;
397 csetRevIndex = changelogRevision; 407 csetRevIndex = changelogRevision;
398 return true; 408 return true;
399 } 409 }
400 }; 410 };
401 repository.getManifest().walkFileRevisions(targetPath, collectFileRevAtCset,tagLocalRevs); 411 repository.getManifest().walkFileRevisions(targetPath, collectFileRevAtCset,tagLocalRevs);
402 412
403 final long start2a = System.nanoTime(); 413 final long start2a = System.nanoTime();
404 fileNode.indexWalk(0, lastRev, new HgDataFile.RevisionInspector() { 414 fileNode.indexWalk(0, TIP, new HgDataFile.RevisionInspector() {
405 415
406 public void next(int fileRevisionIndex, Nodeid fileRevision, int changesetRevisionIndex) { 416 public void next(int fileRevisionIndex, Nodeid fileRevision, int changesetRevisionIndex) {
407 List<String> associatedTags = new LinkedList<String>(); 417 List<String> associatedTags = new LinkedList<String>();
408 for (int taggetRevision : tagLocalRevs) { 418
419 for (int taggedRevision : tagLocalRevs) {
409 // current file revision can't appear in tags that point to earlier changelog revisions (they got own file revision) 420 // current file revision can't appear in tags that point to earlier changelog revisions (they got own file revision)
410 if (taggetRevision >= changesetRevisionIndex) { 421 if (taggedRevision >= changesetRevisionIndex) {
411 // z points to some changeset with tag 422 // z points to some changeset with tag
412 Nodeid wasKnownAs = fileRevisionAtTagRevision.get(taggetRevision); 423 Nodeid wasKnownAs = fileRevisionAtTagRevision.get(taggedRevision);
413 if (wasKnownAs.equals(fileRevision)) { 424 if (wasKnownAs.equals(fileRevision)) {
414 // has tag associated with changeset at index z 425 // has tag associated with changeset at index z
415 List<TagInfo> tagsAtRev = tagLocalRev2TagInfo.get(taggetRevision); 426 List<TagInfo> tagsAtRev = tagRevIndex2TagInfo.get(taggedRevision);
416 assert tagsAtRev != null; 427 assert tagsAtRev != null;
417 for (TagInfo ti : tagsAtRev) { 428 for (TagInfo ti : tagsAtRev) {
418 associatedTags.add(ti.name()); 429 associatedTags.add(ti.name());
419 } 430 }
420 } 431 }
421 } 432 }
422 } 433 }
434 //
423 System.out.printf("%3d%7d%s\n", fileRevisionIndex, changesetRevisionIndex, associatedTags); 435 System.out.printf("%3d%7d%s\n", fileRevisionIndex, changesetRevisionIndex, associatedTags);
424 } 436 }
425 }); 437 });
438 for (int i = 0, lastRev = fileNode.getLastRevision(); i <= lastRev; i++) {
439 Nodeid fileRevision = fileNode.getRevision(i);
440 List<String> associatedTags2 = fileRev2TagNames.get(fileRevision);
441 int changesetRevIndex = fileNode.getChangesetRevisionIndex(i);
442 System.out.printf("%3d%7d%s\n", i, changesetRevIndex, associatedTags2 == null ? Collections.emptyList() : associatedTags2);
443 }
426 System.out.printf("Alternative total time: %d ms, of that init: %d ms\n", (System.nanoTime() - start2)/1000000, (start2a-start2)/1000000); 444 System.out.printf("Alternative total time: %d ms, of that init: %d ms\n", (System.nanoTime() - start2)/1000000, (start2a-start2)/1000000);
427 System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory()); 445 System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory());
428 } 446 }
429 447
430 static class DoNothingManifestInspector implements HgManifest.Inspector { 448 static class DoNothingManifestInspector implements HgManifest.Inspector {