Mercurial > hg
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. |