Mercurial > hg
comparison tests/test-rename-merge2.t @ 42222:57203e0210f8
copies: calculate mergecopies() based on pathcopies()
When copies are stored in changesets, we need a changeset-centric
version of mergecopies() just like we have a changeset-centric version
of pathcopies(). I think the natural way of thinking about
mergecopies() is in terms of pathcopies() from the base to each of the
commits. So if we can rewrite mergecopies() based on two such
pathcopies() calls, we'll get the changeset-centric version for
free. That's what this patch does.
A nice bonus is that it ends up being a lot simpler. mergecopies() has
accumulated a lot of technical debt over time. One good example is the
code for dealing with grafts (the "partial/incomplete/dirty"
stuff). Since pathcopies() already deals with backwards renames and
ping-pong renames, we get that for free.
I've run tests with hard-coded debug logging for "fullcopy" and while
I haven't looked at every difference it produces, all the ones I have
looked at seemed reasonable to me. I'm a little surprised that no more
tests fail when run with '--extra-config-opt
experimental.copies.read-from=compatibility' compared to before this
patch. This patch also fixes the broken cases in test-annotate.t and
test-fastannotate.t. It also enables the part of test-copies.t that
was previously disabled exactly because mergecopies() needed to get a
changeset-centric version.
One drawback of the rewritten code is that we may now make
remotefilelog prefetch more files. We used to prefetch files that were
unique to either side of the merge compared to the other. We now
prefetch files that are unique to either side of the merge compared to
the base. This means that if you added the same file to each side, we
would not prefetch it before, but we would now. Such cases are
probably quite rare, but one likely scenario where they happen is when
moving from a commit to its successor (or the other way around). The
user will probably already have the files in the cache in such cases,
so it's probably not a big deal.
Some timings for calculating mergecopies between two revisions
(revisions shown on each line, all using the common ancestor as base):
In the hg repo:
4.8 4.9: 0.21s -> 0.21s
4.0 4.8: 0.35s -> 0.63s
In and old copy of the mozilla-unified repo:
FIREFOX_BETA_60_BASE^ FIREFOX_BETA_60_BASE: 0.82s -> 0.82s
FIREFOX_NIGHTLY_59_END FIREFOX_BETA_60_BASE: 2.5s -> 2.6s
FIREFOX_BETA_59_END FIREFOX_BETA_60_BASE: 3.9s -> 4.1s
FIREFOX_AURORA_50_BASE FIREFOX_BETA_60_BASE: 31s -> 33s
So it's measurably slower in most cases. The most significant
difference is in the hg repo between revisions 4.0 and 4.8. In that
case it seems to come from the fact that pathcopies() uses
fctx.isintroducedafter() (in _tracefile), while the old mergecopies()
used fctx.linkrev() (in _checkcopies()). That results in a single call
to filectx._adjustlinkrev(), which is responsible for the entire
difference in time (in my repo). So we pay a performance penalty but
we get more correct code (see change in
test-mv-cp-st-diff.t). Deleting the "== f.filenode()" in _tracefile()
recovers the lost performance in the hg repo.
There were are few other optimizations in _checkcopies() that I could
not measure any impact from. One was from the "seen" set. Another was
from a "continue" when the file was not in the destination manifest
(corresponding to "am" in _tracefile).
Also note that merge copies are not calculated when updating with a
clean working copy, which is probably the most common case. I
therefore think the much simpler code is worth the slowdown.
Differential Revision: https://phab.mercurial-scm.org/D6255
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Thu, 11 Apr 2019 23:22:54 -0700 |
parents | a68036b849b0 |
children | 4764e8436b2a |
comparison
equal
deleted
inserted
replaced
42221:c83c08cf02b7 | 42222:57203e0210f8 |
---|---|
431 $ tm "nc a b" "up b " " " "12 merge b no ancestor" | 431 $ tm "nc a b" "up b " " " "12 merge b no ancestor" |
432 created new head | 432 created new head |
433 -------------- | 433 -------------- |
434 test L:nc a b R:up b W: - 12 merge b no ancestor | 434 test L:nc a b R:up b W: - 12 merge b no ancestor |
435 -------------- | 435 -------------- |
436 all copies found (* = to merge, ! = divergent, % = renamed and deleted): | |
437 src: 'a' -> dst: 'b' | |
438 checking for directory renames | |
436 resolving manifests | 439 resolving manifests |
437 branchmerge: True, force: False, partial: False | 440 branchmerge: True, force: False, partial: False |
438 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7 | 441 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7 |
439 preserving b for resolve of b | 442 preserving b for resolve of b |
440 preserving rev for resolve of rev | 443 preserving rev for resolve of rev |
467 $ tm "up b " "nm a b" " " "13 merge b no ancestor" | 470 $ tm "up b " "nm a b" " " "13 merge b no ancestor" |
468 created new head | 471 created new head |
469 -------------- | 472 -------------- |
470 test L:up b R:nm a b W: - 13 merge b no ancestor | 473 test L:up b R:nm a b W: - 13 merge b no ancestor |
471 -------------- | 474 -------------- |
475 all copies found (* = to merge, ! = divergent, % = renamed and deleted): | |
476 src: 'a' -> dst: 'b' | |
477 checking for directory renames | |
472 resolving manifests | 478 resolving manifests |
473 branchmerge: True, force: False, partial: False | 479 branchmerge: True, force: False, partial: False |
474 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a | 480 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a |
475 preserving b for resolve of b | 481 preserving b for resolve of b |
476 preserving rev for resolve of rev | 482 preserving rev for resolve of rev |
504 $ tm "nc a b" "up a b" " " "14 merge b no ancestor" | 510 $ tm "nc a b" "up a b" " " "14 merge b no ancestor" |
505 created new head | 511 created new head |
506 -------------- | 512 -------------- |
507 test L:nc a b R:up a b W: - 14 merge b no ancestor | 513 test L:nc a b R:up a b W: - 14 merge b no ancestor |
508 -------------- | 514 -------------- |
515 all copies found (* = to merge, ! = divergent, % = renamed and deleted): | |
516 src: 'a' -> dst: 'b' | |
517 checking for directory renames | |
509 resolving manifests | 518 resolving manifests |
510 branchmerge: True, force: False, partial: False | 519 branchmerge: True, force: False, partial: False |
511 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a | 520 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a |
512 preserving b for resolve of b | 521 preserving b for resolve of b |
513 preserving rev for resolve of rev | 522 preserving rev for resolve of rev |
541 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a" | 550 $ tm "up b " "nm a b" " " "15 merge b no ancestor, remove a" |
542 created new head | 551 created new head |
543 -------------- | 552 -------------- |
544 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a | 553 test L:up b R:nm a b W: - 15 merge b no ancestor, remove a |
545 -------------- | 554 -------------- |
555 all copies found (* = to merge, ! = divergent, % = renamed and deleted): | |
556 src: 'a' -> dst: 'b' | |
557 checking for directory renames | |
546 resolving manifests | 558 resolving manifests |
547 branchmerge: True, force: False, partial: False | 559 branchmerge: True, force: False, partial: False |
548 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a | 560 ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a |
549 preserving b for resolve of b | 561 preserving b for resolve of b |
550 preserving rev for resolve of rev | 562 preserving rev for resolve of rev |
578 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor" | 590 $ tm "nc a b" "up a b" " " "16 get a, merge b no ancestor" |
579 created new head | 591 created new head |
580 -------------- | 592 -------------- |
581 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor | 593 test L:nc a b R:up a b W: - 16 get a, merge b no ancestor |
582 -------------- | 594 -------------- |
595 all copies found (* = to merge, ! = divergent, % = renamed and deleted): | |
596 src: 'a' -> dst: 'b' | |
597 checking for directory renames | |
583 resolving manifests | 598 resolving manifests |
584 branchmerge: True, force: False, partial: False | 599 branchmerge: True, force: False, partial: False |
585 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a | 600 ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a |
586 preserving b for resolve of b | 601 preserving b for resolve of b |
587 preserving rev for resolve of rev | 602 preserving rev for resolve of rev |
615 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor" | 630 $ tm "up a b" "nc a b" " " "17 keep a, merge b no ancestor" |
616 created new head | 631 created new head |
617 -------------- | 632 -------------- |
618 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor | 633 test L:up a b R:nc a b W: - 17 keep a, merge b no ancestor |
619 -------------- | 634 -------------- |
635 all copies found (* = to merge, ! = divergent, % = renamed and deleted): | |
636 src: 'a' -> dst: 'b' | |
637 checking for directory renames | |
620 resolving manifests | 638 resolving manifests |
621 branchmerge: True, force: False, partial: False | 639 branchmerge: True, force: False, partial: False |
622 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24 | 640 ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24 |
623 preserving b for resolve of b | 641 preserving b for resolve of b |
624 preserving rev for resolve of rev | 642 preserving rev for resolve of rev |
651 $ tm "nm a b" "up a b" " " "18 merge b no ancestor" | 669 $ tm "nm a b" "up a b" " " "18 merge b no ancestor" |
652 created new head | 670 created new head |
653 -------------- | 671 -------------- |
654 test L:nm a b R:up a b W: - 18 merge b no ancestor | 672 test L:nm a b R:up a b W: - 18 merge b no ancestor |
655 -------------- | 673 -------------- |
674 all copies found (* = to merge, ! = divergent, % = renamed and deleted): | |
675 src: 'a' -> dst: 'b' | |
676 checking for directory renames | |
656 resolving manifests | 677 resolving manifests |
657 branchmerge: True, force: False, partial: False | 678 branchmerge: True, force: False, partial: False |
658 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a | 679 ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a |
659 preserving b for resolve of b | 680 preserving b for resolve of b |
660 preserving rev for resolve of rev | 681 preserving rev for resolve of rev |
693 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a" | 714 $ tm "up a b" "nm a b" " " "19 merge b no ancestor, prompt remove a" |
694 created new head | 715 created new head |
695 -------------- | 716 -------------- |
696 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a | 717 test L:up a b R:nm a b W: - 19 merge b no ancestor, prompt remove a |
697 -------------- | 718 -------------- |
719 all copies found (* = to merge, ! = divergent, % = renamed and deleted): | |
720 src: 'a' -> dst: 'b' | |
721 checking for directory renames | |
698 resolving manifests | 722 resolving manifests |
699 branchmerge: True, force: False, partial: False | 723 branchmerge: True, force: False, partial: False |
700 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a | 724 ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a |
701 preserving a for resolve of a | 725 preserving a for resolve of a |
702 preserving b for resolve of b | 726 preserving b for resolve of b |