comparison test/org/tmatesoft/hg/test/MapTagsToFileRevisions.java @ 255:5a6ab50b4cbf

Improve memory footprint of tag collection (about 14 Mb saved for cpython repo without HashMap.Entry and Entry[])
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 16 Aug 2011 14:33:11 +0200
parents a620f0663a37
children b61ed0f2c4da
comparison
equal deleted inserted replaced
254:a620f0663a37 255:5a6ab50b4cbf
1 package org.tmatesoft.hg.test; 1 package org.tmatesoft.hg.test;
2 2
3 import java.io.*; 3 import java.io.File;
4 import java.util.*; 4 import java.util.ArrayList;
5 import java.util.Map.Entry; 5 import java.util.HashMap;
6 import java.util.LinkedList;
7 import java.util.List;
8 import java.util.Map;
6 9
7 import org.tmatesoft.hg.core.*; 10 import org.tmatesoft.hg.core.HgChangeset;
11 import org.tmatesoft.hg.core.HgChangesetHandler;
12 import org.tmatesoft.hg.core.HgException;
13 import org.tmatesoft.hg.core.HgLogCommand;
14 import org.tmatesoft.hg.core.Nodeid;
8 import org.tmatesoft.hg.internal.Pool; 15 import org.tmatesoft.hg.internal.Pool;
9 import org.tmatesoft.hg.repo.*; 16 import org.tmatesoft.hg.repo.HgChangelog;
17 import org.tmatesoft.hg.repo.HgDataFile;
18 import org.tmatesoft.hg.repo.HgLookup;
19 import org.tmatesoft.hg.repo.HgManifest;
20 import org.tmatesoft.hg.repo.HgRepository;
21 import org.tmatesoft.hg.repo.HgTags;
10 import org.tmatesoft.hg.repo.HgTags.TagInfo; 22 import org.tmatesoft.hg.repo.HgTags.TagInfo;
11 import org.tmatesoft.hg.util.*; 23 import org.tmatesoft.hg.util.CancelledException;
24 import org.tmatesoft.hg.util.Path;
12 25
13 /** 26 /**
14 * @author Marc Strapetz 27 * @author Marc Strapetz
15 */ 28 */
16 public class MapTagsToFileRevisions { 29 public class MapTagsToFileRevisions {
17 30
18 // Static ================================================================= 31 // Static =================================================================
19 32
20 public static void main(String[] args) throws HgException, CancelledException { 33 public static void main(String[] args) throws Exception {
34 MapTagsToFileRevisions m = new MapTagsToFileRevisions();
35 System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory());
36 m.main();
37 m = null;
38 System.gc();
39 System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory());
40 }
41
42 private void main() throws HgException, CancelledException {
21 final long start = System.currentTimeMillis(); 43 final long start = System.currentTimeMillis();
22 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython")); 44 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython"));
23 final HgTags tags = repository.getTags(); 45 final HgTags tags = repository.getTags();
24 // 46 //
25 // build cache 47 // build cache
26 final Map<String, Map<TagInfo, Nodeid>> file2tag2rev = new HashMap<String, Map<TagInfo, Nodeid>>(); 48 //
27 System.out.printf("Collecting manifests for %d tags\n", tags.getTags().size()); 49 final TagInfo[] allTags = new TagInfo[tags.getTags().size()];
50 tags.getTags().values().toArray(allTags);
51 // file2rev2tag value is array of revisions, always of allTags.length. Revision index in the array
52 // is index of corresponding TagInfo in allTags;
53 final Map<String, Nodeid[]> file2rev2tag = new HashMap<String, Nodeid[]>();
54 System.out.printf("Collecting manifests for %d tags\n", allTags.length);
28 // effective translation of changeset revisions to their local indexes 55 // effective translation of changeset revisions to their local indexes
29 final HgChangelog.RevisionMap clogrmap = repository.getChangelog().new RevisionMap().init(); 56 final HgChangelog.RevisionMap clogrmap = repository.getChangelog().new RevisionMap().init();
30 int[] tagLocalRevs = new int[tags.getTags().size()]; 57 int[] tagLocalRevs = new int[allTags.length];
31 int i = 0; 58 for (int i = 0; i < allTags.length; i++) {
32 for (TagInfo tag : tags.getTags().values()) { 59 final Nodeid tagRevision = allTags[i].revision();
33 final Nodeid tagRevision = tag.revision(); 60 tagLocalRevs[i] = clogrmap.localRevision(tagRevision);
34 int tagLocalRev = clogrmap.localRevision(tagRevision);
35 tagLocalRevs[i++] = tagLocalRev;
36 } 61 }
37 System.out.printf("Found tag revisions to analyze: %d\n", System.currentTimeMillis() - start); 62 System.out.printf("Prepared tag revisions to analyze: %d ms\n", System.currentTimeMillis() - start);
38 // 63 //
39 repository.getManifest().walk(new HgManifest.Inspector() { 64 repository.getManifest().walk(new HgManifest.Inspector() {
40 private List<String> tagsAtRev; 65 private final ArrayList<Integer> tagIndexAtRev = new ArrayList<Integer>();
41 final Pool<String> filenamePool = new Pool<String>(); 66 private final Pool<String> filenamePool = new Pool<String>();
42 final Pool<Nodeid> nodeidPool = new Pool<Nodeid>(); 67 private final Pool<Nodeid> nodeidPool = new Pool<Nodeid>();
43 68
44 public boolean begin(int mainfestRevision, Nodeid nid, int changelogRevision) { 69 public boolean begin(int mainfestRevision, Nodeid nid, int changelogRevision) {
45 Nodeid cset = clogrmap.revision(changelogRevision); 70 Nodeid cset = clogrmap.revision(changelogRevision);
46 tagsAtRev = tags.tags(cset); 71 tagIndexAtRev.clear();
47 if (tagsAtRev.isEmpty()) { 72 for (int i = 0; i < allTags.length; i++) {
73 if (cset.equals(allTags[i].revision())) {
74 tagIndexAtRev.add(i);
75 }
76 }
77 if (tagIndexAtRev.isEmpty()) {
48 System.out.println("Can't happen, provided we iterate over revisions with tags only"); 78 System.out.println("Can't happen, provided we iterate over revisions with tags only");
49 } 79 }
50 return true; 80 return true;
51 } 81 }
52 82
53 public boolean next(Nodeid nid, String fname, String flags) { 83 public boolean next(Nodeid nid, String fname, String flags) {
54 fname = filenamePool.unify(fname); 84 fname = filenamePool.unify(fname);
55 nid = nodeidPool.unify(nid); 85 nid = nodeidPool.unify(nid);
56 Map<TagInfo, Nodeid> m = file2tag2rev.get(fname); 86 Nodeid[] m = file2rev2tag.get(fname);
57 if (m == null) { 87 if (m == null) {
58 file2tag2rev.put(fname, m = new HashMap<TagInfo, Nodeid>()); 88 file2rev2tag.put(fname, m = new Nodeid[allTags.length]);
59 } 89 }
60 for (String tag : tagsAtRev) { 90 for (int tagIndex : tagIndexAtRev) {
61 m.put(tags.getTags().get(tag), nid); 91 if (m[tagIndex] != null) {
92 System.out.printf("There's another revision (%s) associated with tag %s already while we try to associate %s\n", m[tagIndex].shortNotation(), allTags[tagIndex].name(), nid.shortNotation());
93 }
94 m[tagIndex] = nid;
62 } 95 }
63 return true; 96 return true;
64 } 97 }
65 98
66 public boolean end(int manifestRevision) { 99 public boolean end(int manifestRevision) {
67 return true; 100 return true;
68 } 101 }
69 102
70 }, tagLocalRevs); 103 }, tagLocalRevs);
71 System.out.printf("Cache built: %d\n", System.currentTimeMillis() - start); 104 System.out.printf("Cache built: %d ms\n", System.currentTimeMillis() - start);
72 // 105 //
73 // look up specific file. This part is fast. 106 // look up specific file. This part is fast.
74 final Path targetPath = Path.create("README"); 107 final Path targetPath = Path.create("README");
75 HgDataFile fileNode = repository.getFileNode(targetPath); 108 HgDataFile fileNode = repository.getFileNode(targetPath);
109 final Nodeid[] allTagsOfTheFile = file2rev2tag.get(targetPath.toString());
76 // TODO if fileNode.isCopy, repeat for each getCopySourceName() 110 // TODO if fileNode.isCopy, repeat for each getCopySourceName()
77 for (int localFileRev = 0; localFileRev < fileNode.getRevisionCount(); localFileRev++) { 111 for (int localFileRev = 0; localFileRev < fileNode.getRevisionCount(); localFileRev++) {
78 Nodeid fileRev = fileNode.getRevision(localFileRev); 112 Nodeid fileRev = fileNode.getRevision(localFileRev);
79 int changesetLocalRev = fileNode.getChangesetLocalRevision(localFileRev); 113 int changesetLocalRev = fileNode.getChangesetLocalRevision(localFileRev);
80 List<String> associatedTags = new LinkedList<String>(); 114 List<String> associatedTags = new LinkedList<String>();
81 final Map<TagInfo, Nodeid> allTagsOfTheFile = file2tag2rev.get(targetPath.toString()); 115 for (int i = 0; i < allTagsOfTheFile.length; i++) {
82 for (Entry<TagInfo, Nodeid> e : allTagsOfTheFile.entrySet()) { 116 if (fileRev.equals(allTagsOfTheFile[i])) {
83 Nodeid fileRevAtTag = e.getValue(); 117 associatedTags.add(allTags[i].name());
84 if (fileRev.equals(fileRevAtTag)) {
85 associatedTags.add(e.getKey().name());
86 } 118 }
87 } 119 }
88 System.out.printf("%3d%7d%s\n", localFileRev, changesetLocalRev, associatedTags); 120 System.out.printf("%3d%7d%s\n", localFileRev, changesetLocalRev, associatedTags);
89 } 121 }
90 System.out.printf("Total time: %d", System.currentTimeMillis() - start); 122 System.out.printf("Total time: %d ms\n", System.currentTimeMillis() - start);
123 System.out.printf("Free mem: %,d\n", Runtime.getRuntime().freeMemory());
91 } 124 }
92 125
93 public static void main2(String[] args) throws HgException, CancelledException { 126 public static void main2(String[] args) throws HgException, CancelledException {
94 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython")); 127 final HgRepository repository = new HgLookup().detect(new File("/temp/hg/cpython"));
95 final Path targetPath = Path.create("README"); 128 final Path targetPath = Path.create("README");