Mercurial > hg4j
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"); |