Tim made me do it! http://groups.google.com/group/comp.lang.python/msg/9075a3bc59c334c9
For whatever reason, I was just curious how his code could be sped up. I kept seeing this append method being called and I thought, "there's an opcode for that." What happens if you replace var.append() with the LIST_APPEND opcode. # standard opcodes $ ./python ./Lib/timeit.py -n 1000 -s 'import foo' 'foo.foo1(10000)' 1000 loops, best of 3: 3.66 msec per loop # hacked version $ ./python ./Lib/timeit.py -n 1000 -s 'import foo' 'foo.foo2(10000)' 1000 loops, best of 3: 1.74 msec per loop The patch and foo.py are attached. This code doesn't really work in general. It assumes that any append function call is a list method, which is obviously invalid. But if a variable is known to be a list (ie, local and assigned as list (BUILD_LIST) or a list comprehension), could we do something like this as a peephole optimization? I'm not familiar enough with some dynamic tricks to know if it there are conditions that could break this. Probably useless, but it was interesting to me at the time. n
Index: Python/compile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v retrieving revision 2.352 diff -w -u -r2.352 compile.c --- Python/compile.c 3 Aug 2005 18:33:05 -0000 2.352 +++ Python/compile.c 14 Sep 2005 05:33:29 -0000 @@ -754,6 +754,37 @@ } break; + /* Replace LOAD_ATTR "append" ... CALL_FUNCTION 1 with + LIST_APPEND */ + case LOAD_ATTR: + /* for testing: only do optimization if name is speed */ + name = PyString_AsString(PyTuple_GET_ITEM(names, 0)); + if (name == NULL || strcmp(name, "speed") != 0) + continue; + /* end testing bit */ + + j = GETARG(codestr, i); + name = PyString_AsString(PyTuple_GET_ITEM(names, j)); + if (name == NULL || strcmp(name, "append") != 0) + continue; + if (i + 9 > codelen) + continue; + if (codestr[i+6] != CALL_FUNCTION && + codestr[i+9] != POP_TOP) + continue; + + codestr[i+0] = NOP; + codestr[i+1] = NOP; + codestr[i+2] = NOP; + /* 0-2= LOAD_XXX */ + /* replace CALL_FUNCTION 1 with LIST_APPEND */ + codestr[i+6] = LIST_APPEND; + codestr[i+7] = NOP; + codestr[i+8] = NOP; + /* get rid of POP_TOP */ + codestr[i+9] = NOP; + break; + /* Skip over LOAD_CONST trueconst JUMP_IF_FALSE xx POP_TOP */ case LOAD_CONST: cumlc = lastlc + 1;
def foo1(n): d = [] for x in range(n): d.append(5) def foo2(n): speed = [] for x in range(n): speed.append(5) if __name__ == '__main__': import dis dis.dis(foo1) print dis.dis(foo2)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com