diff options
-rw-r--r-- | xdelta3/Makefile | 3 | ||||
-rw-r--r-- | xdelta3/setup.py | 1 | ||||
-rw-r--r-- | xdelta3/xdelta3-main.h | 8 | ||||
-rwxr-xr-x | xdelta3/xdelta3-regtest.py | 107 | ||||
-rw-r--r-- | xdelta3/xdelta3.h | 9 |
5 files changed, 82 insertions, 46 deletions
diff --git a/xdelta3/Makefile b/xdelta3/Makefile index 2d2b785..3bb7f44 100644 --- a/xdelta3/Makefile +++ b/xdelta3/Makefile | |||
@@ -48,6 +48,7 @@ EXTRA = Makefile COPYING linkxd3lib.c badcopy.c xdelta3.swig \ | |||
48 | 48 | ||
49 | SWIG_FLAGS = -DXD3_DEBUG=0 \ | 49 | SWIG_FLAGS = -DXD3_DEBUG=0 \ |
50 | -DXD3_USE_LARGEFILE64=1 \ | 50 | -DXD3_USE_LARGEFILE64=1 \ |
51 | -DGENERIC_ENCODE_TABLES=1 \ | ||
51 | -DSECONDARY_DJW=1 \ | 52 | -DSECONDARY_DJW=1 \ |
52 | -DVCDIFF_TOOLS=1 \ | 53 | -DVCDIFF_TOOLS=1 \ |
53 | -DSWIG_MODULE=1 \ | 54 | -DSWIG_MODULE=1 \ |
@@ -105,7 +106,7 @@ xdelta3-debug3: $(SOURCES) | |||
105 | $(CC) -g -Wall -Wshadow xdelta3.c -o xdelta3-debug3 -DXD3_MAIN=1 -DGENERIC_ENCODE_TABLES=1 \ | 106 | $(CC) -g -Wall -Wshadow xdelta3.c -o xdelta3-debug3 -DXD3_MAIN=1 -DGENERIC_ENCODE_TABLES=1 \ |
106 | -DXD3_USE_LARGEFILE64=1 -DXD3_STDIO=1 -DREGRESSION_TEST=1 -DXD3_DEBUG=3 -DSECONDARY_DJW=1 -DSECONDARY_FGK=1 -lm | 107 | -DXD3_USE_LARGEFILE64=1 -DXD3_STDIO=1 -DREGRESSION_TEST=1 -DXD3_DEBUG=3 -DSECONDARY_DJW=1 -DSECONDARY_FGK=1 -lm |
107 | 108 | ||
108 | $(PYTGT): $(SOURCES) | 109 | $(PYTGT): $(SOURCES) setup.py |
109 | $(PYTHON) setup.py install --verbose --compile --force | 110 | $(PYTHON) setup.py install --verbose --compile --force |
110 | 111 | ||
111 | xdelta3_wrap.c xdelta3.py: xdelta3.swig | 112 | xdelta3_wrap.c xdelta3.py: xdelta3.swig |
diff --git a/xdelta3/setup.py b/xdelta3/setup.py index d7f11c4..f89aba7 100644 --- a/xdelta3/setup.py +++ b/xdelta3/setup.py | |||
@@ -37,6 +37,7 @@ xdelta3_ext = Extension('xdelta3main', | |||
37 | ('PYTHON_MODULE',1), | 37 | ('PYTHON_MODULE',1), |
38 | ('SECONDARY_DJW',1), | 38 | ('SECONDARY_DJW',1), |
39 | ('VCDIFF_TOOLS',1), | 39 | ('VCDIFF_TOOLS',1), |
40 | ('GENERIC_ENCODE_TABLES',1), | ||
40 | ('XD3_POSIX',1), | 41 | ('XD3_POSIX',1), |
41 | ('XD3_USE_LARGEFILE64',1), | 42 | ('XD3_USE_LARGEFILE64',1), |
42 | 43 | ||
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h index 44f51ee..2f1eb7f 100644 --- a/xdelta3/xdelta3-main.h +++ b/xdelta3/xdelta3-main.h | |||
@@ -400,7 +400,6 @@ reset_defaults(void) | |||
400 | option_srcwinsz_set = 0; | 400 | option_srcwinsz_set = 0; |
401 | option_smatch_config = NULL; | 401 | option_smatch_config = NULL; |
402 | option_level = XD3_DEFAULT_LEVEL; | 402 | option_level = XD3_DEFAULT_LEVEL; |
403 | option_winsize = XD3_DEFAULT_WINSIZE; | ||
404 | option_srcwinsz = XD3_DEFAULT_SRCWINSZ; | 403 | option_srcwinsz = XD3_DEFAULT_SRCWINSZ; |
405 | option_winsize = XD3_DEFAULT_WINSIZE; | 404 | option_winsize = XD3_DEFAULT_WINSIZE; |
406 | option_srcwinsz = XD3_DEFAULT_SRCWINSZ; | 405 | option_srcwinsz = XD3_DEFAULT_SRCWINSZ; |
@@ -2668,15 +2667,16 @@ main_input (xd3_cmd cmd, | |||
2668 | /* Warn when no source copies are found */ | 2667 | /* Warn when no source copies are found */ |
2669 | if (! xd3_encoder_used_source (& stream)) | 2668 | if (! xd3_encoder_used_source (& stream)) |
2670 | { | 2669 | { |
2671 | XPR(NT "warning: input position %"Q"u no source copies\n", | 2670 | XPR(NT "warning: input window %"Q"u..%"Q"u has no source copies\n", |
2672 | stream.current_window * option_winsize); | 2671 | stream.current_window * option_winsize, |
2672 | (stream.current_window+1) * option_winsize); | ||
2673 | } | 2673 | } |
2674 | 2674 | ||
2675 | /* Limited instruction buffer size affects source copies */ | 2675 | /* Limited instruction buffer size affects source copies */ |
2676 | if (option_verbose > 1 && stream.i_slots_used > stream.iopt_size) | 2676 | if (option_verbose > 1 && stream.i_slots_used > stream.iopt_size) |
2677 | { | 2677 | { |
2678 | XPR(NT "warning: input position %"Q"u overflowed instruction buffer, " | 2678 | XPR(NT "warning: input position %"Q"u overflowed instruction buffer, " |
2679 | "needed %u (vs. %u)\n", | 2679 | "needed %u (vs. %u), consider raising -I\n", |
2680 | stream.current_window * option_winsize, | 2680 | stream.current_window * option_winsize, |
2681 | stream.i_slots_used, stream.iopt_size); | 2681 | stream.i_slots_used, stream.iopt_size); |
2682 | } | 2682 | } |
diff --git a/xdelta3/xdelta3-regtest.py b/xdelta3/xdelta3-regtest.py index 1dc6c0a..30bccb1 100755 --- a/xdelta3/xdelta3-regtest.py +++ b/xdelta3/xdelta3-regtest.py | |||
@@ -16,7 +16,6 @@ | |||
16 | # along with this program; if not, write to the Free Software | 16 | # along with this program; if not, write to the Free Software |
17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | 18 | ||
19 | # TODO: Start testing window sizes | ||
20 | # TODO: Test 1.5 vs. greedy | 19 | # TODO: Test 1.5 vs. greedy |
21 | # TODO: Compare w/ bsdiff and generate more summary | 20 | # TODO: Compare w/ bsdiff and generate more summary |
22 | 21 | ||
@@ -39,12 +38,15 @@ MIN_RUN = 1000 * 1000 * 1 | |||
39 | MAX_RUN = 1000 * 1000 * 10 | 38 | MAX_RUN = 1000 * 1000 * 10 |
40 | 39 | ||
41 | # How many results per round | 40 | # How many results per round |
42 | MAX_RESULTS = 10 | 41 | MAX_RESULTS = 6 |
43 | KEEP_P = (0.5) | 42 | KEEP_P = (1.0) |
44 | FAST_P = (0.0) | 43 | FAST_P = (0.0) |
45 | SLOW_P = (0.0) | 44 | SLOW_P = (0.0) |
46 | FILE_P = (0.30) | 45 | FILE_P = (0.30) |
47 | 46 | ||
47 | # the first 10 args go to -C | ||
48 | SOFT_CONFIG_CNT = 10 | ||
49 | |||
48 | CONFIG_ORDER = [ 'large_look', | 50 | CONFIG_ORDER = [ 'large_look', |
49 | 'large_step', | 51 | 'large_step', |
50 | 'small_look', | 52 | 'small_look', |
@@ -54,23 +56,36 @@ CONFIG_ORDER = [ 'large_look', | |||
54 | 'trylazy', | 56 | 'trylazy', |
55 | 'max_lazy', | 57 | 'max_lazy', |
56 | 'long_enough', | 58 | 'long_enough', |
57 | 'promote' ] | 59 | 'promote', |
60 | 'winsize', | ||
61 | 'srcwinsize', | ||
62 | ] | ||
63 | |||
64 | CONFIG_ARGMAP = { | ||
65 | 'winsize' : '-W', | ||
66 | 'srcwinsize' : '-B', | ||
67 | } | ||
58 | 68 | ||
59 | def INPUT_SPEC(rand): | 69 | def INPUT_SPEC(rand): |
60 | return { | 70 | return { |
61 | 'large_look' : lambda d: rand.choice([9, 11, 13, 15]), | 71 | 'large_look' : lambda d: rand.choice([9]), |
62 | 'large_step' : lambda d: rand.choice([11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ]), | 72 | 'large_step' : lambda d: rand.choice([15]), |
63 | 73 | ||
64 | 'small_chain' : lambda d: rand.choice([1]), | 74 | 'small_chain' : lambda d: rand.choice([1]), |
65 | 'small_lchain' : lambda d: rand.choice([1]), | 75 | 'small_lchain' : lambda d: rand.choice([1]), |
66 | 76 | ||
67 | 'max_lazy' : lambda d: rand.choice([9, 13, 18]), | 77 | 'max_lazy' : lambda d: rand.choice([18]), |
68 | 'long_enough' : lambda d: rand.choice([9, 13, 18]), | 78 | 'long_enough' : lambda d: rand.choice([18]), |
69 | 79 | ||
70 | 'small_look' : lambda d: rand.choice([4]), | 80 | 'small_look' : lambda d: rand.choice([4]), |
71 | 'promote' : lambda d: 0, | 81 | 'promote' : lambda d: 0, |
72 | 'trylazy' : lambda d: 1, | 82 | 'trylazy' : lambda d: 1, |
73 | 'ssmatch' : lambda d: 0, | 83 | 'ssmatch' : lambda d: 0, |
84 | |||
85 | 'winsize' : lambda d: rand.choice( | ||
86 | [x * (1<<20) for x in [1, 4, 8, 16, 32, 64]]), | ||
87 | |||
88 | 'srcwinsize' : lambda d: 1<<26, | ||
74 | } | 89 | } |
75 | 90 | ||
76 | 91 | ||
@@ -313,7 +328,7 @@ class Xdelta3RunClass: | |||
313 | #end | 328 | #end |
314 | 329 | ||
315 | def __str__(self): | 330 | def __str__(self): |
316 | return 'xdelta3' | 331 | return ' '.join(self.extra) |
317 | #end | 332 | #end |
318 | 333 | ||
319 | def New(self): | 334 | def New(self): |
@@ -624,13 +639,15 @@ class RcsFile: | |||
624 | 639 | ||
625 | target_size = os.stat(self.Verf(v+1)).st_size | 640 | target_size = os.stat(self.Verf(v+1)).st_size |
626 | 641 | ||
627 | print '%s %s %s: %.2f%% encode %.3f ms: decode %.3f ms' % \ | 642 | if 0: |
643 | print '%s %s %s: %.2f%% encode %.3f ms: decode %.3f ms' % \ | ||
628 | (runclass, | 644 | (runclass, |
629 | os.path.basename(self.fname), | 645 | os.path.basename(self.fname), |
630 | self.Vstr(v+1), | 646 | self.Vstr(v+1), |
631 | target_size > 0 and (100.0 * result.encode_size / target_size) or 0, | 647 | target_size > 0 and (100.0 * result.encode_size / target_size) or 0, |
632 | result.encode_time.mean * 1000.0, | 648 | result.encode_time.mean * 1000.0, |
633 | result.decode_time.mean * 1000.0) | 649 | result.decode_time.mean * 1000.0) |
650 | #end | ||
634 | ntrials.append(result) | 651 | ntrials.append(result) |
635 | #end | 652 | #end |
636 | 653 | ||
@@ -716,9 +733,23 @@ class RcsFinder: | |||
716 | good.append(rf) | 733 | good.append(rf) |
717 | #end | 734 | #end |
718 | self.rcsfiles = good | 735 | self.rcsfiles = good |
736 | ReportPairs(runclass, results) | ||
719 | return results | 737 | return results |
720 | #end | 738 | #end |
721 | 739 | ||
740 | def ReportPairs(name, results): | ||
741 | encode_time = 0 | ||
742 | decode_time = 0 | ||
743 | encode_size = 0 | ||
744 | for r in results: | ||
745 | encode_time += r.encode_time.mean | ||
746 | decode_time += r.decode_time.mean | ||
747 | encode_size += r.encode_size | ||
748 | #end | ||
749 | print '%s rcs: encode %.2f s: decode %.2f s: size %d' % \ | ||
750 | (name, encode_time, decode_time, encode_size) | ||
751 | #end | ||
752 | |||
722 | def GetTestRcsFiles(): | 753 | def GetTestRcsFiles(): |
723 | rcsf = RcsFinder() | 754 | rcsf = RcsFinder() |
724 | rcsf.Crawl(RCSDIR) | 755 | rcsf.Crawl(RCSDIR) |
@@ -831,6 +862,17 @@ class RandomTester: | |||
831 | 862 | ||
832 | return config | 863 | return config |
833 | 864 | ||
865 | def ConfigToArgs(self, config): | ||
866 | args = [ '-C', | ||
867 | ','.join([str(x) for x in config[0:SOFT_CONFIG_CNT]])] | ||
868 | for i in range(SOFT_CONFIG_CNT, len(CONFIG_ORDER)): | ||
869 | key = CONFIG_ARGMAP[CONFIG_ORDER[i]] | ||
870 | val = config[i] | ||
871 | args.append('%s=%s' % (key, val)) | ||
872 | #end | ||
873 | return args | ||
874 | #end | ||
875 | |||
834 | def MakeBigFiles(self, rcsf): | 876 | def MakeBigFiles(self, rcsf): |
835 | f1 = open(TMPDIR + "/big.1", "w") | 877 | f1 = open(TMPDIR + "/big.1", "w") |
836 | f2 = open(TMPDIR + "/big.2", "w") | 878 | f2 = open(TMPDIR + "/big.2", "w") |
@@ -871,7 +913,7 @@ class RandomTester: | |||
871 | config = self.RandomConfig() | 913 | config = self.RandomConfig() |
872 | #end | 914 | #end |
873 | 915 | ||
874 | args = [ '-C', ','.join([str(x) for x in config]) ] | 916 | args = self.ConfigToArgs(config) |
875 | result = TimedTest(f2, f1, Xdelta3Runner(args)) | 917 | result = TimedTest(f2, f1, Xdelta3Runner(args)) |
876 | 918 | ||
877 | tr = RandomTestResult(self.round_num, | 919 | tr = RandomTestResult(self.round_num, |
@@ -935,6 +977,19 @@ class RandomTester: | |||
935 | best_by_time = [] | 977 | best_by_time = [] |
936 | 978 | ||
937 | print 'Worst: %s' % scored[len(scored)-1][1] | 979 | print 'Worst: %s' % scored[len(scored)-1][1] |
980 | |||
981 | pos = 0 | ||
982 | for (score, test) in scored: | ||
983 | pos += 1 | ||
984 | test.score_pos = pos | ||
985 | c = c2s(test.config()) | ||
986 | if not test_totals.has_key(c): | ||
987 | test_totals[c] = [test] | ||
988 | else: | ||
989 | test_totals[c].append(test) | ||
990 | #end | ||
991 | #end | ||
992 | |||
938 | scored = [x[1] for x in scored[0:int(MAX_RESULTS * KEEP_P)]] | 993 | scored = [x[1] for x in scored[0:int(MAX_RESULTS * KEEP_P)]] |
939 | 994 | ||
940 | for fast in [x[1] for x in timed[0:int(MAX_RESULTS * FAST_P)]]: | 995 | for fast in [x[1] for x in timed[0:int(MAX_RESULTS * FAST_P)]]: |
@@ -959,16 +1014,8 @@ class RandomTester: | |||
959 | #end | 1014 | #end |
960 | 1015 | ||
961 | r = [] | 1016 | r = [] |
962 | pos = 0 | ||
963 | for test in scored: | 1017 | for test in scored: |
964 | pos += 1 | ||
965 | test.score_pos = pos | ||
966 | c = c2s(test.config()) | 1018 | c = c2s(test.config()) |
967 | if not test_totals.has_key(c): | ||
968 | test_totals[c] = [test] | ||
969 | else: | ||
970 | test_totals[c].append(test) | ||
971 | #end | ||
972 | s = 0.0 | 1019 | s = 0.0 |
973 | self.results.append(test) | 1020 | self.results.append(test) |
974 | r.append(test.config()) | 1021 | r.append(test.config()) |
@@ -1046,19 +1093,6 @@ def RunSampleDataTest(): | |||
1046 | #end | 1093 | #end |
1047 | #end | 1094 | #end |
1048 | 1095 | ||
1049 | def ReportPairs(name, results): | ||
1050 | encode_time = 0 | ||
1051 | decode_time = 0 | ||
1052 | encode_size = 0 | ||
1053 | for r in results: | ||
1054 | encode_time += r.encode_time.mean | ||
1055 | decode_time += r.decode_time.mean | ||
1056 | encode_size += r.encode_size | ||
1057 | #end | ||
1058 | print '%s rcs: encode %.2f s: decode %.2f s: size %d' % \ | ||
1059 | (name, encode_time, decode_time, encode_size) | ||
1060 | #end | ||
1061 | |||
1062 | if __name__ == "__main__": | 1096 | if __name__ == "__main__": |
1063 | try: | 1097 | try: |
1064 | RunCommand(['rm', '-rf', TMPDIR]) | 1098 | RunCommand(['rm', '-rf', TMPDIR]) |
@@ -1066,10 +1100,11 @@ if __name__ == "__main__": | |||
1066 | 1100 | ||
1067 | #RunSpeedTest() | 1101 | #RunSpeedTest() |
1068 | 1102 | ||
1069 | rcsf = GetTestRcsFiles() | 1103 | #rcsf = GetTestRcsFiles() |
1070 | 1104 | ||
1071 | x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-S', 'djw'])) | 1105 | #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9'])) |
1072 | ReportPairs('xd3 -9', x3r) | 1106 | #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-S', 'djw'])) |
1107 | #x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-T'])) | ||
1073 | 1108 | ||
1074 | #x3r = rcsf.AllPairsByDate(Xdelta3RunClass([])) | 1109 | #x3r = rcsf.AllPairsByDate(Xdelta3RunClass([])) |
1075 | #ReportPairs('xdelta3', x3r) | 1110 | #ReportPairs('xdelta3', x3r) |
@@ -1078,7 +1113,7 @@ if __name__ == "__main__": | |||
1078 | #ReportPairs('xdelta1', x1r) | 1113 | #ReportPairs('xdelta1', x1r) |
1079 | 1114 | ||
1080 | #RunRandomRcsTest(rcsf) | 1115 | #RunRandomRcsTest(rcsf) |
1081 | #RunSampleDataTest() | 1116 | RunSampleDataTest() |
1082 | 1117 | ||
1083 | except CommandError: | 1118 | except CommandError: |
1084 | pass | 1119 | pass |
diff --git a/xdelta3/xdelta3.h b/xdelta3/xdelta3.h index cee63cf..b4c0a4e 100644 --- a/xdelta3/xdelta3.h +++ b/xdelta3/xdelta3.h | |||
@@ -51,10 +51,9 @@ | |||
51 | 51 | ||
52 | /* The XD3_HARDMAXWINSIZE parameter is a safety mechanism to protect decoders against | 52 | /* The XD3_HARDMAXWINSIZE parameter is a safety mechanism to protect decoders against |
53 | * malicious files. The decoder will never decode a window larger than this. If the file | 53 | * malicious files. The decoder will never decode a window larger than this. If the file |
54 | * specifies VCD_TARGET the decoder may require two buffers of this size. Rationale for | 54 | * specifies VCD_TARGET the decoder may require two buffers of this size. |
55 | * choosing 22-bits as a maximum: this means that in the worst case, any VCDIFF address | 55 | * |
56 | * without a copy window will require 3 bytes to encode (7 bits per byte, HERE and SAME | 56 | * 8-16MB is reasonable, probably don't need to go larger. |
57 | * modes making every address within half the window away. */ | ||
58 | #ifndef XD3_HARDMAXWINSIZE | 57 | #ifndef XD3_HARDMAXWINSIZE |
59 | #define XD3_HARDMAXWINSIZE (1U<<24) | 58 | #define XD3_HARDMAXWINSIZE (1U<<24) |
60 | #endif | 59 | #endif |
@@ -64,7 +63,7 @@ | |||
64 | * seekable, they are decompressed to a temporary file location and the user may not wish | 63 | * seekable, they are decompressed to a temporary file location and the user may not wish |
65 | * for this. */ | 64 | * for this. */ |
66 | #ifndef XD3_NODECOMPRESSSIZE | 65 | #ifndef XD3_NODECOMPRESSSIZE |
67 | #define XD3_NODECOMPRESSSIZE (1U<<24) | 66 | #define XD3_NODECOMPRESSSIZE (1U<<28) |
68 | #endif | 67 | #endif |
69 | 68 | ||
70 | /* The IOPT_SIZE value sets the size of a buffer used to batch overlapping copy | 69 | /* The IOPT_SIZE value sets the size of a buffer used to batch overlapping copy |