From 83d73b2b9d24a39dc1d3efe1a1316042519f1182 Mon Sep 17 00:00:00 2001 From: Maks Verver Date: Thu, 20 Jun 2019 13:44:30 +0200 Subject: [PATCH] Slightly improve DecodeCopy() performance. Instead of increasing `address` every iteration of the loop, we can just keep it fixed and double the number of bytes copied every iteration. This works because the string to be generated is periodic. For example, if we want to copy 9 bytes starting 2 bytes back: |-------| size 9 abc......... ^ ^ | | | target_bytes_decoded: 3 address: 1 Then the old version of the code would generate these intermediate states: abc......... ^ ^ abcbc....... (1) ^ ^ abcbcbc..... (2) ^ ^ abcbcbcbc... (3) ^ ^ abcbcbcbcbc. (4) ^ ^ abcbcbcbcbcb (5, outside the loop) While the new version would double the range to be copied every time: abc......... ^ ^ abcbc....... (1) ^ ^ abcbcbcbc... (2) ^ ^ abcbcbcbcbcb (3, outside the loop) In general, if s = size and d = (target_bytes_decoded - address), then the number of calls to CopyBytes is reduced from (s/d) + 1 to log(s/d)/log(2) + 1. The total time complexity is still O(s) because CopyBytes is presumably linear in the number of bytes copied, but we end up doing fewer calls in total, which is likely to be faster in practice, especially if `s` is large and `d` is small. --- src/vcdecoder.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/vcdecoder.cc b/src/vcdecoder.cc index 6cba7f7..dde3c4e 100644 --- a/src/vcdecoder.cc +++ b/src/vcdecoder.cc @@ -1223,7 +1223,6 @@ VCDiffResult VCDiffDeltaFileWindow::DecodeCopy(size_t size, const size_t partial_copy_size = target_bytes_decoded - address; CopyBytes(&target_segment_ptr[address], partial_copy_size); target_bytes_decoded += partial_copy_size; - address += partial_copy_size; size -= partial_copy_size; } CopyBytes(&target_segment_ptr[address], size);