##// END OF EJS Templates
deltas: add a debug-delta-find command to analyse delta search...
marmoute -
r50123:b909dd35 default
parent child Browse files
Show More
@@ -73,6 +73,7 b' from . import ('
73 repoview,
73 repoview,
74 requirements,
74 requirements,
75 revlog,
75 revlog,
76 revlogutils,
76 revset,
77 revset,
77 revsetlang,
78 revsetlang,
78 scmutil,
79 scmutil,
@@ -989,6 +990,65 b' def debugdeltachain(ui, repo, file_=None'
989
990
990
991
991 @command(
992 @command(
993 b'debug-delta-find',
994 cmdutil.debugrevlogopts + cmdutil.formatteropts,
995 _(b'-c|-m|FILE REV'),
996 optionalrepo=True,
997 )
998 def debugdeltafind(ui, repo, arg_1, arg_2=None, **opts):
999 """display the computation to get to a valid delta for storing REV
1000
1001 This command will replay the process used to find the "best" delta to store
1002 a revision and display information about all the steps used to get to that
1003 result.
1004
1005 The revision use the revision number of the target storage (not changelog
1006 revision number).
1007
1008 note: the process is initiated from a full text of the revision to store.
1009 """
1010 opts = pycompat.byteskwargs(opts)
1011 if arg_2 is None:
1012 file_ = None
1013 rev = arg_1
1014 else:
1015 file_ = arg_1
1016 rev = arg_2
1017
1018 rev = int(rev)
1019
1020 revlog = cmdutil.openrevlog(repo, b'debugdeltachain', file_, opts)
1021
1022 deltacomputer = deltautil.deltacomputer(
1023 revlog,
1024 write_debug=ui.write,
1025 debug_search=True,
1026 )
1027
1028 node = revlog.node(rev)
1029 p1r, p2r = revlog.parentrevs(rev)
1030 p1 = revlog.node(p1r)
1031 p2 = revlog.node(p2r)
1032 btext = [revlog.revision(rev)]
1033 textlen = len(btext[0])
1034 cachedelta = None
1035 flags = revlog.flags(rev)
1036
1037 revinfo = revlogutils.revisioninfo(
1038 node,
1039 p1,
1040 p2,
1041 btext,
1042 textlen,
1043 cachedelta,
1044 flags,
1045 )
1046
1047 fh = revlog._datafp()
1048 deltacomputer.finddeltainfo(revinfo, fh, target_rev=rev)
1049
1050
1051 @command(
992 b'debugdirstate|debugstate',
1052 b'debugdirstate|debugstate',
993 [
1053 [
994 (
1054 (
@@ -931,9 +931,10 b' def _rawgroups(revlog, p1, p2, cachedelt'
931
931
932
932
933 class deltacomputer:
933 class deltacomputer:
934 def __init__(self, revlog, write_debug=None):
934 def __init__(self, revlog, write_debug=None, debug_search=False):
935 self.revlog = revlog
935 self.revlog = revlog
936 self._write_debug = write_debug
936 self._write_debug = write_debug
937 self._debug_search = debug_search
937
938
938 def buildtext(self, revinfo, fh):
939 def buildtext(self, revinfo, fh):
939 """Builds a fulltext version of a revision
940 """Builds a fulltext version of a revision
@@ -980,6 +981,7 b' class deltacomputer:'
980 def _builddeltainfo(self, revinfo, base, fh):
981 def _builddeltainfo(self, revinfo, base, fh):
981 # can we use the cached delta?
982 # can we use the cached delta?
982 revlog = self.revlog
983 revlog = self.revlog
984 debug_search = self._write_debug is not None and self._debug_search
983 chainbase = revlog.chainbase(base)
985 chainbase = revlog.chainbase(base)
984 if revlog._generaldelta:
986 if revlog._generaldelta:
985 deltabase = base
987 deltabase = base
@@ -1009,13 +1011,27 b' class deltacomputer:'
1009 delta = revinfo.cachedelta[1]
1011 delta = revinfo.cachedelta[1]
1010 if delta is None:
1012 if delta is None:
1011 delta = self._builddeltadiff(base, revinfo, fh)
1013 delta = self._builddeltadiff(base, revinfo, fh)
1014 if debug_search:
1015 msg = b"DBG-DELTAS-SEARCH: uncompressed-delta-size=%d\n"
1016 msg %= len(delta)
1017 self._write_debug(msg)
1012 # snapshotdept need to be neither None nor 0 level snapshot
1018 # snapshotdept need to be neither None nor 0 level snapshot
1013 if revlog.upperboundcomp is not None and snapshotdepth:
1019 if revlog.upperboundcomp is not None and snapshotdepth:
1014 lowestrealisticdeltalen = len(delta) // revlog.upperboundcomp
1020 lowestrealisticdeltalen = len(delta) // revlog.upperboundcomp
1015 snapshotlimit = revinfo.textlen >> snapshotdepth
1021 snapshotlimit = revinfo.textlen >> snapshotdepth
1022 if debug_search:
1023 msg = b"DBG-DELTAS-SEARCH: projected-lower-size=%d\n"
1024 msg %= lowestrealisticdeltalen
1025 self._write_debug(msg)
1016 if snapshotlimit < lowestrealisticdeltalen:
1026 if snapshotlimit < lowestrealisticdeltalen:
1027 if debug_search:
1028 msg = b"DBG-DELTAS-SEARCH: DISCARDED (snapshot limit)\n"
1029 self._write_debug(msg)
1017 return None
1030 return None
1018 if revlog.length(base) < lowestrealisticdeltalen:
1031 if revlog.length(base) < lowestrealisticdeltalen:
1032 if debug_search:
1033 msg = b"DBG-DELTAS-SEARCH: DISCARDED (prev size)\n"
1034 self._write_debug(msg)
1019 return None
1035 return None
1020 header, data = revlog.compress(delta)
1036 header, data = revlog.compress(delta)
1021 deltalen = len(header) + len(data)
1037 deltalen = len(header) + len(data)
@@ -1090,6 +1106,8 b' class deltacomputer:'
1090 if self._write_debug is not None:
1106 if self._write_debug is not None:
1091 start = util.timer()
1107 start = util.timer()
1092
1108
1109 debug_search = self._write_debug is not None and self._debug_search
1110
1093 # count the number of different delta we tried (for debug purpose)
1111 # count the number of different delta we tried (for debug purpose)
1094 dbg_try_count = 0
1112 dbg_try_count = 0
1095 # count the number of "search round" we did. (for debug purpose)
1113 # count the number of "search round" we did. (for debug purpose)
@@ -1113,6 +1131,10 b' class deltacomputer:'
1113 p2_chain_len = revlog._chaininfo(p2r)[0]
1131 p2_chain_len = revlog._chaininfo(p2r)[0]
1114 else:
1132 else:
1115 p2_chain_len = -1
1133 p2_chain_len = -1
1134 if debug_search:
1135 msg = b"DBG-DELTAS-SEARCH: SEARCH rev=%d\n"
1136 msg %= target_rev
1137 self._write_debug(msg)
1116
1138
1117 groups = _candidategroups(
1139 groups = _candidategroups(
1118 self.revlog, revinfo.textlen, p1r, p2r, cachedelta
1140 self.revlog, revinfo.textlen, p1r, p2r, cachedelta
@@ -1120,21 +1142,93 b' class deltacomputer:'
1120 candidaterevs = next(groups)
1142 candidaterevs = next(groups)
1121 while candidaterevs is not None:
1143 while candidaterevs is not None:
1122 dbg_try_rounds += 1
1144 dbg_try_rounds += 1
1145 if debug_search:
1146 prev = None
1147 if deltainfo is not None:
1148 prev = deltainfo.base
1149
1150 if p1 in candidaterevs or p2 in candidaterevs:
1151 round_type = b"parents"
1152 elif prev is not None and all(c < prev for c in candidaterevs):
1153 round_type = b"refine-down"
1154 elif prev is not None and all(c > prev for c in candidaterevs):
1155 round_type = b"refine-up"
1156 else:
1157 round_type = b"search-down"
1158 msg = b"DBG-DELTAS-SEARCH: ROUND #%d - %d candidates - %s\n"
1159 msg %= (dbg_try_rounds, len(candidaterevs), round_type)
1160 self._write_debug(msg)
1123 nominateddeltas = []
1161 nominateddeltas = []
1124 if deltainfo is not None:
1162 if deltainfo is not None:
1163 if debug_search:
1164 msg = (
1165 b"DBG-DELTAS-SEARCH: CONTENDER: rev=%d - length=%d\n"
1166 )
1167 msg %= (deltainfo.base, deltainfo.deltalen)
1168 self._write_debug(msg)
1125 # if we already found a good delta,
1169 # if we already found a good delta,
1126 # challenge it against refined candidates
1170 # challenge it against refined candidates
1127 nominateddeltas.append(deltainfo)
1171 nominateddeltas.append(deltainfo)
1128 for candidaterev in candidaterevs:
1172 for candidaterev in candidaterevs:
1173 if debug_search:
1174 msg = b"DBG-DELTAS-SEARCH: CANDIDATE: rev=%d\n"
1175 msg %= candidaterev
1176 self._write_debug(msg)
1177 candidate_type = None
1178 if candidaterev == p1:
1179 candidate_type = b"p1"
1180 elif candidaterev == p2:
1181 candidate_type = b"p2"
1182 elif self.revlog.issnapshot(candidaterev):
1183 candidate_type = b"snapshot-%d"
1184 candidate_type %= self.revlog.snapshotdepth(
1185 candidaterev
1186 )
1187
1188 if candidate_type is not None:
1189 msg = b"DBG-DELTAS-SEARCH: type=%s\n"
1190 msg %= candidate_type
1191 self._write_debug(msg)
1192 msg = b"DBG-DELTAS-SEARCH: size=%d\n"
1193 msg %= self.revlog.length(candidaterev)
1194 self._write_debug(msg)
1195 msg = b"DBG-DELTAS-SEARCH: base=%d\n"
1196 msg %= self.revlog.deltaparent(candidaterev)
1197 self._write_debug(msg)
1129 if candidaterev in excluded_bases:
1198 if candidaterev in excluded_bases:
1199 if debug_search:
1200 msg = b"DBG-DELTAS-SEARCH: EXCLUDED\n"
1201 self._write_debug(msg)
1130 continue
1202 continue
1131 if candidaterev >= target_rev:
1203 if candidaterev >= target_rev:
1204 if debug_search:
1205 msg = b"DBG-DELTAS-SEARCH: TOO-HIGH\n"
1206 self._write_debug(msg)
1132 continue
1207 continue
1133 dbg_try_count += 1
1208 dbg_try_count += 1
1209
1210 if debug_search:
1211 delta_start = util.timer()
1134 candidatedelta = self._builddeltainfo(revinfo, candidaterev, fh)
1212 candidatedelta = self._builddeltainfo(revinfo, candidaterev, fh)
1213 if debug_search:
1214 delta_end = util.timer()
1215 msg = b"DBG-DELTAS-SEARCH: delta-search-time=%f\n"
1216 msg %= delta_end - delta_start
1217 self._write_debug(msg)
1135 if candidatedelta is not None:
1218 if candidatedelta is not None:
1136 if isgooddeltainfo(self.revlog, candidatedelta, revinfo):
1219 if isgooddeltainfo(self.revlog, candidatedelta, revinfo):
1220 if debug_search:
1221 msg = b"DBG-DELTAS-SEARCH: DELTA: length=%d (GOOD)\n"
1222 msg %= candidatedelta.deltalen
1223 self._write_debug(msg)
1137 nominateddeltas.append(candidatedelta)
1224 nominateddeltas.append(candidatedelta)
1225 elif debug_search:
1226 msg = b"DBG-DELTAS-SEARCH: DELTA: length=%d (BAD)\n"
1227 msg %= candidatedelta.deltalen
1228 self._write_debug(msg)
1229 elif debug_search:
1230 msg = b"DBG-DELTAS-SEARCH: NO-DELTA\n"
1231 self._write_debug(msg)
1138 if nominateddeltas:
1232 if nominateddeltas:
1139 deltainfo = min(nominateddeltas, key=lambda x: x.deltalen)
1233 deltainfo = min(nominateddeltas, key=lambda x: x.deltalen)
1140 if deltainfo is not None:
1234 if deltainfo is not None:
@@ -1145,7 +1239,7 b' class deltacomputer:'
1145 if deltainfo is None:
1239 if deltainfo is None:
1146 dbg_type = b"full"
1240 dbg_type = b"full"
1147 deltainfo = self._fullsnapshotinfo(fh, revinfo, target_rev)
1241 deltainfo = self._fullsnapshotinfo(fh, revinfo, target_rev)
1148 elif deltainfo.snapshotdepth:
1242 elif deltainfo.snapshotdepth: # pytype: disable=attribute-error
1149 dbg_type = b"snapshot"
1243 dbg_type = b"snapshot"
1150 else:
1244 else:
1151 dbg_type = b"delta"
1245 dbg_type = b"delta"
@@ -1161,8 +1255,13 b' class deltacomputer:'
1161 'p1-chain-len': p1_chain_len,
1255 'p1-chain-len': p1_chain_len,
1162 'p2-chain-len': p2_chain_len,
1256 'p2-chain-len': p2_chain_len,
1163 }
1257 }
1164 if deltainfo.snapshotdepth is not None:
1258 if (
1165 dbg['snapshot-depth'] = deltainfo.snapshotdepth
1259 deltainfo.snapshotdepth # pytype: disable=attribute-error
1260 is not None
1261 ):
1262 dbg[
1263 'snapshot-depth'
1264 ] = deltainfo.snapshotdepth # pytype: disable=attribute-error
1166 else:
1265 else:
1167 dbg['snapshot-depth'] = 0
1266 dbg['snapshot-depth'] = 0
1168 target_revlog = b"UNKNOWN"
1267 target_revlog = b"UNKNOWN"
@@ -74,6 +74,7 b' Do not show debug commands if there are '
74
74
75 Show debug commands if there are no other candidates
75 Show debug commands if there are no other candidates
76 $ hg debugcomplete debug
76 $ hg debugcomplete debug
77 debug-delta-find
77 debug-repair-issue6528
78 debug-repair-issue6528
78 debugancestor
79 debugancestor
79 debugantivirusrunning
80 debugantivirusrunning
@@ -267,6 +268,7 b' Show all commands + options'
267 config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template
268 config: untrusted, exp-all-known, edit, local, source, shared, non-shared, global, template
268 continue: dry-run
269 continue: dry-run
269 copy: forget, after, at-rev, force, include, exclude, dry-run
270 copy: forget, after, at-rev, force, include, exclude, dry-run
271 debug-delta-find: changelog, manifest, dir, template
270 debug-repair-issue6528: to-report, from-report, paranoid, dry-run
272 debug-repair-issue6528: to-report, from-report, paranoid, dry-run
271 debugancestor:
273 debugancestor:
272 debugantivirusrunning:
274 debugantivirusrunning:
@@ -978,6 +978,8 b' Test list of internal help commands'
978 $ hg help debug
978 $ hg help debug
979 debug commands (internal and unsupported):
979 debug commands (internal and unsupported):
980
980
981 debug-delta-find
982 display the computation to get to a valid delta for storing REV
981 debug-repair-issue6528
983 debug-repair-issue6528
982 find affected revisions and repair them. See issue6528 for more
984 find affected revisions and repair them. See issue6528 for more
983 details.
985 details.
@@ -149,4 +149,46 b' repeatedly while some of it changes rare'
149 deltas against p2 : 63 ( 1.36%)
149 deltas against p2 : 63 ( 1.36%)
150 deltas against other : 0 ( 0.00%)
150 deltas against other : 0 ( 0.00%)
151
151
152
153 Test `debug-delta-find`
154 -----------------------
155
156 $ ls -1
157 SPARSE-REVLOG-TEST-FILE
158 $ hg debugdeltachain SPARSE-REVLOG-TEST-FILE | grep other | tail -1
159 4971 3 5 4930 other 19179 346472 427596 1.23414 15994877 15567281 36.40652 427596 179288 1.00000 5
160 $ hg debug-delta-find SPARSE-REVLOG-TEST-FILE 4971
161 DBG-DELTAS-SEARCH: SEARCH rev=4971
162 DBG-DELTAS-SEARCH: ROUND #1 - 2 candidates - search-down
163 DBG-DELTAS-SEARCH: CANDIDATE: rev=4962
164 DBG-DELTAS-SEARCH: type=snapshot-4
165 DBG-DELTAS-SEARCH: size=18296
166 DBG-DELTAS-SEARCH: base=4930
167 DBG-DELTAS-SEARCH: uncompressed-delta-size=30377
168 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
169 DBG-DELTAS-SEARCH: DELTA: length=16872 (BAD)
170 DBG-DELTAS-SEARCH: CANDIDATE: rev=4971
171 DBG-DELTAS-SEARCH: type=snapshot-4
172 DBG-DELTAS-SEARCH: size=19179
173 DBG-DELTAS-SEARCH: base=4930
174 DBG-DELTAS-SEARCH: TOO-HIGH
175 DBG-DELTAS-SEARCH: ROUND #2 - 1 candidates - search-down
176 DBG-DELTAS-SEARCH: CANDIDATE: rev=4930
177 DBG-DELTAS-SEARCH: type=snapshot-3
178 DBG-DELTAS-SEARCH: size=39228
179 DBG-DELTAS-SEARCH: base=4799
180 DBG-DELTAS-SEARCH: uncompressed-delta-size=33050
181 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
182 DBG-DELTAS-SEARCH: DELTA: length=19179 (GOOD)
183 DBG-DELTAS-SEARCH: ROUND #3 - 1 candidates - refine-down
184 DBG-DELTAS-SEARCH: CONTENDER: rev=4930 - length=19179
185 DBG-DELTAS-SEARCH: CANDIDATE: rev=4799
186 DBG-DELTAS-SEARCH: type=snapshot-2
187 DBG-DELTAS-SEARCH: size=50213
188 DBG-DELTAS-SEARCH: base=4623
189 DBG-DELTAS-SEARCH: uncompressed-delta-size=82661
190 DBG-DELTAS-SEARCH: delta-search-time=* (glob)
191 DBG-DELTAS-SEARCH: DELTA: length=49132 (BAD)
192 DBG-DELTAS: FILELOG:SPARSE-REVLOG-TEST-FILE: rev=4971: search-rounds=3 try-count=3 - delta-type=snapshot snap-depth=4 - p1-chain-length=15 p2-chain-length=-1 - duration=* (glob)
193
152 $ cd ..
194 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now