This speeds up e.g. parsing of rst pages by factor 2.
Put this at the beginning of e.g. moin.py:
1 import unfold, __builtin__
2 _opti_mods = set()
3 def __import__(name, globals={}, locals={}, fromlist=[]):
4 mod = __builtin__.__import_old__(name, globals, locals, fromlist)
5 if name not in _opti_mods:
6 _opti_mods.add(name)
7 unfold.bind_all(mod, stoplist=('_url_re', '_acl_cache', '_wiki_plugins',
8 '_opti_mods'))
9 return mod
10
11 __builtin__.__import_old__ = __builtin__.__import__
12 __builtin__.__import__ = __import__
13
14 import sys
15 for mod in sys.modules.copy():
16 try:
17 __import__(mod)
18 except ImportError:
19 pass
Put this into a folder in the python-path and call it unfold.py:
1 # stolen from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/277940
2 from types import *
3 import __builtin__
4
5 from opcode import opmap, HAVE_ARGUMENT, EXTENDED_ARG
6 globals().update(opmap)
7
8 def _make_constants(f, builtin_only=False, stoplist=(), verbose=False):
9 try:
10 co = f.func_code
11 except AttributeError:
12 return f # Jython doesn't have a func_code attribute.
13 newcode = map(ord, co.co_code)
14 newconsts = list(co.co_consts)
15 names = co.co_names
16 codelen = len(newcode)
17
18 env = vars(__builtin__).copy()
19 if builtin_only:
20 stoplist = dict.fromkeys(stoplist)
21 stoplist.update(f.func_globals)
22 else:
23 env.update(f.func_globals)
24
25 # First pass converts global lookups into constants
26 i = 0
27 while i < codelen:
28 opcode = newcode[i]
29 if opcode in (EXTENDED_ARG, STORE_GLOBAL):
30 return f # for simplicity, only optimize common cases
31 if opcode == LOAD_GLOBAL:
32 oparg = newcode[i+1] + (newcode[i+2] << 8)
33 name = co.co_names[oparg]
34 if name in env and name not in stoplist:
35 value = env[name]
36 for pos, v in enumerate(newconsts):
37 if v is value:
38 break
39 else:
40 pos = len(newconsts)
41 newconsts.append(value)
42 newcode[i] = LOAD_CONST
43 newcode[i+1] = pos & 0xFF
44 newcode[i+2] = pos >> 8
45 if verbose:
46 print name, '-->', value
47 i += 1
48 if opcode >= HAVE_ARGUMENT:
49 i += 2
50
51 # Second pass folds tuples of constants and constant attribute lookups
52 i = 0
53 while i < codelen:
54
55 newtuple = []
56 while newcode[i] == LOAD_CONST:
57 oparg = newcode[i+1] + (newcode[i+2] << 8)
58 newtuple.append(newconsts[oparg])
59 i += 3
60
61 opcode = newcode[i]
62 if not newtuple:
63 i += 1
64 if opcode >= HAVE_ARGUMENT:
65 i += 2
66 continue
67
68 if opcode == LOAD_ATTR:
69 obj = newtuple[-1]
70 oparg = newcode[i+1] + (newcode[i+2] << 8)
71 name = names[oparg]
72 try:
73 value = getattr(obj, name)
74 except AttributeError:
75 continue
76 deletions = 1
77
78 elif opcode == BUILD_TUPLE:
79 oparg = newcode[i+1] + (newcode[i+2] << 8)
80 if oparg != len(newtuple):
81 continue
82 deletions = len(newtuple)
83 value = tuple(newtuple)
84
85 else:
86 continue
87
88 reljump = deletions * 3
89 newcode[i-reljump] = JUMP_FORWARD
90 newcode[i-reljump+1] = (reljump-3) & 0xFF
91 newcode[i-reljump+2] = (reljump-3) >> 8
92
93 n = len(newconsts)
94 newconsts.append(value)
95 newcode[i] = LOAD_CONST
96 newcode[i+1] = n & 0xFF
97 newcode[i+2] = n >> 8
98 i += 3
99 if verbose:
100 print "new folded constant:", repr(value)
101
102 codestr = ''.join(map(chr, newcode))
103 codeobj = type(co)(co.co_argcount, co.co_nlocals, co.co_stacksize,
104 co.co_flags, codestr, tuple(newconsts), co.co_names,
105 co.co_varnames, co.co_filename, co.co_name,
106 co.co_firstlineno, co.co_lnotab, co.co_freevars,
107 co.co_cellvars)
108 return type(f)(codeobj, f.func_globals, f.func_name, f.func_defaults,
109 f.func_closure)
110
111 _make_constants = _make_constants(_make_constants) # optimize thyself!
112
113 def bind_all(mc, builtin_only=False, stoplist=(), verbose=False):
114 """Recursively apply constant binding to functions in a module or class.
115
116 Use as the last line of the module (after everything is defined, but
117 before test code). In modules that need modifiable globals, set
118 builtin_only to True.
119 """
120 try:
121 d = vars(mc)
122 except TypeError:
123 return
124 for k, v in d.items():
125 if type(v) is FunctionType:
126 newv = _make_constants(v, builtin_only, stoplist, verbose)
127 setattr(mc, k, newv)
128 elif type(v) in (type, ClassType):
129 bind_all(v, builtin_only, stoplist, verbose)
130
131 bind_all = _make_constants(bind_all)