Mercurial > hg4j
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) { |