[bip] Bioinformatics Programming Language Shootout, Python performance poopoo'd
Andrew Dalke
dalke at dalkescientific.com
Tue Feb 5 22:24:44 PST 2008
This is my last posting on details. :)
Annoyances:
> Python and Perl are often called script languages and when
> executed, are compiled in an intermediate representation without
> creating an intermediate file (syntax tree in Perl and byte code in
> Python) and then interpreted.
> Java and C# are semi-compiled languages using automatic memory
> management. A Java program is compiled in an intermediate-level
> code or bytecode then it is run by either an interpreter or
> compiler at runtime, in this case, the Java Virtual Machine (JVM).
So the difference between a script language and a semi-compiled
language is that the byte code for the main program isn't saved to an
intermediate file. Not a useful distinction.
> whereas objects in Python are implemented as hash tables.
This is ... wrong? PyObject can have a __dict__ which stores
instance variables. But it can also use __slots__, and doing that
can save quite a bit of memory and performance. See
http://www.dalkescientific.com/writings/diary/archive/2006/03/19/
class_instantiation_performance.html
and
http://www.dalkescientific.com/writings/
useful_and_new_python_modules.pdf
(search for "__slots__")
If someone wants to time the NJ.py file, it'll probably be faster and
take less memory as
class Node(object):
__slots__ = "name right left right_length left_length
divergence".split()
def __init__(self,n=""):
self.name=n
self.right=None
self.left=None
self.right_length=0.0
self.left_length=0.0
self.divergence=0.0
Bruce:
> Looking at the code for C (and pretending to understand Perl), I
> don't think that the same algorithm is being implemented in each
> language!
For examples, the Perl FASTA reader reads line-by-line while the
Python one reads the entire file into memory.
The Perl and Python readers do
$rec->{'name'}=substr($_,1,20);
and
header=line[0:21]
(which should be a line[1:21]).
while the C reader copies the entire line into 'name' and doesn't
restrict itself to the first 20 characters (why is this truncation
there?)
header = (char*)malloc(sizeof(char) * size_line);
strcpy(header, line+1); // +1 to avoid > at the beginning
header=replace(header, ',', ' ');
size_header=size_line-1;
and the C++ code does
s.name=header;
You also pointed out:
> For example, the readFasta.py involves a list of classes that I don't
> think is done in the other languages
perl uses a hash (not a blessed one)
c uses a typedef (in reader.h)
java uses a 'Sequence' class
c# also uses 'Sequence' class
BTW, using a __slots__ on the Python Sequence class gives a 10%
performance speedup.
The paper talks about the memory usage for the alignment code. By
changing
F = [[0.0 for x in xrange(m+1)] for y in xrange(n+1)]
to
import array
F = [array.array("l", [0]*(m+1)) for y in xrange(n+1)]
I take a roughly 10% performance hit (20% if I use the correct "0"
instead of the given "0.0") for about a 40% memory savings
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD
RSIZE VSIZE
26636 Python 99.2% 0:17.73 1 14 190 164M+ 5.20M 166M
+ 209M+
26638 Python 98.6% 0:21.77 1 14 185 87.9M 5.27M
90.0M 129M
(I checked and nothing else uses an int '0' instead of a float '0.0'
like the benchmark uses for Python. That saved about 10% in my
earlier tests.)
Andrew
dalke at dalkescientific.com
More information about the biology-in-python
mailing list