57 return self.end(rev) - self.start(rev) |
57 return self.end(rev) - self.start(rev) |
58 |
58 |
59 def __len__(self): |
59 def __len__(self): |
60 return len(self._data) |
60 return len(self._data) |
61 |
61 |
62 def slicechunk(revlog, revs, deltainfo=None, targetsize=None): |
62 def slicechunk(revlog, revs, targetsize=None): |
63 """slice revs to reduce the amount of unrelated data to be read from disk. |
63 """slice revs to reduce the amount of unrelated data to be read from disk. |
64 |
64 |
65 ``revs`` is sliced into groups that should be read in one time. |
65 ``revs`` is sliced into groups that should be read in one time. |
66 Assume that revs are sorted. |
66 Assume that revs are sorted. |
67 |
67 |
114 """ |
114 """ |
115 if targetsize is not None: |
115 if targetsize is not None: |
116 targetsize = max(targetsize, revlog._srmingapsize) |
116 targetsize = max(targetsize, revlog._srmingapsize) |
117 # targetsize should not be specified when evaluating delta candidates: |
117 # targetsize should not be specified when evaluating delta candidates: |
118 # * targetsize is used to ensure we stay within specification when reading, |
118 # * targetsize is used to ensure we stay within specification when reading, |
119 # * deltainfo is used to pick are good delta chain when writing. |
|
120 if not (deltainfo is None or targetsize is None): |
|
121 msg = 'cannot use `targetsize` with a `deltainfo`' |
|
122 raise error.ProgrammingError(msg) |
|
123 for chunk in _slicechunktodensity(revlog, revs, |
119 for chunk in _slicechunktodensity(revlog, revs, |
124 deltainfo, |
|
125 revlog._srdensitythreshold, |
120 revlog._srdensitythreshold, |
126 revlog._srmingapsize): |
121 revlog._srmingapsize): |
127 for subchunk in _slicechunktosize(revlog, chunk, targetsize): |
122 for subchunk in _slicechunktosize(revlog, chunk, targetsize): |
128 yield subchunk |
123 yield subchunk |
129 |
124 |
202 startrevidx = idx |
197 startrevidx = idx |
203 startdata = revlog.start(r) |
198 startdata = revlog.start(r) |
204 endrevidx = idx |
199 endrevidx = idx |
205 yield _trimchunk(revlog, revs, startrevidx) |
200 yield _trimchunk(revlog, revs, startrevidx) |
206 |
201 |
207 def _slicechunktodensity(revlog, revs, deltainfo=None, targetdensity=0.5, |
202 def _slicechunktodensity(revlog, revs, targetdensity=0.5, |
208 mingapsize=0): |
203 mingapsize=0): |
209 """slice revs to reduce the amount of unrelated data to be read from disk. |
204 """slice revs to reduce the amount of unrelated data to be read from disk. |
210 |
205 |
211 ``revs`` is sliced into groups that should be read in one time. |
206 ``revs`` is sliced into groups that should be read in one time. |
212 Assume that revs are sorted. |
207 Assume that revs are sorted. |
213 |
|
214 ``deltainfo`` is a _deltainfo instance of a revision that we would append |
|
215 to the top of the revlog. |
|
216 |
208 |
217 The initial chunk is sliced until the overall density (payload/chunks-span |
209 The initial chunk is sliced until the overall density (payload/chunks-span |
218 ratio) is above `targetdensity`. No gap smaller than `mingapsize` is |
210 ratio) is above `targetdensity`. No gap smaller than `mingapsize` is |
219 skipped. |
211 skipped. |
220 |
212 |
262 |
254 |
263 if len(revs) <= 1: |
255 if len(revs) <= 1: |
264 yield revs |
256 yield revs |
265 return |
257 return |
266 |
258 |
267 nextrev = len(revlog) |
259 deltachainspan = segmentspan(revlog, revs) |
268 nextoffset = revlog.end(nextrev - 1) |
260 chainpayload = sum(length(r) for r in revs) |
269 |
|
270 if deltainfo is None: |
|
271 deltachainspan = segmentspan(revlog, revs) |
|
272 chainpayload = sum(length(r) for r in revs) |
|
273 else: |
|
274 deltachainspan = deltainfo.distance |
|
275 chainpayload = deltainfo.compresseddeltalen |
|
276 |
261 |
277 if deltachainspan < mingapsize: |
262 if deltachainspan < mingapsize: |
278 yield revs |
263 yield revs |
279 return |
264 return |
280 |
265 |
286 density = 1.0 |
271 density = 1.0 |
287 |
272 |
288 if density >= targetdensity: |
273 if density >= targetdensity: |
289 yield revs |
274 yield revs |
290 return |
275 return |
291 |
|
292 if deltainfo is not None and deltainfo.deltalen: |
|
293 revs = list(revs) |
|
294 revs.append(nextrev) |
|
295 |
276 |
296 # Store the gaps in a heap to have them sorted by decreasing size |
277 # Store the gaps in a heap to have them sorted by decreasing size |
297 gapsheap = [] |
278 gapsheap = [] |
298 heapq.heapify(gapsheap) |
279 heapq.heapify(gapsheap) |
299 prevend = None |
280 prevend = None |
300 for i, rev in enumerate(revs): |
281 for i, rev in enumerate(revs): |
301 if rev < nextrev: |
282 revstart = start(rev) |
302 revstart = start(rev) |
283 revlen = length(rev) |
303 revlen = length(rev) |
|
304 else: |
|
305 revstart = nextoffset |
|
306 revlen = deltainfo.deltalen |
|
307 |
284 |
308 # Skip empty revisions to form larger holes |
285 # Skip empty revisions to form larger holes |
309 if revlen == 0: |
286 if revlen == 0: |
310 continue |
287 continue |
311 |
288 |