Mercurial > jhg
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 |
