comparison src/org/tmatesoft/hg/repo/HgStatusCollector.java @ 281:81e9a3c9bafe

Utilize IntMap when caching manifest revisions
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 02 Sep 2011 13:59:21 +0200
parents 3fbfce107f94
children e51dd9a14b6f
comparison
equal deleted inserted replaced
280:35125450c804 281:81e9a3c9bafe
23 import java.util.Collections; 23 import java.util.Collections;
24 import java.util.LinkedHashMap; 24 import java.util.LinkedHashMap;
25 import java.util.LinkedList; 25 import java.util.LinkedList;
26 import java.util.List; 26 import java.util.List;
27 import java.util.Map; 27 import java.util.Map;
28 import java.util.SortedMap;
29 import java.util.TreeMap;
30 import java.util.TreeSet; 28 import java.util.TreeSet;
31 29
32 import org.tmatesoft.hg.core.HgDataStreamException; 30 import org.tmatesoft.hg.core.HgDataStreamException;
33 import org.tmatesoft.hg.core.Nodeid; 31 import org.tmatesoft.hg.core.Nodeid;
32 import org.tmatesoft.hg.internal.IntMap;
34 import org.tmatesoft.hg.internal.ManifestRevision; 33 import org.tmatesoft.hg.internal.ManifestRevision;
35 import org.tmatesoft.hg.internal.Pool; 34 import org.tmatesoft.hg.internal.Pool;
36 import org.tmatesoft.hg.util.Path; 35 import org.tmatesoft.hg.util.Path;
37 import org.tmatesoft.hg.util.PathPool; 36 import org.tmatesoft.hg.util.PathPool;
38 import org.tmatesoft.hg.util.PathRewrite; 37 import org.tmatesoft.hg.util.PathRewrite;
45 * @author TMate Software Ltd. 44 * @author TMate Software Ltd.
46 */ 45 */
47 public class HgStatusCollector { 46 public class HgStatusCollector {
48 47
49 private final HgRepository repo; 48 private final HgRepository repo;
50 private final SortedMap<Integer, ManifestRevision> cache; // sparse array, in fact 49 private final IntMap<ManifestRevision> cache; // sparse array, in fact
51 // with cpython repository, ~70 000 changes, complete Log (direct out, no reverse) output 50 // with cpython repository, ~70 000 changes, complete Log (direct out, no reverse) output
52 // no cache limit, no nodeids and fname caching - OOME on changeset 1035 51 // no cache limit, no nodeids and fname caching - OOME on changeset 1035
53 // no cache limit, but with cached nodeids and filenames - 1730+ 52 // no cache limit, but with cached nodeids and filenames - 1730+
54 // cache limit 100 - 19+ minutes to process 10000, and still working (too long, stopped) 53 // cache limit 100 - 19+ minutes to process 10000, and still working (too long, stopped)
55 private final int cacheMaxSize = 50; // do not keep too much manifest revisions 54 private final int cacheMaxSize = 50; // do not keep too much manifest revisions
60 private Path.Matcher scope = new Path.Matcher.Any(); 59 private Path.Matcher scope = new Path.Matcher.Any();
61 60
62 61
63 public HgStatusCollector(HgRepository hgRepo) { 62 public HgStatusCollector(HgRepository hgRepo) {
64 this.repo = hgRepo; 63 this.repo = hgRepo;
65 cache = new TreeMap<Integer, ManifestRevision>(); 64 cache = new IntMap<ManifestRevision>(cacheMaxSize);
66 cacheNodes = new Pool<Nodeid>(); 65 cacheNodes = new Pool<Nodeid>();
67 cacheFilenames = new Pool<String>(); 66 cacheFilenames = new Pool<String>();
68 67
69 emptyFakeState = new ManifestRevision(null, null); 68 emptyFakeState = new ManifestRevision(null, null);
70 emptyFakeState.begin(-1, null, -1); 69 emptyFakeState.begin(-1, null, -1);
79 ManifestRevision i = cache.get(rev); 78 ManifestRevision i = cache.get(rev);
80 if (i == null) { 79 if (i == null) {
81 if (rev == -1) { 80 if (rev == -1) {
82 return emptyFakeState; 81 return emptyFakeState;
83 } 82 }
84 while (cache.size() > cacheMaxSize) { 83 ensureCacheSize();
85 // assume usually we go from oldest to newest, hence remove oldest as most likely to be no longer necessary
86 cache.remove(cache.firstKey());
87 }
88 i = new ManifestRevision(cacheNodes, cacheFilenames); 84 i = new ManifestRevision(cacheNodes, cacheFilenames);
89 cache.put(rev, i); 85 cache.put(rev, i);
90 repo.getManifest().walk(rev, rev, i); 86 repo.getManifest().walk(rev, rev, i);
91 } 87 }
92 return i; 88 return i;
94 90
95 private boolean cached(int revision) { 91 private boolean cached(int revision) {
96 return cache.containsKey(revision) || revision == -1; 92 return cache.containsKey(revision) || revision == -1;
97 } 93 }
98 94
95 private void ensureCacheSize() {
96 if (cache.size() > cacheMaxSize) {
97 // assume usually we go from oldest to newest, hence remove oldest as most likely to be no longer necessary
98 cache.removeFromStart(cache.size() - cacheMaxSize + 1 /* room for new element */);
99 }
100 }
101
99 private void initCacheRange(int minRev, int maxRev) { 102 private void initCacheRange(int minRev, int maxRev) {
100 while (cache.size() > cacheMaxSize) { 103 ensureCacheSize();
101 // assume usually we go from oldest to newest, hence remove oldest as most likely to be no longer necessary
102 cache.remove(cache.firstKey());
103 }
104 repo.getManifest().walk(minRev, maxRev, new HgManifest.Inspector() { 104 repo.getManifest().walk(minRev, maxRev, new HgManifest.Inspector() {
105 private ManifestRevision delegate; 105 private ManifestRevision delegate;
106 private boolean cacheHit; // range may include revisions we already know about, do not re-create them 106 private boolean cacheHit; // range may include revisions we already know about, do not re-create them
107 107
108 public boolean begin(int manifestRevision, Nodeid nid, int changelogRevision) { 108 public boolean begin(int manifestRevision, Nodeid nid, int changelogRevision) {