Commit Graph

26 Commits

Author SHA1 Message Date
Pierre-Yves David
447cbfab6f profiling: cope with configwith default value handling changes
Changeset 3d003a7a1a87 change 'configwith' behavior so that the default value is
run through the conversion function. In parallel a new user of 'configwith' got
introduced unaware of this coming behavior change. This broke profiling.

We resolve the situation by having the new conversion function cope with a
default value already using the right type.
2017-06-21 10:46:18 +02:00
Gregory Szorc
768455e422 profiling: allow configuring minimum display threshold for hotpath
statprof.display_hotpath() accepts a "limit" function to choose the
minimum threshold for samples to display. The default is 0.05, which
means you don't need individual items contributing less than 5%.

I had a need to adjust this threshold. We already have a config
option for it. So let's reuse it.

check-config.py doesn't like having multiple defaults for the
ui.configwith() calls. The behavior is obviously correct. I'm
not sure if it is worth teaching check-config.py how to ignore
this. So I've just accepted the new output.
2017-06-15 11:10:51 -07:00
Pierre-Yves David
d38cc2c694 profile: properly propagate exception from the sub-context manager
Context manager has a mechanism to control extension propagation. It is not
used by profiling right now, but making the code correct will help prevent bug
in the future.
2017-06-12 17:24:10 +02:00
Pierre-Yves David
0235063e7c profile: close 'fp' in all cases
There are no way for this to happen today, but better be safe than sorry, no
one know how the code will evolve. We now make sure the file pointer is closed
even is profiler is None.
2017-06-12 17:25:37 +02:00
Pierre-Yves David
cbbef9a3be profile: close 'fp' on error within '__enter__'
Previously, error when initialying the profiler would forgot to explicitly
close the file. Thank goes to Yuya Nishihara for spotting this.
2017-06-12 17:21:41 +02:00
Pierre-Yves David
f122fd3d17 profile: indent part of '__enter__'
We are about to introduce a try except. We start with adding the indent to make
the next patch clearer.
2017-06-12 17:20:48 +02:00
Pierre-Yves David
5cc8016d8b profile: remove now useless indent
We no longer rely on the value of '_output' so we can remove this conditional.
2017-06-12 17:15:43 +02:00
Pierre-Yves David
8e927eb83d profile: use explicit logic to control file closing
We make the decision to close 'fp' more explicit instead of relying on the
implication of other variable. This makes the overall logic more robust.
2017-06-12 17:14:56 +02:00
Pierre-Yves David
cb625340da profiling: move 'fp' closing logic into its own function
We are about to make the logic more robust and reuse it in more place, we start
by isolating what we have.
2017-06-12 17:13:35 +02:00
Pierre-Yves David
2fdfd87513 profile: drop maybeprofile
It seems sufficiently simple to use "profile(enabled=X)" to not justify having
a dedicated context manager just to read the config.

(I do not have a too strong opinion about this).
2017-06-09 12:29:29 +01:00
Pierre-Yves David
4dacb46437 profile: make the contextmanager object available to the callers
This will allow calling methods on the object in the code using the context
manager.
2017-06-09 11:42:45 +01:00
Pierre-Yves David
39ee1a16c0 profile: introduce a knob to control if the context is actually profiling
This is a step toward allowing context where the profiling in enabled
withing the context range.

This also open the way to kill the dedicated "maybeprofile" context manager
and keep only one of 'profile' and 'maybeprofile'.
2017-06-09 11:41:47 +01:00
Pierre-Yves David
669f0c9a69 profile: introduce a "start" method to the profile context
The start method is doing all profiler setup and activation. It is currently
unconditionally called by '__init__' but this will be made more flexible in
later changesets.
2017-06-09 11:39:53 +01:00
Pierre-Yves David
1999d809be profile: upgrade the "profile" context manager to a full class
So far we have been able to use a simple decorator for this. However using the
current context manager makes the scope of the profiling in dispatch
constrainted and the time frame to decide to enable profiling quite limited
(using "maybeprofile")

This is the first step toward the ability to enable the profiling from within
the profiling scope. eg::

  with maybeprofiling(ui) as profiler:
      ...
      bar.foo():
      ...
      if options['profile']:
          profiler.start()
      ...
      fooz()
      ...

My target usecase is adding support for  "--profile" to alias definitions with
effect.  These are to be used with "profiling.output=blackbox" to gather data
about operation that get slow from time to time (eg: pull being minutes instead
of seconds from time to time).

Of course, in such case, the scope of the profiling would be smaller since
profiler would be started after running extensions 'reposetup' (and other
potentially costly logic), but these are not relevant for my target usecase
(multiple second commits, multiple tens of seconds pull).

Currently adding '--profile' to a command through alias requires to re-spin a
Mercurial binary (using "!$HG" in alias), which as a significant performance
impact, especially in context where startup performance is being worked on...

An alternative approach would be to stop using the context manager in dispatch
and move back to a try/finally setup.
2017-06-08 01:38:48 +01:00
Jun Wu
610c5f87a9 profiling: allow loading profiling extension before everything else
459366b580cf makes profiler start early without loading extensions. That
makes it impossible for an extension to add customized profilers.

This patch adds a special case: if a profiler is not found but an extension
with the same name could be loaded, load that extension first, and expect it
to have a "profile" contextmanager method. This allows customized profilers
and extension setup time is still profiled.
2017-05-22 01:17:49 -07:00
Simon Farnsworth
e0b70e4f7f mercurial: switch to util.timer for all interval timings
util.timer is now the best available interval timer, at the expense of not
having a known epoch. Let's use it whenever the epoch is irrelevant.
2017-02-15 13:17:39 -08:00
Bryan O'Sullivan
4b315061e0 profiling: add statprof support for Chrome trace viewer rendering
We synthesize function call begin/end events from snapshots, and
try (configurably) to eliminate "noisy" stack frames.

Example invocation:

hg --config profiling.output=$HOME/Desktop/clone.json \
   --config profiling.statformat=chrome \
   --profile clone https://www.mercurial-scm.org/repo/hg
2017-02-12 22:28:09 -08:00
Pulkit Goyal
3c7388da12 py3: replace pycompat.getenv with encoding.environ.get
pycompat.getenv returns os.getenvb on py3 which is not available on Windows.
This patch replaces them with encoding.environ.get and checks to ensure no
new instances of os.getenv or os.setenv are introduced.
2017-01-15 13:17:05 +05:30
Pulkit Goyal
770a0e2938 py3: replace os.getenv with pycompat.osgetenv
os.getenv deals with unicodes on Python 3, so we have pycompat.osgetenv to
deal with bytes. This patch replaces occurrences on os.getenv with
pycompat.osgetenv
2016-12-19 02:54:49 +05:30
Yuya Nishihara
e23e6c94ff profiling: obtain stderr from ui
This will help Python 3 porting.
2016-10-20 22:07:03 +09:00
Gregory Szorc
d1e86f5ae3 profiling: make statprof the default profiler (BC)
The statprof sampling profiler runs with significantly less overhead.
Its data is therefore more useful. Furthermore, its default output
shows the hotpath by default, which I've found to be way more useful
than the default profiler's function time table.

There is one behavioral regression with this change worth noting:
the statprof profiler currently doesn't profile individual hgweb
requests like lsprof does. This is because the current implementation
of statprof only profiles the thread that started profiling.

The ability for lsprof to profile individual hgweb requests is
relatively new and likely not widely used. Furthermore, I have plans
to modify statprof to support profiling multiple threads. I expect
that change to go through several iterations. I'm submitting this
patch first so there is more time to test statprof. Perfect is the
enemy of good.
2016-11-04 21:44:25 -07:00
Gregory Szorc
c60af834ba profiling: use vendored statprof and upstream enhancements (BC)
Now that the statprof module is vendored and suitable for use, we
switch our statprof profiler to use it. This required some minor
changes because of drift between the official statprof profiler
and the vendored copy.

We also incorporate Facebook's improvements from the "statprofext"
extension at
https://bitbucket.org/facebook/hg-experimental, notably support for
different display formats.

Because statprof output is different, this is marked as BC. Although
most users likely won't notice since most users don't profile.
2016-11-04 20:50:38 -07:00
Gregory Szorc
e6e0818daa profiling: don't error with statprof when profiling has already started
statprof.reset() asserts if profiling has already started. So don't
call if it profiling is already running.
2016-08-14 18:28:43 -07:00
Gregory Szorc
9ac5776ef7 profiling: add a context manager that no-ops if profiling isn't enabled
And refactor dispatch.py to use it. As you can see, the resulting code
is much simpler.

I was tempted to inline _runcommand as part of writing this series.
However, a number of extensions wrap _runcommand. So keeping it around
is necessary (extensions can't easily wrap runcommand because it calls
hooks before and after command execution).
2016-08-14 17:51:12 -07:00
Gregory Szorc
fbd4d1a639 profiling: make profiling functions context managers (API)
This makes profiling more flexible since we can now call multiple
functions when a profiler is active. But the real reason for this
is to enable a future consumer to profile a function that returns
a generator. We can't do this from the profiling function itself
because functions can either be generators or have return values:
they can't be both. So therefore it isn't possible to have a generic
profiling function that can both consume and re-emit a generator
and return a value.
2016-08-14 18:25:22 -07:00
Gregory Szorc
bdb3786ca0 profiling: move profiling code from dispatch.py (API)
Currently, profiling code lives in dispatch.py, which is a low-level
module centered around command dispatch. Furthermore, dispatch.py
imports a lot of other modules, meaning that importing dispatch.py
to get at profiling functionality would often result in a module import
cycle.

Profiling is a generic activity. It shouldn't be limited to command
dispatch. This patch moves profiling code from dispatch.py to the
new profiling.py. The low-level "run a profiler against a function"
functions have been moved verbatim. The code for determining how to
invoke the profiler has been extracted to its own function.

I decided to create a new module rather than stick this code
elsewhere (such as util.py) because util.py is already quite large.
And, I foresee this file growing larger once Facebook's profiling
enhancements get added to it.
2016-08-14 16:30:44 -07:00