comparison mercurial/commands.py @ 27263:4efb36ecaaec

commands: add debugdeltachain command We have debug commands for displaying overall revlog statistics (debugrevlog) and for dumping a revlog index (debugindex). As part of investigating various aspects of revlog behavior and performance, I found it important to have an understanding of how revlog delta chains behave in practice. This patch implements a "debugdeltachain" command. For each revision in a revlog, it dumps information about the delta chain. Which delta chain it is part of, length of the delta chain, distance since base revision, info about base revision, size of the delta chain, etc. The generic formatting facility is used, which means we can templatize output and get machine readable output like JSON. This command has already uncovered some weird history in mozilla-central I didn't know about. So I think it's valuable.
author Gregory Szorc <gregory.szorc@gmail.com>
date Sat, 05 Dec 2015 23:37:46 -0800
parents 45124eaab4e2
children e07003a94ef3
comparison
equal deleted inserted replaced
27262:3d0feb2f978b 27263:4efb36ecaaec
2499 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i)) 2499 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2500 if pp[1] != nullid: 2500 if pp[1] != nullid:
2501 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i)) 2501 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2502 ui.write("}\n") 2502 ui.write("}\n")
2503 2503
2504 @command('debugdeltachain',
2505 debugrevlogopts + formatteropts,
2506 _('-c|-m|FILE'),
2507 optionalrepo=True)
2508 def debugdeltachain(ui, repo, file_=None, **opts):
2509 """dump information about delta chains in a revlog
2510
2511 Output can be templatized. Available template keywords are:
2512
2513 rev revision number
2514 chainid delta chain identifier (numbered by unique base)
2515 chainlen delta chain length to this revision
2516 prevrev previous revision in delta chain
2517 deltatype role of delta / how it was computed
2518 compsize compressed size of revision
2519 uncompsize uncompressed size of revision
2520 chainsize total size of compressed revisions in chain
2521 chainratio total chain size divided by uncompressed revision size
2522 (new delta chains typically start at ratio 2.00)
2523 lindist linear distance from base revision in delta chain to end
2524 of this revision
2525 extradist total size of revisions not part of this delta chain from
2526 base of delta chain to end of this revision; a measurement
2527 of how much extra data we need to read/seek across to read
2528 the delta chain for this revision
2529 extraratio extradist divided by chainsize; another representation of
2530 how much unrelated data is needed to load this delta chain
2531 """
2532 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2533 index = r.index
2534 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2535
2536 def revinfo(rev):
2537 iterrev = rev
2538 e = index[iterrev]
2539 chain = []
2540 compsize = e[1]
2541 uncompsize = e[2]
2542 chainsize = 0
2543
2544 if generaldelta:
2545 if e[3] == e[5]:
2546 deltatype = 'p1'
2547 elif e[3] == e[6]:
2548 deltatype = 'p2'
2549 elif e[3] == rev - 1:
2550 deltatype = 'prev'
2551 elif e[3] == rev:
2552 deltatype = 'base'
2553 else:
2554 deltatype = 'other'
2555 else:
2556 if e[3] == rev:
2557 deltatype = 'base'
2558 else:
2559 deltatype = 'prev'
2560
2561 while iterrev != e[3]:
2562 chain.append(iterrev)
2563 chainsize += e[1]
2564 if generaldelta:
2565 iterrev = e[3]
2566 else:
2567 iterrev -= 1
2568 e = index[iterrev]
2569 else:
2570 chainsize += e[1]
2571 chain.append(iterrev)
2572
2573 chain.reverse()
2574 return compsize, uncompsize, deltatype, chain, chainsize
2575
2576 fm = ui.formatter('debugdeltachain', opts)
2577
2578 fm.plain(' rev chain# chainlen prev delta '
2579 'size rawsize chainsize ratio lindist extradist '
2580 'extraratio\n')
2581
2582 chainbases = {}
2583 for rev in r:
2584 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2585 chainbase = chain[0]
2586 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2587 basestart = r.start(chainbase)
2588 revstart = r.start(rev)
2589 lineardist = revstart + comp - basestart
2590 extradist = lineardist - chainsize
2591 try:
2592 prevrev = chain[-2]
2593 except IndexError:
2594 prevrev = -1
2595
2596 chainratio = float(chainsize) / float(uncomp)
2597 extraratio = float(extradist) / float(chainsize)
2598
2599 fm.startitem()
2600 fm.write('rev chainid chainlen prevrev deltatype compsize '
2601 'uncompsize chainsize chainratio lindist extradist '
2602 'extraratio',
2603 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2604 rev, chainid, len(chain), prevrev, deltatype, comp,
2605 uncomp, chainsize, chainratio, lineardist, extradist,
2606 extraratio,
2607 rev=rev, chainid=chainid, chainlen=len(chain),
2608 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2609 uncompsize=uncomp, chainsize=chainsize,
2610 chainratio=chainratio, lindist=lineardist,
2611 extradist=extradist, extraratio=extraratio)
2612
2613 fm.end()
2614
2504 @command('debuginstall', [], '', norepo=True) 2615 @command('debuginstall', [], '', norepo=True)
2505 def debuginstall(ui): 2616 def debuginstall(ui):
2506 '''test Mercurial installation 2617 '''test Mercurial installation
2507 2618
2508 Returns 0 on success. 2619 Returns 0 on success.