Rev 2726: Add -Devil flag to highlight the use of problematic API calls. in http://people.ubuntu.com/~robertc/baz2.0/devil
Robert Collins
robertc at robertcollins.net
Mon Aug 20 04:44:33 BST 2007
At http://people.ubuntu.com/~robertc/baz2.0/devil
------------------------------------------------------------
revno: 2726
revision-id: robertc at robertcollins.net-20070820034340-am05707e05l1nth5
parent: pqm at pqm.ubuntu.com-20070817192843-0jaoxooskia72irk
committer: Robert Collins <robertc at robertcollins.net>
branch nick: devil
timestamp: Mon 2007-08-20 13:43:40 +1000
message:
Add -Devil flag to highlight the use of problematic API calls.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/debug.py debug.py-20061102062349-vdhrw9qdpck8cl35-1
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/test_trace.py testtrace.py-20051110225523-a21117fc7a07eeff
bzrlib/trace.py trace.py-20050309040759-c8ed824bdcd4748a
doc/developers/performance-contributing.txt performancecontribut-20070621063612-ac4zhhagjzkr21qp-1
=== modified file 'NEWS'
--- a/NEWS 2007-08-17 17:56:35 +0000
+++ b/NEWS 2007-08-20 03:43:40 +0000
@@ -35,11 +35,15 @@
* ``Branch.append_revision`` is removed altogether; please use
``Branch.set_last_revision_info`` instead. (Martin Pool)
- aPI CHANGES:
-
* ``Transport.should_cache`` has been removed. It was not called in the
previous release. (Martin Pool)
+ INTERNALS:
+
+ * New trace function ``mutter_callsite`` will print out a subset of the
+ stack to the log, which can be useful for gathering debug details.
+ (Robert Collins)
+
bzr 0.90rc1 2007-08-14
BUGFIXES:
=== modified file 'bzrlib/debug.py'
--- a/bzrlib/debug.py 2007-07-09 04:31:30 +0000
+++ b/bzrlib/debug.py 2007-08-20 03:43:40 +0000
@@ -21,7 +21,8 @@
These are set with eg ``-Dlock`` on the bzr command line.
Options include:
-
+
+ * evil - capture call sites that do expensive or badly-scaling operations.
* error - show stack traces for all top level exceptions
* hooks
* hpss - trace smart protocol requests and responses
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2007-08-17 05:08:52 +0000
+++ b/bzrlib/tests/__init__.py 2007-08-20 03:43:40 +0000
@@ -1202,9 +1202,14 @@
mutter(*args)
def _get_log(self, keep_log_file=False):
- """Return as a string the log for this test. If the file is still
- on disk and keep_log_file=False, delete the log file and store the
- content in self._log_contents."""
+ """Get the log from bzrlib.trace calls from this test.
+
+ :param keep_log_file: When True, if the log is still a file on disk
+ leave it as a file on disk. When False, if the log is still a file
+ on disk, the log file is deleted and the log preserved as
+ self._log_contents.
+ :return: A string containing the log.
+ """
# flush the log file, to get all content
import bzrlib.trace
bzrlib.trace._trace_file.flush()
=== modified file 'bzrlib/tests/test_trace.py'
--- a/bzrlib/tests/test_trace.py 2006-11-17 05:53:17 +0000
+++ b/bzrlib/tests/test_trace.py 2007-08-20 03:43:40 +0000
@@ -27,7 +27,7 @@
errors,
)
from bzrlib.tests import TestCaseInTempDir, TestCase
-from bzrlib.trace import mutter, report_exception
+from bzrlib.trace import mutter, mutter_callsite, report_exception
def _format_exception():
@@ -113,6 +113,30 @@
else:
self.fail("expected error not raised")
+ def test_mutter_callsite_1(self):
+ """mutter_callsite can capture 1 level of stack frame."""
+ mutter_callsite(1, "foo %s", "a string")
+ log = self._get_log(keep_log_file=True)
+ # begin with the message
+ self.assertStartsWith(log, 'foo a string\nCalled from:\n')
+ # should show two frame: this frame and the one above
+ self.assertContainsRe(log,
+ 'test_trace\.py", line \d+, in test_mutter_callsite_1\n')
+ # this frame should be the final one
+ self.assertEndsWith(log, ' "a string")\n')
+
+ def test_mutter_callsite_2(self):
+ """mutter_callsite can capture 2 levels of stack frame."""
+ mutter_callsite(2, "foo %s", "a string")
+ log = self._get_log(keep_log_file=True)
+ # begin with the message
+ self.assertStartsWith(log, 'foo a string\nCalled from:\n')
+ # should show two frame: this frame and the one above
+ self.assertContainsRe(log,
+ 'test_trace.py", line \d+, in test_mutter_callsite_2\n')
+ # this frame should be the final one
+ self.assertEndsWith(log, ' "a string")\n')
+
def test_mutter_never_fails(self):
# Even if the decode/encode stage fails, mutter should not
# raise an exception
@@ -123,3 +147,4 @@
self.assertContainsRe(log, 'Writing a greek mu')
self.assertContainsRe(log, "But fails in an ascii string")
self.assertContainsRe(log, u"ascii argument: \xb5")
+
=== modified file 'bzrlib/trace.py'
--- a/bzrlib/trace.py 2007-08-15 04:33:34 +0000
+++ b/bzrlib/trace.py 2007-08-20 03:43:40 +0000
@@ -56,8 +56,10 @@
from bzrlib.lazy_import import lazy_import
lazy_import(globals(), """
+from cStringIO import StringIO
import errno
import logging
+import traceback
""")
import bzrlib
@@ -122,6 +124,21 @@
#_trace_file.flush()
+def mutter_callsite(stacklevel, fmt, *args):
+ """Perform a mutter of fmt and args, logging the call trace.
+
+ :param stacklevel: The number of frames to show. None will show all
+ frames.
+ :param fmt: The format string to pass to mutter.
+ :param args: A list of substitution variables.
+ """
+ outf = StringIO()
+ traceback.print_stack(limit=stacklevel + 1, file=outf)
+ formatted_lines = outf.getvalue().splitlines()
+ formatted_stack = '\n'.join(formatted_lines[:-2])
+ mutter(fmt + "\nCalled from:\n%s", *(args + (formatted_stack,)))
+
+
def _rollover_trace_maybe(trace_fname):
import stat
try:
=== modified file 'doc/developers/performance-contributing.txt'
--- a/doc/developers/performance-contributing.txt 2007-06-21 06:41:07 +0000
+++ b/doc/developers/performance-contributing.txt 2007-08-20 03:43:40 +0000
@@ -10,6 +10,13 @@
changes. In general, pick a BLUE node from performance.png which has nothing
pointing at it that is also BLUE, and start working on that.
+Adhoc performance work can also be done. One useful tool is the 'evil' debug
+flag. For instance running ``bzr -Devil commit -m 'test'`` will log a backtrace
+to the bzr log file for every method call which triggers a slow or non-scalable
+part of the bzr library. So checking that a given command with ``-Devil`` has
+no backtraces logged to the log file is a good way to find problem function
+calls that might be nested deep in the code base.
+
Status
------
More information about the bazaar-commits
mailing list