Permalink
Browse files

Added timings

  • Loading branch information...
1 parent ed3d936 commit c2bc80fcf24d8102d6230aa478380402bd166b41 @mitsuhiko committed Feb 25, 2012
Showing with 120 additions and 0 deletions.
  1. +34 −0 pep-XXXX.rst
  2. +86 −0 timing.py
View
@@ -197,6 +197,40 @@ reintroducing redundant syntax. On the other hand, Python already has
multiple literals for strings with mostly the same behavior (single
quoted, double quoted, single triple quoted, double triple quoted).
+Runtime Overhead of Wrappers
+============================
+
+I did some basic timings on the performance of a ``u()`` wrapper function
+as used by the `six` library. The implementation of ``u()`` is as
+follows::
+
+ if sys.version_info >= (3, 0):
+ def u(value):
+ return value
+ else:
+ def u(value):
+ return unicode(value, 'unicode-escape')
+
+The intention is that ``u'foo'`` can be turned to ``u('foo')`` and that on
+Python 2.x an implicit decoding happens. In this case the wrapper will
+have a decoding overhead for Python 2.x. I did some basic timings to see
+how bad the performance loss would be. The following examples measure the
+execution time over 10000 iterations::
+
+ u'\N{SNOWMAN}barbaz' 1000 loops, best of 3: 295 usec per loop
+ u('\N{SNOWMAN}barbaz') 10 loops, best of 3: 18.5 msec per loop
+ u'foobarbaz_%d' % x 100 loops, best of 3: 8.32 msec per loop
+ u('foobarbaz_%d') % x 10 loops, best of 3: 25.6 msec per loop
+ u'fööbarbaz' 1000 loops, best of 3: 289 usec per loop
+ u('fööbarbaz') 100 loops, best of 3: 15.1 msec per loop
+ u'foobarbaz' 1000 loops, best of 3: 294 usec per loop
+ u('foobarbaz') 100 loops, best of 3: 14.3 msec per loop
+
+The overhead of the wrapper function in Python 3 is the price of a
+function call since the function only has to return the argument
+unchanged.
+
+
References
==========
View
@@ -0,0 +1,86 @@
+# coding: utf-8
+import sys
+from subprocess import Popen
+
+
+ITERATIONS = 10000
+
+
+def u(value):
+ return unicode(value, 'unicode-escape')
+
+
+def bench_format_literal():
+ """u'foobarbaz_%d' % x"""
+ for x in xrange(ITERATIONS):
+ y = u'foobarbaz_%d' % x
+
+
+def bench_format_wrapped():
+ """u('foobarbaz_%d') % x"""
+ for x in xrange(ITERATIONS):
+ y = u('foobarbaz_%d') % x
+
+
+def bench_simple_literal():
+ """u'foobarbaz'"""
+ for x in xrange(ITERATIONS):
+ y = u'foobarbaz'
+
+
+def bench_simple_wrapped():
+ """u('foobarbaz')"""
+ for x in xrange(ITERATIONS):
+ y = u('foobarbaz')
+
+
+def bench_non_ascii_literal():
+ """u'fööbarbaz'"""
+ for x in xrange(ITERATIONS):
+ y = u'fööbarbaz'
+
+
+def bench_non_ascii_wrapped():
+ """u('fööbarbaz')"""
+ for x in xrange(ITERATIONS):
+ y = u('fööbarbaz')
+
+
+def bench_escaped_literal():
+ """u'\N{SNOWMAN}barbaz'"""
+ for x in xrange(ITERATIONS):
+ y = u'\N{SNOWMAN}barbaz'
+
+
+def bench_escaped_wrapped():
+ """u('\N{SNOWMAN}barbaz')"""
+ for x in xrange(ITERATIONS):
+ y = u('\N{SNOWMAN}barbaz')
+
+
+def list_benchmarks():
+ for name in sorted(globals().keys()):
+ if name.startswith('bench_'):
+ yield name[6:]
+
+
+def run_bench(name):
+ text = globals()['bench_' + name].__doc__.strip().decode('utf-8')
+ sys.stdout.write((u'%-32s' % text).encode('utf-8'))
+ sys.stdout.flush()
+ Popen([sys.executable, '-mtimeit', '-s',
+ 'from timing import bench_%s as run' % name,
+ 'run()']).wait()
+
+
+def main():
+ print '=' * 80
+ print 'Running benchmarks'
+ print '-' * 80
+ for bench in list_benchmarks():
+ run_bench(bench)
+ print '-' * 80
+
+
+if __name__ == '__main__':
+ main()

0 comments on commit c2bc80f

Please sign in to comment.