Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgDataFile.java @ 242:ad6a046943be
Improved reading of sparse revisions from a revlog
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 23 Jun 2011 15:19:07 +0200 |
parents | 29231022fec8 |
children | 2fb439375ddc |
comparison
equal
deleted
inserted
replaced
241:d3ab16739736 | 242:ad6a046943be |
---|---|
222 end = last; | 222 end = last; |
223 } else if (end < start || end > last) { | 223 } else if (end < start || end > last) { |
224 throw new IllegalArgumentException(); | 224 throw new IllegalArgumentException(); |
225 } | 225 } |
226 final int[] commitRevisions = new int[end - start + 1]; | 226 final int[] commitRevisions = new int[end - start + 1]; |
227 final boolean[] needsSorting = { false }; | |
227 RevlogStream.Inspector insp = new RevlogStream.Inspector() { | 228 RevlogStream.Inspector insp = new RevlogStream.Inspector() { |
228 int count = 0; | 229 int count = 0; |
229 | |
230 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) { | 230 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) { |
231 if (count > 0) { | |
232 if (commitRevisions[count -1] > linkRevision) { | |
233 needsSorting[0] = true; | |
234 } | |
235 } | |
231 commitRevisions[count++] = linkRevision; | 236 commitRevisions[count++] = linkRevision; |
232 } | 237 } |
233 }; | 238 }; |
234 content.iterate(start, end, false, insp); | 239 content.iterate(start, end, false, insp); |
235 final HgChangelog changelog = getRepo().getChangelog(); | 240 final HgChangelog changelog = getRepo().getChangelog(); |
236 /* | 241 if (needsSorting[0]) { |
237 * changelog.range(inspector, commitRevisions); | 242 // automatic tools (svnmerge?) produce unnatural file history |
238 * Not effective when changes are sparse and far from each other. | 243 // (e.g. cpython/Lib/doctest.py, revision 164 points to cset 63509, 165 - to 38453) |
239 * However, it's only single file read, unlike code below (few reads of sequential blocks) | 244 Arrays.sort(commitRevisions); |
240 * Need to weight tradeoffs of file read and iteration of sparse files. | 245 } |
241 */ | 246 changelog.range(inspector, commitRevisions); |
242 | |
243 // | |
244 final int HistoricallyCloseCommits = 50; // XXX perhaps, shall increase/decrease based on changelog.revisionCount() | |
245 // (huge changelog => memory mapped files, each file re-read is more expensive than iterating over records in one read? | |
246 // | |
247 // try short sequences on neighboring revisions. | |
248 Arrays.sort(commitRevisions); // automatic tools (svnmerge?) produce unnatural file history | |
249 // (e.g. cpython/Lib/doctest.py, revision 164 points to 63509, 165 - to 38453) | |
250 for (int i = 0; i < commitRevisions.length; ) { | |
251 int x = i; | |
252 i++; | |
253 boolean sequential = true; | |
254 while (i < commitRevisions.length) { | |
255 if (commitRevisions[i] == commitRevisions[i-1] + 1) { | |
256 i++; | |
257 } else if (commitRevisions[i] - commitRevisions[i-1] < HistoricallyCloseCommits) { | |
258 // close enough, but not sequential | |
259 sequential = false; | |
260 i++; | |
261 } else { | |
262 break; | |
263 } | |
264 } | |
265 if (sequential) { | |
266 // commitRevisions[x..i-1] are sequential | |
267 changelog.range(commitRevisions[x], commitRevisions[i-1], inspector); | |
268 } else { | |
269 int[] revs = new int[i-x]; | |
270 System.arraycopy(commitRevisions, x, revs, 0, i-x); | |
271 changelog.range(inspector, revs); | |
272 } | |
273 } | |
274 } | 247 } |
275 | 248 |
276 // for a given local revision of the file, find out local revision in the changelog | 249 // for a given local revision of the file, find out local revision in the changelog |
277 public int getChangesetLocalRevision(int revision) { | 250 public int getChangesetLocalRevision(int revision) { |
278 return content.linkRevision(revision); | 251 return content.linkRevision(revision); |