mercurial/revlogutils/deltas.py
changeset 40604 3ac23dad6364
parent 40603 2f7e531ef3e7
child 40605 a32ccd32982b
equal deleted inserted replaced
40603:2f7e531ef3e7 40604:3ac23dad6364
    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