diff options
author | Joshua MacDonald <josh.macdonald@gmail.com> | 2015-11-17 22:52:01 -0800 |
---|---|---|
committer | Joshua MacDonald <josh.macdonald@gmail.com> | 2015-11-17 22:52:01 -0800 |
commit | dc410accc1e1dcef1100d4c047fadb3c6545d172 (patch) | |
tree | 5df6805271e4a6d79b385a25df6f487010593d78 /xdelta3/testing/regtest.cc | |
parent | 97a6543f64e84821b638a60c88c814c2bdcdfc60 (diff) |
Simplifies xd3_srcwin_move_point; reads the full max_winsize before starting to compress (see notes in the corresponding comments); eliminates xd3_stream::frontier_pos; changes as a result, and improvements in testing/regtest.cc; tested on osx-darwin
Diffstat (limited to 'xdelta3/testing/regtest.cc')
-rw-r--r-- | xdelta3/testing/regtest.cc | 177 |
1 files changed, 84 insertions, 93 deletions
diff --git a/xdelta3/testing/regtest.cc b/xdelta3/testing/regtest.cc index eeb0e4b..23c985e 100644 --- a/xdelta3/testing/regtest.cc +++ b/xdelta3/testing/regtest.cc | |||
@@ -790,32 +790,34 @@ void TestSmallStride() { | |||
790 | usize_t size = Constants::BLOCK_SIZE * 4; | 790 | usize_t size = Constants::BLOCK_SIZE * 4; |
791 | spec0.GenerateFixedSize(size); | 791 | spec0.GenerateFixedSize(size); |
792 | 792 | ||
793 | /* TODO Need to study the actual causes of missed adds for tests | 793 | // Note: Not very good performance due to hash collisions, note 3x |
794 | * less than 30 bytes. */ | 794 | // multiplier below. |
795 | const int s = 30; | 795 | for (int s = 15; s < 101; s++) { |
796 | usize_t adds = 0; | 796 | usize_t changes = 0; |
797 | ChangeList cl; | 797 | ChangeList cl; |
798 | for (usize_t j = s; j < size; j += s, ++adds) | 798 | for (usize_t j = s; j < size; j += s, ++changes) |
799 | { | 799 | { |
800 | cl.push_back(Change(Change::MODIFY, 1, j)); | 800 | cl.push_back(Change(Change::MODIFY, 1, j)); |
801 | } | 801 | } |
802 | 802 | ||
803 | FileSpec spec1(&rand); | 803 | FileSpec spec1(&rand); |
804 | spec0.ModifyTo(ChangeListMutator(cl), &spec1); | 804 | spec0.ModifyTo(ChangeListMutator(cl), &spec1); |
805 | 805 | ||
806 | Options options; | 806 | Options options; |
807 | options.encode_srcwin_maxsz = size; | 807 | options.encode_srcwin_maxsz = size; |
808 | options.iopt_size = 128; | 808 | options.iopt_size = 128; |
809 | options.smatch_cfg = XD3_SMATCH_SLOW; | 809 | options.smatch_cfg = XD3_SMATCH_SLOW; |
810 | options.size_known = false; | 810 | options.size_known = false; |
811 | 811 | ||
812 | Block block; | 812 | Block block; |
813 | InMemoryEncodeDecode(spec0, spec1, &block, options); | 813 | InMemoryEncodeDecode(spec0, spec1, &block, options); |
814 | Delta delta(block); | 814 | Delta delta(block); |
815 | 815 | ||
816 | // Allow an additional two byte of add per window | 816 | IF_DEBUG1(DP(RINT "[stride=%d] changes=%u adds=%"Q"u\n", |
817 | usize_t allowance = 2 * size / Constants::WINDOW_SIZE; | 817 | s, changes, delta.AddedBytes())); |
818 | CHECK_GE(adds + allowance, delta.AddedBytes()); | 818 | double allowance = Constants::BLOCK_SIZE < 8192 ? 3.0 : 1.1; |
819 | CHECK_GE(allowance, (double)delta.AddedBytes()); | ||
820 | } | ||
819 | } | 821 | } |
820 | 822 | ||
821 | void TestCopyWindow() { | 823 | void TestCopyWindow() { |
@@ -927,85 +929,73 @@ void TestCopyFromEnd() { | |||
927 | } | 929 | } |
928 | 930 | ||
929 | void TestHalfBlockCopy() { | 931 | void TestHalfBlockCopy() { |
930 | MTRandom rand; | 932 | // Create a half-block copy, 7.5 blocks apart, in a pair of files: |
931 | FileSpec spec0(&rand); | 933 | // 0 1 ... 6 7 |
932 | FileSpec spec1(&rand); | 934 | // spec0 [bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb][ccccc][bbbb_] |
933 | 935 | // spec1 [aaaaa][ccccc][aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_] | |
934 | // The test takes place over four blocks, but we create a 8-block | 936 | // where stage= |
935 | // file to ensure that the whole input doesn't fit in memory. | 937 | // 0: the final block is full |
936 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 8); | 938 | // a. (source)spec1->(target)spec0 copies block C: reads 8 source |
937 | 939 | // blocks during target block 0. | |
938 | // Create a half-block copy, 2.5 blocks apart, from the second half | 940 | // b. (source)spec0->(target)spec1 does not copy block C b/c attempt |
939 | // of the source version to the first half of the target version. | 941 | // to read past EOF empties block 0 from (virtual) block cache |
940 | // 0 1 2 3 | 942 | // 1: the final block is less than full. |
941 | // spec0 [bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb][ccccc][bbbbb...] | 943 | // a. (same) copies block C |
942 | // spec1 [aaaaa][ccccc][aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...] | 944 | // b. (same) copies block C, unlike 0a, no attempt to read past EOF |
943 | ChangeList cl1; | 945 | // |
944 | cl1.push_back(Change(Change::MODIFY, | 946 | // "virtual" above refers to XD3_TOOFARBACK, since there is no caching |
945 | Constants::BLOCK_SIZE / 2, // size | 947 | // in the API, there is simply a promise not to request blocks that are |
946 | 0)); | 948 | // beyond source->max_winsize from the last known source file position. |
947 | cl1.push_back(Change(Change::COPYOVER, | 949 | for (int stage = 0; stage < 2; stage++) |
948 | Constants::BLOCK_SIZE / 2, // size | ||
949 | Constants::BLOCK_SIZE * 3, // offset | ||
950 | Constants::BLOCK_SIZE / 2)); | ||
951 | cl1.push_back(Change(Change::MODIFY, | ||
952 | Constants::BLOCK_SIZE * 7, | ||
953 | Constants::BLOCK_SIZE)); | ||
954 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | ||
955 | |||
956 | const int nocopy_adds = 8 * Constants::BLOCK_SIZE; | ||
957 | const int onecopy_adds = nocopy_adds - Constants::BLOCK_SIZE / 2; | ||
958 | |||
959 | // TODO Note restricted loop | ||
960 | for (int b = 4; b <= 4; b++) | ||
961 | { | 950 | { |
951 | IF_DEBUG1 (DP(RINT "half_block_copy stage %d\n", stage)); | ||
952 | |||
953 | MTRandom rand; | ||
954 | FileSpec spec0(&rand); | ||
955 | FileSpec spec1(&rand); | ||
956 | |||
957 | spec0.GenerateFixedSize(Constants::BLOCK_SIZE * 8 - stage); | ||
958 | |||
959 | ChangeList cl1; | ||
960 | cl1.push_back(Change(Change::MODIFY, | ||
961 | Constants::BLOCK_SIZE / 2, // size | ||
962 | 0)); | ||
963 | cl1.push_back(Change(Change::COPYOVER, | ||
964 | Constants::BLOCK_SIZE / 2, // size | ||
965 | Constants::BLOCK_SIZE * 7, // offset | ||
966 | Constants::BLOCK_SIZE / 2)); | ||
967 | cl1.push_back(Change(Change::MODIFY, | ||
968 | Constants::BLOCK_SIZE * 7, | ||
969 | Constants::BLOCK_SIZE - stage)); | ||
970 | spec0.ModifyTo(ChangeListMutator(cl1), &spec1); | ||
971 | |||
962 | Options options; | 972 | Options options; |
963 | options.encode_srcwin_maxsz = Constants::BLOCK_SIZE * b; | 973 | options.encode_srcwin_maxsz = Constants::BLOCK_SIZE * 8; |
964 | 974 | ||
965 | Block block0; | 975 | Block block0; |
966 | Block block1; | 976 | Block block1; |
967 | InMemoryEncodeDecode(spec0, spec1, &block0, options); | 977 | InMemoryEncodeDecode(spec0, spec1, &block0, options); |
968 | InMemoryEncodeDecode(spec1, spec0, &block1, options); | 978 | InMemoryEncodeDecode(spec1, spec0, &block1, options); |
979 | |||
969 | Delta delta0(block0); | 980 | Delta delta0(block0); |
970 | Delta delta1(block1); | 981 | Delta delta1(block1); |
971 | 982 | ||
972 | // The first block never copies from the last source block, by | 983 | const int yes = |
973 | // design, because if the last source block is available when | 984 | Constants::BLOCK_SIZE * 8 - Constants::BLOCK_SIZE / 2; |
974 | // the first target block is ready, the caller is expected to | 985 | const int no = |
975 | // use a single block. | 986 | Constants::BLOCK_SIZE * 8 - Constants::BLOCK_SIZE / 2; |
976 | CHECK_EQ(nocopy_adds, delta0.AddedBytes()); | 987 | |
977 | if (Constants::BLOCK_SIZE < 8192 || b > 3) | 988 | if (stage == 0) |
978 | { | 989 | { |
979 | // For small-block inputs, the entire file is read into one | 990 | CHECK_EQ(yes, delta0.AddedBytes()); |
980 | // block (the min source window size is 16kB). | 991 | CHECK_EQ(no, delta1.AddedBytes()); |
981 | // | 992 | } |
982 | // For large blocks, at least 4 blocks of source window are | ||
983 | // needed. | ||
984 | CHECK_EQ(onecopy_adds, delta1.AddedBytes()); | ||
985 | } | ||
986 | else | 993 | else |
987 | { | 994 | { |
988 | // When there are fewer than 3 source blocks. | 995 | CHECK_EQ(yes, delta0.AddedBytes()); |
989 | CHECK_EQ(nocopy_adds, delta1.AddedBytes()); | 996 | CHECK_EQ(yes, delta1.AddedBytes()); |
990 | } | 997 | } |
991 | } | 998 | } |
992 | |||
993 | Options options; | ||
994 | options.encode_srcwin_maxsz = Constants::BLOCK_SIZE * 4; | ||
995 | options.block_size = Constants::BLOCK_SIZE * 4; | ||
996 | |||
997 | // Test the whole-buffer case. | ||
998 | Block block0; | ||
999 | Block block1; | ||
1000 | InMemoryEncodeDecode(spec0, spec1, &block0, options); | ||
1001 | InMemoryEncodeDecode(spec1, spec0, &block1, options); | ||
1002 | Delta delta0(block0); | ||
1003 | Delta delta1(block1); | ||
1004 | // This <= >= are only for blocksize = 512, which has irregular readsize. | ||
1005 | CHECK_LE(onecopy_adds, delta0.AddedBytes()); | ||
1006 | CHECK_GE(onecopy_adds + 1, delta0.AddedBytes()); | ||
1007 | |||
1008 | CHECK_EQ(onecopy_adds, delta1.AddedBytes()); | ||
1009 | } | 999 | } |
1010 | 1000 | ||
1011 | void FourWayMergeTest(const FileSpec &spec0, | 1001 | void FourWayMergeTest(const FileSpec &spec0, |
@@ -1299,10 +1289,10 @@ int main(int argc, char **argv) | |||
1299 | mcmd.push_back("test"); | 1289 | mcmd.push_back("test"); |
1300 | mcmd.push_back(NULL); | 1290 | mcmd.push_back(NULL); |
1301 | 1291 | ||
1302 | // UnitTest<SmallBlock>(); | 1292 | UnitTest<SmallBlock>(); |
1303 | // MainTest<SmallBlock>(); | 1293 | MainTest<SmallBlock>(); |
1304 | // MainTest<MixedBlock>(); | 1294 | MainTest<MixedBlock>(); |
1305 | // MainTest<OversizeBlock>(); | 1295 | MainTest<OversizeBlock>(); |
1306 | MainTest<LargeBlock>(); | 1296 | MainTest<LargeBlock>(); |
1307 | 1297 | ||
1308 | CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, | 1298 | CHECK_EQ(0, xd3_main_cmdline(mcmd.size() - 1, |
@@ -1310,3 +1300,4 @@ int main(int argc, char **argv) | |||
1310 | 1300 | ||
1311 | return 0; | 1301 | return 0; |
1312 | } | 1302 | } |
1303 | |||