private static int DeltaSizeLimit(DeltaWindowEntry res, int maxDepth, DeltaWindowEntry src) { // Ideally the delta is at least 50% of the original size, // but we also want to account for delta header overhead in // the pack file (to point to the delta base) so subtract off // some of those header bytes from the limit. // int limit = res.Size() / 2 - 20; // Distribute the delta limit over the entire chain length. // This is weighted such that deeper items in the chain must // be even smaller than if they were earlier in the chain, as // they cost significantly more to unpack due to the increased // number of recursive unpack calls. // int remainingDepth = maxDepth - src.Depth(); return((limit * remainingDepth) / maxDepth); }
/// <exception cref="System.IO.IOException"></exception> private int Delta(DeltaWindowEntry src, int srcSlot) { // Objects must use only the same type as their delta base. // If we are looking at something where that isn't true we // have exhausted everything of the correct type and should // move on to the next thing to examine. // if (src.Type() != res.Type()) { KeepInWindow(); return NEXT_RES; } // Only consider a source with a short enough delta chain. if (src.Depth() > resMaxDepth) { return NEXT_SRC; } // Estimate a reasonable upper limit on delta size. int msz = DeltaSizeLimit(res, resMaxDepth, src); if (msz <= 8) { return NEXT_SRC; } // If we have to insert a lot to make this work, find another. if (res.Size() - src.Size() > msz) { return NEXT_SRC; } // If the sizes are radically different, this is a bad pairing. if (res.Size() < src.Size() / 16) { return NEXT_SRC; } DeltaIndex srcIndex; try { srcIndex = Index(src); } catch (LargeObjectException) { // If the source is too big to work on, skip it. DropFromWindow(srcSlot); return NEXT_SRC; } catch (IOException notAvailable) { if ([email protected]()) { // This is an edge that is suddenly not available. DropFromWindow(srcSlot); return NEXT_SRC; } else { throw; } } byte[] resBuf; try { resBuf = Buffer(res); } catch (LargeObjectException) { // If its too big, move on to another item. return NEXT_RES; } // If we already have a delta for the current object, abort // encoding early if this new pairing produces a larger delta. if (bestDelta != null && bestDelta.Length() < msz) { msz = (int)bestDelta.Length(); } TemporaryBuffer.Heap delta = new TemporaryBuffer.Heap(msz); try { if (!srcIndex.Encode(delta, resBuf, msz)) { return NEXT_SRC; } } catch (IOException) { // This only happens when the heap overflows our limit. return NEXT_SRC; } if (IsBetterDelta(src, delta)) { bestDelta = delta; bestSlot = srcSlot; } return NEXT_SRC; }
private static int DeltaSizeLimit(DeltaWindowEntry res, int maxDepth, DeltaWindowEntry src) { // Ideally the delta is at least 50% of the original size, // but we also want to account for delta header overhead in // the pack file (to point to the delta base) so subtract off // some of those header bytes from the limit. // int limit = res.Size() / 2 - 20; // Distribute the delta limit over the entire chain length. // This is weighted such that deeper items in the chain must // be even smaller than if they were earlier in the chain, as // they cost significantly more to unpack due to the increased // number of recursive unpack calls. // int remainingDepth = maxDepth - src.Depth(); return (limit * remainingDepth) / maxDepth; }
/// <exception cref="System.IO.IOException"></exception> private int Delta(DeltaWindowEntry src, int srcSlot) { // Objects must use only the same type as their delta base. // If we are looking at something where that isn't true we // have exhausted everything of the correct type and should // move on to the next thing to examine. // if (src.Type() != res.Type()) { KeepInWindow(); return(NEXT_RES); } // Only consider a source with a short enough delta chain. if (src.Depth() > resMaxDepth) { return(NEXT_SRC); } // Estimate a reasonable upper limit on delta size. int msz = DeltaSizeLimit(res, resMaxDepth, src); if (msz <= 8) { return(NEXT_SRC); } // If we have to insert a lot to make this work, find another. if (res.Size() - src.Size() > msz) { return(NEXT_SRC); } // If the sizes are radically different, this is a bad pairing. if (res.Size() < src.Size() / 16) { return(NEXT_SRC); } DeltaIndex srcIndex; try { srcIndex = Index(src); } catch (LargeObjectException) { // If the source is too big to work on, skip it. DropFromWindow(srcSlot); return(NEXT_SRC); } catch (IOException notAvailable) { if ([email protected]()) { // This is an edge that is suddenly not available. DropFromWindow(srcSlot); return(NEXT_SRC); } else { throw; } } byte[] resBuf; try { resBuf = Buffer(res); } catch (LargeObjectException) { // If its too big, move on to another item. return(NEXT_RES); } // If we already have a delta for the current object, abort // encoding early if this new pairing produces a larger delta. if (bestDelta != null && bestDelta.Length() < msz) { msz = (int)bestDelta.Length(); } TemporaryBuffer.Heap delta = new TemporaryBuffer.Heap(msz); try { if (!srcIndex.Encode(delta, resBuf, msz)) { return(NEXT_SRC); } } catch (IOException) { // This only happens when the heap overflows our limit. return(NEXT_SRC); } if (IsBetterDelta(src, delta)) { bestDelta = delta; bestSlot = srcSlot; } return(NEXT_SRC); }