Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgStatusCollector.java @ 195:c9b305df0b89
Optimization: use ParentWalker to get changeset's parents, if possible. Do not keep duplicating nodeids and strings in manifest revisions
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Fri, 15 Apr 2011 05:17:44 +0200 |
parents | d5268ca7715b |
children | 3a7696fb457c |
comparison
equal
deleted
inserted
replaced
194:344e8d7e4d6e | 195:c9b305df0b89 |
---|---|
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; | |
28 import java.util.TreeMap; | 29 import java.util.TreeMap; |
29 import java.util.TreeSet; | 30 import java.util.TreeSet; |
30 | 31 |
31 import org.tmatesoft.hg.core.HgDataStreamException; | 32 import org.tmatesoft.hg.core.HgDataStreamException; |
32 import org.tmatesoft.hg.core.Nodeid; | 33 import org.tmatesoft.hg.core.Nodeid; |
34 import org.tmatesoft.hg.internal.Pool; | |
33 import org.tmatesoft.hg.util.Path; | 35 import org.tmatesoft.hg.util.Path; |
34 import org.tmatesoft.hg.util.PathPool; | 36 import org.tmatesoft.hg.util.PathPool; |
35 import org.tmatesoft.hg.util.PathRewrite; | 37 import org.tmatesoft.hg.util.PathRewrite; |
36 | 38 |
37 | 39 |
42 * @author TMate Software Ltd. | 44 * @author TMate Software Ltd. |
43 */ | 45 */ |
44 public class HgStatusCollector { | 46 public class HgStatusCollector { |
45 | 47 |
46 private final HgRepository repo; | 48 private final HgRepository repo; |
47 private final Map<Integer, ManifestRevisionInspector> cache; // sparse array, in fact | 49 private final SortedMap<Integer, ManifestRevisionInspector> cache; // sparse array, in fact |
50 // with cpython repository, ~70 000 changes, complete Log (direct out, no reverse) output | |
51 // no cache limit, no nodeids and fname caching - OOME on changeset 1035 | |
52 // no cache limit, but with cached nodeids and filenames - 1730+ | |
53 // cache limit 100 - 19+ minutes to process 10000, and still working (too long, stopped) | |
54 private final int cacheMaxSize = 100; // do not keep too much manifest revisions | |
48 private PathPool pathPool; | 55 private PathPool pathPool; |
56 private final Pool<Nodeid> cacheNodes; | |
57 private final Pool<String> cacheFilenames; // XXX in fact, need to think if use of PathPool directly instead is better solution | |
58 | |
49 | 59 |
50 public HgStatusCollector(HgRepository hgRepo) { | 60 public HgStatusCollector(HgRepository hgRepo) { |
51 this.repo = hgRepo; | 61 this.repo = hgRepo; |
52 cache = new TreeMap<Integer, ManifestRevisionInspector>(); | 62 cache = new TreeMap<Integer, ManifestRevisionInspector>(); |
53 ManifestRevisionInspector emptyFakeState = new ManifestRevisionInspector(); | 63 cacheNodes = new Pool<Nodeid>(); |
64 cacheFilenames = new Pool<String>(); | |
65 ManifestRevisionInspector emptyFakeState = new ManifestRevisionInspector(null, null); | |
54 emptyFakeState.begin(-1, null); | 66 emptyFakeState.begin(-1, null); |
55 emptyFakeState.end(-1); // FIXME HgRepo.TIP == -1 as well, need to distinguish fake "prior to first" revision from "the very last" | 67 emptyFakeState.end(-1); // FIXME HgRepo.TIP == -1 as well, need to distinguish fake "prior to first" revision from "the very last" |
56 cache.put(-1, emptyFakeState); | 68 cache.put(-1, emptyFakeState); |
57 } | 69 } |
58 | 70 |
61 } | 73 } |
62 | 74 |
63 private ManifestRevisionInspector get(int rev) { | 75 private ManifestRevisionInspector get(int rev) { |
64 ManifestRevisionInspector i = cache.get(rev); | 76 ManifestRevisionInspector i = cache.get(rev); |
65 if (i == null) { | 77 if (i == null) { |
66 i = new ManifestRevisionInspector(); | 78 if (cache.size() > cacheMaxSize) { |
79 // assume usually we go from oldest to newest, hence remove oldest as most likely to be no longer necessary | |
80 cache.remove(cache.firstKey()); | |
81 } | |
82 i = new ManifestRevisionInspector(cacheNodes, cacheFilenames); | |
67 cache.put(rev, i); | 83 cache.put(rev, i); |
68 repo.getManifest().walk(rev, rev, i); | 84 repo.getManifest().walk(rev, rev, i); |
69 } | 85 } |
70 return i; | 86 return i; |
71 } | 87 } |
128 | 144 |
129 repo.getManifest().walk(minRev, maxRev, new HgManifest.Inspector() { | 145 repo.getManifest().walk(minRev, maxRev, new HgManifest.Inspector() { |
130 private ManifestRevisionInspector delegate; | 146 private ManifestRevisionInspector delegate; |
131 | 147 |
132 public boolean begin(int revision, Nodeid nid) { | 148 public boolean begin(int revision, Nodeid nid) { |
133 cache.put(revision, delegate = new ManifestRevisionInspector()); | 149 cache.put(revision, delegate = new ManifestRevisionInspector(cacheNodes, cacheFilenames)); |
134 delegate.begin(revision, nid); | 150 delegate.begin(revision, nid); |
135 return true; | 151 return true; |
136 } | 152 } |
137 | 153 |
138 public boolean next(Nodeid nid, String fname, String flags) { | 154 public boolean next(Nodeid nid, String fname, String flags) { |
340 } | 356 } |
341 l.add(p); | 357 l.add(p); |
342 return l; | 358 return l; |
343 } | 359 } |
344 } | 360 } |
345 | 361 |
346 /*package-local*/ static final class ManifestRevisionInspector implements HgManifest.Inspector { | 362 /*package-local*/ static final class ManifestRevisionInspector implements HgManifest.Inspector { |
347 private final TreeMap<String, Nodeid> idsMap; | 363 private final TreeMap<String, Nodeid> idsMap; |
348 private final TreeMap<String, String> flagsMap; | 364 private final TreeMap<String, String> flagsMap; |
349 | 365 private final Pool<Nodeid> idsPool; |
350 public ManifestRevisionInspector() { | 366 private final Pool<String> namesPool; |
367 | |
368 // optional pools for effective management of nodeids and filenames (they are likely | |
369 // to be duplicated among different manifest revisions | |
370 public ManifestRevisionInspector(Pool<Nodeid> nodeidPool, Pool<String> filenamePool) { | |
371 idsPool = nodeidPool; | |
372 namesPool = filenamePool; | |
351 idsMap = new TreeMap<String, Nodeid>(); | 373 idsMap = new TreeMap<String, Nodeid>(); |
352 flagsMap = new TreeMap<String, String>(); | 374 flagsMap = new TreeMap<String, String>(); |
353 } | 375 } |
354 | 376 |
355 public Collection<String> files() { | 377 public Collection<String> files() { |
365 } | 387 } |
366 | 388 |
367 // | 389 // |
368 | 390 |
369 public boolean next(Nodeid nid, String fname, String flags) { | 391 public boolean next(Nodeid nid, String fname, String flags) { |
392 if (namesPool != null) { | |
393 fname = namesPool.unify(fname); | |
394 } | |
395 if (idsPool != null) { | |
396 nid = idsPool.unify(nid); | |
397 } | |
370 idsMap.put(fname, nid); | 398 idsMap.put(fname, nid); |
371 flagsMap.put(fname, flags); | 399 flagsMap.put(fname, flags); |
372 return true; | 400 return true; |
373 } | 401 } |
374 | 402 |