comparison mercurial/debugcommands.py @ 49660:bd3b6f363fb9

debug-revlog: move the code in revlogutils module We have a module dedicated to debug code, let us use it.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 07 Nov 2022 14:24:52 -0500
parents 7c0a383849a8
children 4302db0f54c8
comparison
equal deleted inserted replaced
49659:7c0a383849a8 49660:bd3b6f363fb9
19 import random 19 import random
20 import re 20 import re
21 import socket 21 import socket
22 import ssl 22 import ssl
23 import stat 23 import stat
24 import string
25 import subprocess 24 import subprocess
26 import sys 25 import sys
27 import time 26 import time
28 27
29 from .i18n import _ 28 from .i18n import _
3239 opts = pycompat.byteskwargs(opts) 3238 opts = pycompat.byteskwargs(opts)
3240 r = cmdutil.openrevlog(repo, b'debugrevlog', file_, opts) 3239 r = cmdutil.openrevlog(repo, b'debugrevlog', file_, opts)
3241 3240
3242 if opts.get(b"dump"): 3241 if opts.get(b"dump"):
3243 revlog_debug.dump(ui, r) 3242 revlog_debug.dump(ui, r)
3244 return 0
3245
3246 format = r._format_version
3247 v = r._format_flags
3248 flags = []
3249 gdelta = False
3250 if v & revlog.FLAG_INLINE_DATA:
3251 flags.append(b'inline')
3252 if v & revlog.FLAG_GENERALDELTA:
3253 gdelta = True
3254 flags.append(b'generaldelta')
3255 if not flags:
3256 flags = [b'(none)']
3257
3258 ### tracks merge vs single parent
3259 nummerges = 0
3260
3261 ### tracks ways the "delta" are build
3262 # nodelta
3263 numempty = 0
3264 numemptytext = 0
3265 numemptydelta = 0
3266 # full file content
3267 numfull = 0
3268 # intermediate snapshot against a prior snapshot
3269 numsemi = 0
3270 # snapshot count per depth
3271 numsnapdepth = collections.defaultdict(lambda: 0)
3272 # delta against previous revision
3273 numprev = 0
3274 # delta against first or second parent (not prev)
3275 nump1 = 0
3276 nump2 = 0
3277 # delta against neither prev nor parents
3278 numother = 0
3279 # delta against prev that are also first or second parent
3280 # (details of `numprev`)
3281 nump1prev = 0
3282 nump2prev = 0
3283
3284 # data about delta chain of each revs
3285 chainlengths = []
3286 chainbases = []
3287 chainspans = []
3288
3289 # data about each revision
3290 datasize = [None, 0, 0]
3291 fullsize = [None, 0, 0]
3292 semisize = [None, 0, 0]
3293 # snapshot count per depth
3294 snapsizedepth = collections.defaultdict(lambda: [None, 0, 0])
3295 deltasize = [None, 0, 0]
3296 chunktypecounts = {}
3297 chunktypesizes = {}
3298
3299 def addsize(size, l):
3300 if l[0] is None or size < l[0]:
3301 l[0] = size
3302 if size > l[1]:
3303 l[1] = size
3304 l[2] += size
3305
3306 numrevs = len(r)
3307 for rev in range(numrevs):
3308 p1, p2 = r.parentrevs(rev)
3309 delta = r.deltaparent(rev)
3310 if format > 0:
3311 addsize(r.rawsize(rev), datasize)
3312 if p2 != nullrev:
3313 nummerges += 1
3314 size = r.length(rev)
3315 if delta == nullrev:
3316 chainlengths.append(0)
3317 chainbases.append(r.start(rev))
3318 chainspans.append(size)
3319 if size == 0:
3320 numempty += 1
3321 numemptytext += 1
3322 else:
3323 numfull += 1
3324 numsnapdepth[0] += 1
3325 addsize(size, fullsize)
3326 addsize(size, snapsizedepth[0])
3327 else:
3328 chainlengths.append(chainlengths[delta] + 1)
3329 baseaddr = chainbases[delta]
3330 revaddr = r.start(rev)
3331 chainbases.append(baseaddr)
3332 chainspans.append((revaddr - baseaddr) + size)
3333 if size == 0:
3334 numempty += 1
3335 numemptydelta += 1
3336 elif r.issnapshot(rev):
3337 addsize(size, semisize)
3338 numsemi += 1
3339 depth = r.snapshotdepth(rev)
3340 numsnapdepth[depth] += 1
3341 addsize(size, snapsizedepth[depth])
3342 else:
3343 addsize(size, deltasize)
3344 if delta == rev - 1:
3345 numprev += 1
3346 if delta == p1:
3347 nump1prev += 1
3348 elif delta == p2:
3349 nump2prev += 1
3350 elif delta == p1:
3351 nump1 += 1
3352 elif delta == p2:
3353 nump2 += 1
3354 elif delta != nullrev:
3355 numother += 1
3356
3357 # Obtain data on the raw chunks in the revlog.
3358 if util.safehasattr(r, b'_getsegmentforrevs'):
3359 segment = r._getsegmentforrevs(rev, rev)[1]
3360 else:
3361 segment = r._revlog._getsegmentforrevs(rev, rev)[1]
3362 if segment:
3363 chunktype = bytes(segment[0:1])
3364 else:
3365 chunktype = b'empty'
3366
3367 if chunktype not in chunktypecounts:
3368 chunktypecounts[chunktype] = 0
3369 chunktypesizes[chunktype] = 0
3370
3371 chunktypecounts[chunktype] += 1
3372 chunktypesizes[chunktype] += size
3373
3374 # Adjust size min value for empty cases
3375 for size in (datasize, fullsize, semisize, deltasize):
3376 if size[0] is None:
3377 size[0] = 0
3378
3379 numdeltas = numrevs - numfull - numempty - numsemi
3380 numoprev = numprev - nump1prev - nump2prev
3381 totalrawsize = datasize[2]
3382 datasize[2] /= numrevs
3383 fulltotal = fullsize[2]
3384 if numfull == 0:
3385 fullsize[2] = 0
3386 else: 3243 else:
3387 fullsize[2] /= numfull 3244 revlog_debug.debug_revlog(ui, r)
3388 semitotal = semisize[2] 3245 return 0
3389 snaptotal = {}
3390 if numsemi > 0:
3391 semisize[2] /= numsemi
3392 for depth in snapsizedepth:
3393 snaptotal[depth] = snapsizedepth[depth][2]
3394 snapsizedepth[depth][2] /= numsnapdepth[depth]
3395
3396 deltatotal = deltasize[2]
3397 if numdeltas > 0:
3398 deltasize[2] /= numdeltas
3399 totalsize = fulltotal + semitotal + deltatotal
3400 avgchainlen = sum(chainlengths) / numrevs
3401 maxchainlen = max(chainlengths)
3402 maxchainspan = max(chainspans)
3403 compratio = 1
3404 if totalsize:
3405 compratio = totalrawsize / totalsize
3406
3407 basedfmtstr = b'%%%dd\n'
3408 basepcfmtstr = b'%%%dd %s(%%5.2f%%%%)\n'
3409
3410 def dfmtstr(max):
3411 return basedfmtstr % len(str(max))
3412
3413 def pcfmtstr(max, padding=0):
3414 return basepcfmtstr % (len(str(max)), b' ' * padding)
3415
3416 def pcfmt(value, total):
3417 if total:
3418 return (value, 100 * float(value) / total)
3419 else:
3420 return value, 100.0
3421
3422 ui.writenoi18n(b'format : %d\n' % format)
3423 ui.writenoi18n(b'flags : %s\n' % b', '.join(flags))
3424
3425 ui.write(b'\n')
3426 fmt = pcfmtstr(totalsize)
3427 fmt2 = dfmtstr(totalsize)
3428 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
3429 ui.writenoi18n(b' merges : ' + fmt % pcfmt(nummerges, numrevs))
3430 ui.writenoi18n(
3431 b' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs)
3432 )
3433 ui.writenoi18n(b'revisions : ' + fmt2 % numrevs)
3434 ui.writenoi18n(b' empty : ' + fmt % pcfmt(numempty, numrevs))
3435 ui.writenoi18n(
3436 b' text : '
3437 + fmt % pcfmt(numemptytext, numemptytext + numemptydelta)
3438 )
3439 ui.writenoi18n(
3440 b' delta : '
3441 + fmt % pcfmt(numemptydelta, numemptytext + numemptydelta)
3442 )
3443 ui.writenoi18n(
3444 b' snapshot : ' + fmt % pcfmt(numfull + numsemi, numrevs)
3445 )
3446 for depth in sorted(numsnapdepth):
3447 ui.write(
3448 (b' lvl-%-3d : ' % depth)
3449 + fmt % pcfmt(numsnapdepth[depth], numrevs)
3450 )
3451 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
3452 ui.writenoi18n(b'revision size : ' + fmt2 % totalsize)
3453 ui.writenoi18n(
3454 b' snapshot : ' + fmt % pcfmt(fulltotal + semitotal, totalsize)
3455 )
3456 for depth in sorted(numsnapdepth):
3457 ui.write(
3458 (b' lvl-%-3d : ' % depth)
3459 + fmt % pcfmt(snaptotal[depth], totalsize)
3460 )
3461 ui.writenoi18n(b' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
3462
3463 def fmtchunktype(chunktype):
3464 if chunktype == b'empty':
3465 return b' %s : ' % chunktype
3466 elif chunktype in pycompat.bytestr(string.ascii_letters):
3467 return b' 0x%s (%s) : ' % (hex(chunktype), chunktype)
3468 else:
3469 return b' 0x%s : ' % hex(chunktype)
3470
3471 ui.write(b'\n')
3472 ui.writenoi18n(b'chunks : ' + fmt2 % numrevs)
3473 for chunktype in sorted(chunktypecounts):
3474 ui.write(fmtchunktype(chunktype))
3475 ui.write(fmt % pcfmt(chunktypecounts[chunktype], numrevs))
3476 ui.writenoi18n(b'chunks size : ' + fmt2 % totalsize)
3477 for chunktype in sorted(chunktypecounts):
3478 ui.write(fmtchunktype(chunktype))
3479 ui.write(fmt % pcfmt(chunktypesizes[chunktype], totalsize))
3480
3481 ui.write(b'\n')
3482 fmt = dfmtstr(max(avgchainlen, maxchainlen, maxchainspan, compratio))
3483 ui.writenoi18n(b'avg chain length : ' + fmt % avgchainlen)
3484 ui.writenoi18n(b'max chain length : ' + fmt % maxchainlen)
3485 ui.writenoi18n(b'max chain reach : ' + fmt % maxchainspan)
3486 ui.writenoi18n(b'compression ratio : ' + fmt % compratio)
3487
3488 if format > 0:
3489 ui.write(b'\n')
3490 ui.writenoi18n(
3491 b'uncompressed data size (min/max/avg) : %d / %d / %d\n'
3492 % tuple(datasize)
3493 )
3494 ui.writenoi18n(
3495 b'full revision size (min/max/avg) : %d / %d / %d\n'
3496 % tuple(fullsize)
3497 )
3498 ui.writenoi18n(
3499 b'inter-snapshot size (min/max/avg) : %d / %d / %d\n'
3500 % tuple(semisize)
3501 )
3502 for depth in sorted(snapsizedepth):
3503 if depth == 0:
3504 continue
3505 ui.writenoi18n(
3506 b' level-%-3d (min/max/avg) : %d / %d / %d\n'
3507 % ((depth,) + tuple(snapsizedepth[depth]))
3508 )
3509 ui.writenoi18n(
3510 b'delta size (min/max/avg) : %d / %d / %d\n'
3511 % tuple(deltasize)
3512 )
3513
3514 if numdeltas > 0:
3515 ui.write(b'\n')
3516 fmt = pcfmtstr(numdeltas)
3517 fmt2 = pcfmtstr(numdeltas, 4)
3518 ui.writenoi18n(
3519 b'deltas against prev : ' + fmt % pcfmt(numprev, numdeltas)
3520 )
3521 if numprev > 0:
3522 ui.writenoi18n(
3523 b' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev)
3524 )
3525 ui.writenoi18n(
3526 b' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev)
3527 )
3528 ui.writenoi18n(
3529 b' other : ' + fmt2 % pcfmt(numoprev, numprev)
3530 )
3531 if gdelta:
3532 ui.writenoi18n(
3533 b'deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas)
3534 )
3535 ui.writenoi18n(
3536 b'deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas)
3537 )
3538 ui.writenoi18n(
3539 b'deltas against other : ' + fmt % pcfmt(numother, numdeltas)
3540 )
3541 3246
3542 3247
3543 @command( 3248 @command(
3544 b'debugrevlogindex', 3249 b'debugrevlogindex',
3545 cmdutil.debugrevlogopts 3250 cmdutil.debugrevlogopts