Commit Graph

86 Commits

Author SHA1 Message Date
Gregory Szorc
1e94780ad6 repoview: remove special casing of "requirements"
At the time this code was introduced (7d207cb7e38a), the inline comment
was true. This changed in 2f304c7e2233. The proxy is no longer needed.
2017-06-08 20:28:13 -07:00
Martin von Zweigbergk
e8402531b3 hidden: remove unnecessary guard condition
The "if visible" guard is now pretty pointless, because the function
call it guards will do almost no work anyway when there are no visible
revisions.

We can also stop wrapping "visible" in a set since it just needs to be
an iterable now.
2017-05-30 13:16:32 -07:00
Martin von Zweigbergk
cf924ce951 hidden: subtract pinned revs from hidden earlier
The pinned revs are simply revisions that should not be hidden even if
hideablerevs() says that should. Let's make that clear by simply
setting "hidden = hideablerevs() - pinnedrevs()" early on.
2017-05-30 10:27:20 -07:00
Martin von Zweigbergk
92723c6001 hidden: make _revealancestors() reveal ancestors exclusively
I think this seems more expected. It also prepares for the next
commit.
2017-05-27 23:05:10 -07:00
Martin von Zweigbergk
b246ec6657 hidden: remove _consistencyblockers()
Roughly speaking, we currently do this to reveal hidden ancestors of
visible revisions:

 1. Iterate over all visible non-public revisions and see if they have
    hidden parents

 2. For each revision found in step (1) walk the chain of hidden
    commits and reveal it

We can simplify that by skipping step (1) and doing step (2) from all
visible non-public revisions instead.

This doesn't seem to have much impact on "perfvolatilesets".

Before:
! obsolete
! wall 0.004616 comb 0.000000 user 0.000000 sys 0.000000 (best of 570)
! visible
! wall 0.008235 comb 0.010000 user 0.010000 sys 0.000000 (best of 326)

After:
! obsolete
! wall 0.004727 comb 0.010000 user 0.010000 sys 0.000000 (best of 543)
! visible
! wall 0.008371 comb 0.000000 user 0.000000 sys 0.000000 (best of 324)
2017-05-27 22:55:19 -07:00
Martin von Zweigbergk
6d496b7350 hidden: pass revs to iterate into _consistencyblockers()
Instead of passing the domain into _consistencyblockers() and having
the function calculate the set of revisions to iterate over, let the
caller do it. This is just a minor refactoring to make future changes
simpler.
2017-05-27 22:43:37 -07:00
Martin von Zweigbergk
df6061b050 hidden: remove unnecessary 'domain' parameter from _revealancestors()
The function will stop searching as soon as it runs into a non-hidden
revision, so there is no need to restrict by the domain (of mutable
revisions) as well.

This doesn't seem to have much impact on "perfvolatilesets".

Before:
! obsolete
! wall 0.004903 comb 0.000000 user 0.000000 sys 0.000000 (best of 535)
! visible
! wall 0.008913 comb 0.010000 user 0.010000 sys 0.000000 (best of 300)

After:
! obsolete
! wall 0.004616 comb 0.000000 user 0.000000 sys 0.000000 (best of 570)
! visible
! wall 0.008235 comb 0.010000 user 0.010000 sys 0.000000 (best of 326)
2017-05-27 22:10:20 -07:00
Martin von Zweigbergk
985e29a449 hidden: change _domainancestors() to _revealancestors()
This change makes the function actually reveal the ancestors by
removing them from the hidden set. This prepares for further
simplification.

Note that the function will now only reveal contiguous chains of
hidden revisions, but that's fine because we always pass it an
immediate child of any revision that should be revealed (or the
revision itself).

This doesn't seem to have much impact on "perfvolatilesets".

Before:
! obsolete
! wall 0.004672 comb 0.010000 user 0.010000 sys 0.000000 (best of 590)
! visible
! wall 0.008936 comb 0.010000 user 0.010000 sys 0.000000 (best of 322)

After:
! obsolete
! wall 0.004903 comb 0.000000 user 0.000000 sys 0.000000 (best of 535)
! visible
! wall 0.008913 comb 0.010000 user 0.010000 sys 0.000000 (best of 300)
2017-05-27 21:17:06 -07:00
Martin von Zweigbergk
782a1185dc hidden: rename "revealedrevs" to "pinnedrevs" (API)
E.g. tags and bookmarks can reveal revisions that would otherwise be
hidden. A revision can also be revealed because one if its descendants
is visible. Let's use the term "pinned" for the former case
(bookmarks etc.).
2017-05-27 21:08:51 -07:00
Martin von Zweigbergk
5572c33d0e hidden: drop obsolete comment about cacheability
The cache was recently dropped, so I believe the comment is now obsolete.
2017-05-27 21:02:17 -07:00
Pierre-Yves David
214b54869e hidden: drop outdated comment about "dynamic" performance
This comment is now irrelevant since we have a faster algorithm and no cache.
2017-05-21 15:56:02 +02:00
Pierre-Yves David
dc83ea2d5f hidden: unify the static and dynamic blocker logic
We no longer have cache and they both work the same way. Unifying the logic
simplify the code and reduce the amount of set copies.
2017-05-21 15:47:06 +02:00
Pierre-Yves David
74dcd06928 hidden: drop the hidden cache logic
The improvement in time complexitty and the speed-up in computation is large
enough that the has little use now. Its update time can even gets in the way. So
we drop it.

This will allow us to unify the static/dynamic blockers logic in the next
changeset.
2017-05-21 15:53:08 +02:00
Pierre-Yves David
103db3f051 hidden: simplify the computation of consistency blocker
For a couple of years, we now have precomputed set for all mutable phases. We
can use this set restrict our search and quickly detect non-hideable children of
hideable changesets.  This speeds up the hidden computation. See docstring of
the new function for details.

This new version reuses the '_domainancestors' function to keep the computation
of revealed changeset in O(len(visible))

Below are perfvolatilesets timing from two Mozilla repositories with different
contents. hidden cache is disabled while obtaining them.

1) Mozilla repository with:
 * 400667 changesets
 * 35 hidden changesets (first rev-268334)
 * 288 visible drafts
 * 1 unstable changeset

Before:
! visible
! wall 0.001744 comb 0.000000 user 0.000000 sys 0.000000 (best of 1563)

After:
! visible
! wall 0.000742 comb 0.000000 user 0.000000 sys 0.000000 (best of 3755)


The timing above include the computation of obsolete changeset:
! obsolete
! wall 0.000396 comb 0.000000 user 0.000000 sys 0.000000 (best of 6816)

So adjusted time give 1.3ms before versus 0.3ms after. A 4x speedup.

2) Mozilla repository with:
 * 405645 changesets
 * 4312 hidden changesets (first rev-326004)
 * 264 visible drafts
 * 1 unstable changeset

Before:
! visible
! wall 0.025476 comb 0.030000 user 0.030000 sys 0.000000 (best of 111)


After
! visible
! wall 0.007703 comb 0.010000 user 0.010000 sys 0.000000 (best of 358)


The timing above include the computation of obsolete changeset:
! obsolete
! wall 0.006408 comb 0.010000 user 0.010000 sys 0.000000 (best of 404)

So adjusted time give 19ms before versus 1.3ms after. A 17x speedup.
2017-05-21 16:01:20 +02:00
Pierre-Yves David
9d76dff252 hidden: use _domainancestors to compute revs revealed by dynamic blocker
The complexity of computing the revealed changesets is now 'O(revealed)'.
This massively speeds up the computation on large repository. Moving it to the
millisecond range.

Below are timing from two Mozilla repositories with different contents:

1) mozilla repository with:
 * 400667 changesets
 * 35 hidden changesets (first rev-268334)
 * 288 visible drafts
 * obsolete working copy (dynamicblockers),

Before:
! visible
! wall 0.030247 comb 0.030000 user 0.030000 sys 0.000000 (best of 100)

After:
! visible
! wall 0.000585 comb 0.000000 user 0.000000 sys 0.000000 (best of 4221)

The timing above include the computation of obsolete changeset:
! obsolete
! wall 0.000396 comb 0.000000 user 0.000000 sys 0.000000 (best of 6816)

So adjusted time give 30ms before versus 0.2ms after. A 150x speedup.

2) mozilla repository with:
 * 405645 changesets
 * 4312 hidden changesets (first rev-326004)
 * 264 visible drafts
 * obsolete working copy (dynamicblockers),

Before:
! visible
! wall 0.168658 comb 0.170000 user 0.170000 sys 0.000000 (best of 48)

After
! visible
! wall 0.008612 comb 0.010000 user 0.010000 sys 0.000000 (best of 325)

The timing above include the computation of obsolete changeset:
! obsolete
! wall 0.006408 comb 0.010000 user 0.010000 sys 0.000000 (best of 404)

So adjusted time give 160ms before versus 2ms after. A 75x speedup.
2017-05-21 15:35:21 +02:00
Pierre-Yves David
33754edd6e hidden: add a function returning ancestors of revs within a domain
See documentation for details. This will be used to improve the hidden
computation algorithm. See new changesets for usage.
2017-05-21 15:21:46 +02:00
Pierre-Yves David
b02205e9d6 repoview: rename '_getdynamicblockers' to 'revealedrevs' (API)
Recent mailing list discussion made me realised we could clarify these. We make
the function "public" to encourage extensions to wrap it and we use a more
explicit name that mirror "hideablerevs".
2017-05-20 19:43:58 +02:00
Pierre-Yves David
2795351073 repoview: move '_getdynamicblock' next to 'hideablerevs'
There are the two functions that extensions should use to augment the hidding
logic. It seem better to have them together at the top of the file.
2017-05-20 19:43:29 +02:00
Yuya Nishihara
fad2547154 py3: use portable way to stringify cache key of repoview 2017-03-12 17:20:42 -07:00
Augie Fackler
87aee9cbf5 repoview: specify setattr values as native strings 2017-03-12 00:48:06 -05:00
Pulkit Goyal
970d2f2cc3 repoview: convert attribute names to unicodes on Python 3
In Python 3, the attribute names must be strings i.e. unicodes.
2017-03-08 00:49:15 +05:30
Stanislau Hlebik
2dc1cd49f3 repoview: separate cache hash computation from cache reading
This change will make it easier for extensions to use another cache hash.
2017-02-20 01:54:07 -08:00
Augie Fackler
ad67b99d20 cleanup: replace uses of util.(md5|sha1|sha256|sha512) with hashlib.\1
All versions of Python we support or hope to support make the hash
functions available in the same way under the same name, so we may as
well drop the util forwards.
2016-06-10 00:12:33 -04:00
Matt Mackall
a684f1361f repoview: ignore unwritable hidden cache
The atomictemp.close() file attempts to do a rename, which can fail.
Moving the close inside the exception handler fixes it.

This doesn't fit well with the with: pattern, as it's the finalizer
that's failing.
2016-04-28 16:26:18 -05:00
Pierre-Yves David
4ceff995cf hideablerevs: expand docstring to warn about possible traps
Sean Farley just wasted multiple hours trying to figure out why his code was
crashing. We update the docstring to make the constraint clearer.
2016-04-02 15:56:47 -07:00
FUJIWARA Katsunori
4bd619a29e repoview: discard filtered changelog if index isn't shared with unfiltered
Before this patch, revisions rollbacked at failure of previous
transaction might be visible at subsequent operations unintentionally,
if repoview object is reused even after failure of transaction:
e.g. command server and HTTP server are typical cases.

'repoview' uses the tuple of values below of unfiltered changelog as
"the key" to examine validity of filtered changelog cache.

     - length
     - tip node
     - filtered revisions (as hashed value)
     - '_delayed' field

'repoview' compares between "the key" of unfiltered changelog at
previous caching and now, and reuses filtered changelog cache if no
change is detected.

But this comparison indicates only that there is no change between
unfiltered 'repo.changelog' at last caching and now, but not that
filtered changelog cache is valid for current unfiltered one.

'repoview' uses "shallow copy" of unfiltered changelog to create
filtered changelog cache. In this case, 'index' buffer of unfiltered
changelog is also referred by filtered changelog.

At failure of transaction, unfiltered changelog itself is invalidated
(= un-referred) on the 'repo' side (see b7829fc79508 also). But
'index' of it still contains revisions to be rollbacked at this
failure, and is referred by filtered changelog.

Therefore, even if there is no change between unfiltered
'repo.changelog' at last caching and now, steps below makes rollbacked
revisions visible via filtered changelog unintentionally.

  1. instantiate unfiltered changelog as 'repo.changelog'
     (call it CL1)

  2. make filtered (= shallow copy of) CL1
     (call it FCL1)

  3. cache FCL1 with "the key" of CL1

  4. revisions are appended to 'index', which is shared by CL1 and FCL1

  5. invalidate 'repo.changelog' (= CL1) at failure of transaction

  6. instantiate 'repo.changelog' again at next operation
     (call it CL2)

     CL2 doesn't have revisions added at (4), because it is
     instantiated from '00changelog.i', which isn't changed while
     failed transaction.

  7. compare between "the key" of CL1 and CL2

  8. FCL1 cached at (3) is reused, because comparison at (7) doesn't
     detect change between CL1 at (1) and CL2

  9. revisions rollbacked at (5) are visible via FCL1 unintentionally,
     because FCL1 still refers 'index' changed at (4)

The root cause of this issue is that there is no examination about
validity of filtered changelog cache against current unfiltered one.

This patch discards filtered changelog cache, if its 'index' object
isn't shared with unfiltered one.

BTW, at the time of this patch, redundant truncation of
'00changelog.i' at failure of transaction (see b7829fc79508 for
detail) often prevents "hg serve" from making already rollbacked
revisions visible, because updating timestamps of '00changelog.i' by
truncation makes "hg serve" discard old repoview object with invalid
filtered changelog cache.

This is reason why this issue is overlooked before this patch, even
though test-bundle2-exchange.t has tests in similar situation: failure
of "hg push" via HTTP by pretxnclose hook on server side doesn't
prevent subsequent commands from looking up outgoing revisions
correctly.

But timestamp on the filesystem doesn't have enough resolution for
recent computation power, and it can't be assumed that this avoidance
always works as expected.

Therefore, without this patch, this issue might appear occasionally.
2016-02-24 06:10:46 +09:00
Laurent Charignon
7dcb9bf272 repoview: fix corrupted hiddencache crash Mercurial (issue5042)
Before this patch if the hiddencache existed but was empty, it would crash
mercurial. This patch adds exception handling when reading the hiddencache to
avoid the issue.
When encountering a corrupted cache file we print a devel warning. There would
be no point in issuing a normal warning as the user wouldn't be able to do
anything about the situation.

The warning looks like:

devel-warn: corrupted hidden cache, removing it at: /path/to/repoview.py
2016-01-20 13:43:01 -08:00
Laurent Charignon
71a4d24c5d repoview: add missing newline character in debug prints 2016-01-20 13:40:59 -08:00
Pierre-Yves David
7d5370f77a repoview: bypass changelog method to computed cache key
Getting the data necessary for the cache key using the changelog/revlog method
adds a significant overhead. Given how simple the underlying implementation is
and often this code is ran, it makes sense to violate layering and directly
compute the data.

Testing `hg log` on Mozilla-central, this reduce the time spent on changelog
cache validation by an extra half:

before: 12.2s of 69s
after:   6.1s of 62s

Total speed up from this patch and it's parent is 3x

(With stupid python profiler overhead)

The global speedup without profiler overhead is still there,

Before: 51s
After:  39s (-23%)
2015-12-04 14:22:15 -08:00
Pierre-Yves David
509e099539 repoview: stop recomputing cached key in all case
As explained in the comment, we were computing the key of the cache value every
time because of some obscure MQ test failure. I've dropped that code and ran the
test again that failure is gone. I assume some transaction cleanup got rid of
it.

So we are dropping that code. This provide a significant speedup.

Testing `hg log` on Mozilla-central this reduce the time spent on changelog
cache validation by a third:

before: 19.5s of 80s
after:  12.2s of 69s

(With stupid python profiler overhead)
2015-12-04 14:04:24 -08:00
Gregory Szorc
2e850c30e2 repoview: use absolute_import 2015-08-08 19:58:05 -07:00
Augie Fackler
a5b17bd9d1 cleanup: use __builtins__.any instead of util.any
any() is available in all Python versions we support now.
2015-05-16 14:30:07 -04:00
Matt Mackall
f24fd8ebbe repoview: use try/except/finally 2015-05-15 09:57:44 -05:00
Pierre-Yves David
b838547883 repoview: avoid processing the same rev twice in _getstatichidden
If a rev had multiple children, it would be added to the heap multiple times. We
now ensure it is added only once.
2015-04-03 14:41:18 -07:00
Pierre-Yves David
eca03d6be8 repoview: skip public parent earlier in _getstatichidden
Public changeset have nothing to offer regarding hidden changeset. Lets not add
them to the heap at all.
2015-04-03 14:37:52 -07:00
Pierre-Yves David
93633df1d0 repoview: directly skip public head in _getstatichidden
Public heads have nothing to offer regarding hidden stuff, let's skip them.
2015-04-03 14:36:05 -07:00
Pierre-Yves David
201089f587 repoview: simplify process in _getstatichidden
Since all children are processed before their parents, we can apply the following algorithm:

For each rev (descending order):

* If I'm still hidden, no children will block me,
* If I'm not hidden, I must remove my parent from the hidden set,

This allows us to dynamically change the set of 'hidden' revisions, dropping the
need for the 'actuallyhidden' dictionary and the 'blocked' boolean in the queue.

As before, we start iterating from all heads and stop at the first public
changesets. This ensures the hidden computation is 'O(not public())' instead of
'O(len(min(not public()):))'.
2015-04-03 14:35:53 -07:00
Pierre-Yves David
aa3bc6a909 repoview: use a heap in _getstatichidden
Since we want to process all non-public changesets from top to bottom, a heap
seems more appropriate. This will ensure any revision is processed after all
its children, opening the way to code simplification.
2015-04-03 14:16:50 -07:00
Pierre-Yves David
cdd34568db repoview: update documentation of _getstatichidden
In def1a225fdc4, the function name, role and return was changed. But the
documentation was not. This fixes it.
2015-04-03 13:58:12 -07:00
Durham Goode
e33ea26dd5 repoview: improve compute staticblockers perf
Previously we would compute the repoview's static blockers by finding all the
children of hidden commits that were not hidden.  This was O(number of commits
since first hidden change) since 'children' requires walking every commit from
tip until the first hidden change.

The new algorithm walks all heads down until it sees a public commit. This makes
the computation O(number of draft) commits, which is much faster in large
repositories with a large number of commits and a low number of drafts.

On a large repo with 1000+ obsolete markers and the earliest draft commit around
tip~200000, this improves computehidden perf by 200x (2s to 0.01s).
2015-04-01 12:50:10 -07:00
Matt Mackall
3f5d6ecec7 repoview: invalidate cached changelog if _delayed changes (issue4549)
Starting with b1e85ff3a7fc, when a clone reached the checkout stage,
the cached changelog in the filtered view was still seeing the
_delayed flag, even though the changelog had already been finalized.
2015-03-01 23:20:02 -06:00
Pierre-Yves David
e0712f847d repoview: backout 542a704cdc0f
Monkey patching repoview does not really work and making it really work will
be really hard. So we better have it broken without complexity than broken with
extra complexity.
2014-12-17 12:21:07 -08:00
Matt Harbison
f2d468fb0a repoview: allow methods on the proxy class to be replaced
It doesn't seem to be a common idiom for repo instances, but the status() method
is replaced in largefiles' purge() override.  Since __setattr__ is implemented
in repoview to setattr() on the unfiltered repo, the replacement method wouldn't
get called unless it was invoked with the unfiltered repo, because the filtered
repo remains unchanged.

Since this doesn't seem to be commonly used, I didn't bother to filter out
methods that perhaps shouldn't be replaced, such as changelog().
2014-12-07 10:52:56 -05:00
Pierre-Yves David
8f926bef9a repoview: extract actual hidden cache writing in its own function
This will allow the generation of this cache within the transaction. Relying on
the transaction will reduce the chance of reader seeing bad cache.
2014-11-13 11:11:17 +00:00
David Soria Parra
fdc87e21e5 repoview: remove hiddencache verification
We have been running hiddencache verification since 3.1.1 and so
far not received a bug report concerning it. Therefore we remove
the verification code and make the hiddencache authoritive. That
way we get the intended speedup.
2014-10-06 07:29:40 -07:00
Augie Fackler
f41d193435 merge with stable 2014-09-04 09:59:23 -04:00
Mike Hommey
edf6a59652 repoview: fix typo in repoview.changelog
Incidentally, this avoids the changelog cache being invalidated each time
it's accessed on a repoview.

On a filtering experiment on a repository the size of mozilla-central,
this makes a significant difference:

Before, running hg log -l 10 --time with about 8k changesets filtered out:
time: real 1.490 secs (user 1.450+0.000 sys 0.040+0.000)

After:
time: real 0.540 secs (user 0.530+0.000 sys 0.010+0.000)
2014-08-31 19:43:03 +09:00
Matt Mackall
9bc396577d repoview: fix 0L with pack/unpack for 2.4 2014-08-26 13:11:53 +02:00
Matt Mackall
17ab77f157 repoview: filter tags to non-existent nodes from blockers (issue4328) 2014-08-12 02:40:42 -05:00
Augie Fackler
cceb152b73 repoview: use util.sha1() instead of hashlib.sha1()
6f2e3119e8a1 accidentally broke Python 2.4 compatibility, this fixes it.
2014-08-20 13:21:41 -04:00