summaryrefslogtreecommitdiff
path: root/xdelta3
diff options
context:
space:
mode:
authorjosh.macdonald <jmacd@users.noreply.github.com>2007-11-10 21:27:30 +0000
committerjosh.macdonald <jmacd@users.noreply.github.com>2007-11-10 21:27:30 +0000
commit9c137e5d088878e6867b5de40ddefa30a7afa59c (patch)
tree9a8c2a382b77944e88fb5bd05bc0699ed8057aec /xdelta3
parent6c303e681012e5abf252d28eaff0a5d084a18f64 (diff)
Adds output regarding inefficient copy instructions to "printdelta".
Adds crude inefficiency check to xd3_smatch(), preventing 4-byte matches if (here-addr) >= 2^14 and 5-byte matches if (here-addr) >= 2^21. Nice improvement.
Diffstat (limited to 'xdelta3')
-rw-r--r--xdelta3/Makefile9
-rw-r--r--xdelta3/xdelta3-main.h27
-rw-r--r--xdelta3/xdelta3.c49
3 files changed, 69 insertions, 16 deletions
diff --git a/xdelta3/Makefile b/xdelta3/Makefile
index 19afc42..9c8b79e 100644
--- a/xdelta3/Makefile
+++ b/xdelta3/Makefile
@@ -218,8 +218,13 @@ xdelta3-everything: $(SOURCES)
218 -DXD3_DEBUG=1 -lm 218 -DXD3_DEBUG=1 -lm
219 219
220xdelta3-Opg: $(SOURCES) 220xdelta3-Opg: $(SOURCES)
221 $(CC) -pg -g -O -Wall -Wshadow xdelta3.c -o xdelta3-Opg -DXD3_MAIN=1 \ 221 $(CC) -pg -g -O3 -fno-builtin -Wall -Wshadow xdelta3.c -o xdelta3-Opg \
222 -DSECONDARY_DJW=1 -DSECONDARY_FGK=1 -DXD3_POSIX=1 -DXD3_USE_LARGEFILE64=1 -DREGRESSION_TEST=1 222 -DXD3_MAIN=1 \
223 -DSECONDARY_DJW=1 \
224 -DSECONDARY_FGK=1 \
225 -DXD3_POSIX=1 \
226 -DXD3_USE_LARGEFILE64=1 \
227 -DREGRESSION_TEST=1
223 228
224xdelta3-nosec.o: $(SOURCES) 229xdelta3-nosec.o: $(SOURCES)
225 $(CC) -O2 -Wall -Wshadow -c xdelta3.c -DSECONDARY_FGK=0 -DSECONDARY_DJW=0 -o xdelta3-nosec.o 230 $(CC) -O2 -Wall -Wshadow -c xdelta3.c -DSECONDARY_FGK=0 -DSECONDARY_DJW=0 -o xdelta3-nosec.o
diff --git a/xdelta3/xdelta3-main.h b/xdelta3/xdelta3-main.h
index 6be82dc..23133a3 100644
--- a/xdelta3/xdelta3-main.h
+++ b/xdelta3/xdelta3-main.h
@@ -1138,7 +1138,12 @@ main_print_window (xd3_stream* stream, main_file *xfile)
1138 1138
1139 while (stream->inst_sect.buf < stream->inst_sect.buf_max) 1139 while (stream->inst_sect.buf < stream->inst_sect.buf_max)
1140 { 1140 {
1141 uint code = stream->inst_sect.buf[0]; 1141 uint code = stream->inst_sect.buf[0];
1142 const uint8_t *addr_before = stream->addr_sect.buf;
1143 const uint8_t *inst_before = stream->inst_sect.buf;
1144 usize_t addr_bytes;
1145 usize_t inst_bytes;
1146 usize_t size_before = size;
1142 1147
1143 if ((ret = xd3_decode_instruction (stream))) 1148 if ((ret = xd3_decode_instruction (stream)))
1144 { 1149 {
@@ -1147,13 +1152,15 @@ main_print_window (xd3_stream* stream, main_file *xfile)
1147 return ret; 1152 return ret;
1148 } 1153 }
1149 1154
1155 addr_bytes = stream->addr_sect.buf - addr_before;
1156 inst_bytes = stream->inst_sect.buf - inst_before;
1157
1150 VC(UT " %06"Q"u %03u %s %3u", stream->dec_winstart + size, code, 1158 VC(UT " %06"Q"u %03u %s %3u", stream->dec_winstart + size, code,
1151 xd3_rtype_to_string (stream->dec_current1.type, option_print_cpymode), 1159 xd3_rtype_to_string (stream->dec_current1.type, option_print_cpymode),
1152 (usize_t) stream->dec_current1.size)VE; 1160 (usize_t) stream->dec_current1.size)VE;
1153 1161
1154 if (stream->dec_current1.type != XD3_NOOP) 1162 if (stream->dec_current1.type != XD3_NOOP)
1155 { 1163 {
1156 size += stream->dec_current1.size;
1157 if (stream->dec_current1.type >= XD3_CPY) 1164 if (stream->dec_current1.type >= XD3_CPY)
1158 { 1165 {
1159 VC(UT " @%-6u", (usize_t)stream->dec_current1.addr)VE; 1166 VC(UT " @%-6u", (usize_t)stream->dec_current1.addr)VE;
@@ -1162,11 +1169,12 @@ main_print_window (xd3_stream* stream, main_file *xfile)
1162 { 1169 {
1163 VC(UT " ")VE; 1170 VC(UT " ")VE;
1164 } 1171 }
1172
1173 size += stream->dec_current1.size;
1165 } 1174 }
1166 1175
1167 if (stream->dec_current2.type != XD3_NOOP) 1176 if (stream->dec_current2.type != XD3_NOOP)
1168 { 1177 {
1169 size += stream->dec_current2.size;
1170 VC(UT " %s %3u", 1178 VC(UT " %s %3u",
1171 xd3_rtype_to_string (stream->dec_current2.type, 1179 xd3_rtype_to_string (stream->dec_current2.type,
1172 option_print_cpymode), 1180 option_print_cpymode),
@@ -1176,9 +1184,22 @@ main_print_window (xd3_stream* stream, main_file *xfile)
1176 { 1184 {
1177 VC(UT " @%-6u", (usize_t)stream->dec_current2.addr)VE; 1185 VC(UT " @%-6u", (usize_t)stream->dec_current2.addr)VE;
1178 } 1186 }
1187
1188 size += stream->dec_current2.size;
1179 } 1189 }
1180 1190
1181 VC(UT "\n")VE; 1191 VC(UT "\n")VE;
1192
1193 if (option_verbose &&
1194 addr_bytes + inst_bytes >= (size - size_before) &&
1195 (stream->dec_current1.type >= XD3_CPY ||
1196 stream->dec_current2.type >= XD3_CPY))
1197 {
1198 VC(UT " %06"Q"u (inefficiency) %u encoded as %u bytes\n",
1199 stream->dec_winstart + size_before,
1200 size - size_before,
1201 addr_bytes + inst_bytes)VE;
1202 }
1182 } 1203 }
1183 1204
1184 if (stream->dec_tgtlen != size && (stream->flags & XD3_SKIP_WINDOW) == 0) 1205 if (stream->dec_tgtlen != size && (stream->flags & XD3_SKIP_WINDOW) == 0)
diff --git a/xdelta3/xdelta3.c b/xdelta3/xdelta3.c
index 197c7ed..cf2d224 100644
--- a/xdelta3/xdelta3.c
+++ b/xdelta3/xdelta3.c
@@ -968,7 +968,9 @@ xd3_build_code_table (const xd3_code_table_desc *desc, xd3_dinst *tbl)
968 { 968 {
969 for (size1 = 1; size1 <= desc->addcopy_add_max; size1 += 1) 969 for (size1 = 1; size1 <= desc->addcopy_add_max; size1 += 1)
970 { 970 {
971 int max = (mode < 2 + desc->near_modes) ? desc->addcopy_near_cpy_max : desc->addcopy_same_cpy_max; 971 int max = (mode < 2 + desc->near_modes) ?
972 desc->addcopy_near_cpy_max :
973 desc->addcopy_same_cpy_max;
972 974
973 for (size2 = MIN_MATCH; size2 <= max; size2 += 1, d += 1) 975 for (size2 = MIN_MATCH; size2 <= max; size2 += 1, d += 1)
974 { 976 {
@@ -982,7 +984,9 @@ xd3_build_code_table (const xd3_code_table_desc *desc, xd3_dinst *tbl)
982 984
983 for (mode = 0; mode < cpy_modes; mode += 1) 985 for (mode = 0; mode < cpy_modes; mode += 1)
984 { 986 {
985 int max = (mode < 2 + desc->near_modes) ? desc->copyadd_near_cpy_max : desc->copyadd_same_cpy_max; 987 int max = (mode < 2 + desc->near_modes) ?
988 desc->copyadd_near_cpy_max :
989 desc->copyadd_same_cpy_max;
986 990
987 for (size1 = MIN_MATCH; size1 <= max; size1 += 1) 991 for (size1 = MIN_MATCH; size1 <= max; size1 += 1)
988 { 992 {
@@ -1073,7 +1077,9 @@ xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_ri
1073 { 1077 {
1074 /* The second and third exprs are 0 in the 1078 /* The second and third exprs are 0 in the
1075 default table. */ 1079 default table. */
1076 prev->code2 = sizes->offset + (sizes->mult * (prev->size - MIN_MATCH)) + (inst->size - MIN_ADD); 1080 prev->code2 = sizes->offset +
1081 (sizes->mult * (prev->size - MIN_MATCH)) +
1082 (inst->size - MIN_ADD);
1077 } 1083 }
1078 } 1084 }
1079 } 1085 }
@@ -1105,7 +1111,9 @@ xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_ri
1105 1111
1106 if (inst->size <= sizes->cpy_max) 1112 if (inst->size <= sizes->cpy_max)
1107 { 1113 {
1108 prev->code2 = sizes->offset + (sizes->mult * (prev->size - MIN_ADD)) + (inst->size - MIN_MATCH); 1114 prev->code2 = sizes->offset +
1115 (sizes->mult * (prev->size - MIN_ADD)) +
1116 (inst->size - MIN_MATCH);
1109 } 1117 }
1110 } 1118 }
1111 } 1119 }
@@ -1116,7 +1124,7 @@ xd3_choose_instruction (const xd3_code_table_desc *desc, xd3_rinst *prev, xd3_ri
1116 1124
1117/* This version of xd3_choose_instruction is hard-coded for the default table. */ 1125/* This version of xd3_choose_instruction is hard-coded for the default table. */
1118static void 1126static void
1119xd3_choose_instruction (/* const xd3_code_table_desc *desc,*/ xd3_rinst *prev, xd3_rinst *inst) 1127xd3_choose_instruction (xd3_rinst *prev, xd3_rinst *inst)
1120{ 1128{
1121 switch (inst->type) 1129 switch (inst->type)
1122 { 1130 {
@@ -3121,9 +3129,12 @@ xd3_iopt_flush_instructions (xd3_stream *stream, int force)
3121 r2moff = r2end - r1end; 3129 r2moff = r2end - r1end;
3122 gap = r2end - r1->pos; 3130 gap = r2end - r1->pos;
3123 3131
3124 /* If the two matches overlap almost entirely, choose the better 3132 /* If the two matches overlap almost entirely, choose the better match
3125 * match and discard the other. This heuristic is BLACK MAGIC. 3133 * and discard the other. The else branch can still create inefficient
3126 * Havesomething better? */ 3134 * copies, e.g., a 4-byte copy that takes 4 bytes to encode, which
3135 * xd3_smatch() wouldn't allow by its crude efficiency check. However,
3136 * in this case there are adjacent copies which mean the add would cost
3137 * one extra byte. Allow the inefficiency here. */
3127 if (gap < 2*MIN_MATCH || r2moff <= 2 || r2off <= 2) 3138 if (gap < 2*MIN_MATCH || r2moff <= 2 || r2off <= 2)
3128 { 3139 {
3129 /* Only one match should be used, choose the longer one. */ 3140 /* Only one match should be used, choose the longer one. */
@@ -4783,9 +4794,6 @@ xd3_check_smatch (const uint8_t *ref0, const uint8_t *inp0,
4783 * linked lists are in use (because stream->smatcher.small_chain > 1), 4794 * linked lists are in use (because stream->smatcher.small_chain > 1),
4784 * previous matches are tested searching for the longest match. If 4795 * previous matches are tested searching for the longest match. If
4785 * (stream->min_match > MIN_MATCH) then a lazy match is in effect. 4796 * (stream->min_match > MIN_MATCH) then a lazy match is in effect.
4786 *
4787 * TODO: This is the second most-expensive function, after
4788 * xd3_srcwin_move_point().
4789 */ 4797 */
4790static usize_t 4798static usize_t
4791xd3_smatch (xd3_stream *stream, 4799xd3_smatch (xd3_stream *stream,
@@ -4872,6 +4880,25 @@ xd3_smatch (xd3_stream *stream,
4872 } 4880 }
4873 4881
4874 done: 4882 done:
4883 /* Crude efficiency test: if the match is very short and very far back, it's
4884 * unlikely to help, but the exact calculation requires knowing the state of
4885 * the address cache and adjacent instructions, which we can't do here.
4886 * Rather than encode a probably inefficient copy here and check it later
4887 * (which complicates the code a lot), do this:
4888 */
4889 if (match_length == 4 && stream->input_position - (*match_offset) >= 1<<14)
4890 {
4891 /* It probably takes >2 bytes to encode an address >= 2^14 from here */
4892 return 0;
4893 }
4894 if (match_length == 5 && stream->input_position - (*match_offset) >= 1<<21)
4895 {
4896 /* It probably takes >3 bytes to encode an address >= 2^21 from here */
4897 return 0;
4898 }
4899
4900 /* It's unlikely that a window is large enough for the (match_length == 6 &&
4901 * address >= 2^28) check */
4875 return match_length; 4902 return match_length;
4876} 4903}
4877 4904