4 ms·
I'm no python developer but this: def main(): for i in xrange(10000000): "%d %d" % (i, i) main() Does't seem to be copying the result anywhere.
by xd 15y ago
I'm no python developer but this:
def main():
for i in xrange(10000000):
"%d %d" % (i, i)
main()
Does't seem to be copying the result anywhere. Where as the C example is copying the result to memory .. which would explain why it is slower.
- kingkilr 15y agoYes, it does seem a little strange that the result is unused, however changing that to be ``x = <stuff>`` would have no effect on the runtime, the compiler isn't quite good enough yet to realize the result is unused.
- xd 15y agoOh and does anyone else think the malloc example in comparison to actual garbage collection is incredibly unfair?
- scott_s 15y ago"Fairness" is not really relevant. As long as they're comparing typical C idioms to typical Python idioms, it's valid.
- xd 15y agoSo why not simply do: #include <stdio.h> #include <stdlib.h> int main() { int i = 0; char *x = malloc(44 * sizeof(char)); for (i = 0; i < 10000000; i++) { sprintf(x, "%d %d", i, i); } free(x); } Their version was intentionally biased, which is a shame.
- scott_s 15y agoProbably because they wanted to simulate calling a function that parsed a string, and such functions will have to allocate and deallocate memory as needed. It's also worth noting that calling malloc and free in a tight loop where you're always requesting the same amount of memory will be pretty fast. Good implementations of malloc - of which glibc certainly is - will consistently return the exact same chunk of memory to you, and you will be on the fast-path of the allocation algorithm.
- xd 15y agoWhy would you assume the need to deallocate in the loop? Reuse of an already allocated memory location is C optimisation 101.
- scott_s 15y agoYou're looking at this from the wrong angle. You're looking at the C code and thinking, "How can I optimize this?" What you need to do in this case is look at it and say, "How can I optimize this and still retain the essence of what I want to test?" Your optimizations remove that essence - if you're calling a function that is a part of an API, it will have to allocate and free its own memory. That the code is in a loop is an artifact of the experiment.
- xd 15y agoI'm looking at it from the angle of someone that has spent over a decade in and out of C. The code in the loop is in NO way an "artifact", it's absolutely critical to the comparison. My example in no way removes the essence, especially if we are using "idioms".
- scott_s 15y agoI said the loop is an artifact, not the code in the loop. Their experimental design is "Do x N times, then divide the overall runtime of the program by N to estimate the cost of x." If timing a program that did x once lead to good results, they would do that - but it doesn't, so they don't. You're trying to optimize around the loop, but by doing that, you're changing the x that is being measured.
- xd 15y agoIf by x you mean performing a string operation and copying the result to memory .. I still fail to see how allocating and deallocating memory on each iteration is a fair comparison, it's not something I'd expect a competent C developer to do ergo how is that a relevant comparison? I know the aim is to show off the string operation in and of itself so why not leave it there, why the need to bring garbage collection into the mix? Edit: it's the way the garbage collection has been thrown into the mix I'm having difficulty understanding the need for.
- pizza_ 15y agosizeof(char) is always 1 by definition
- MostAwesomeDude 15y agoIf you didn't notice, their version was based off of static allocation for the character array, which is the kind of thing a sharp C programmer will put in as an optimization. Note that the Python version is already pretty optimized, according to general Python idioms. You are arguing that they should have compared against a less efficient C example, which honestly boggles my mind.
- kingkilr 15y agoI've long since lost track of what it means for a comparison between languages to be fair. To put that a different way, how should we have compared them? Should we have downloaded some GC library for C to implement it?
- xd 15y agoI guess the real problem is that the example serves no real world purpose and can very easily be biased. See my response to scott_s below.
- MostAwesomeDude 15y agoInstantiation for side effects happens in Python. Unless PyPy can prove that the string isn't used anywhere (and it can't, really), it has to execute the statement and push the object onto the stack before discarding it.
- wingo 15y agoWhy can't it?
- MostAwesomeDude 15y agoPyPy simply doesn't have such a thing yet, that's all. I don't think there's any technical reason that it couldn't be developed at some point in the future.
- carbonica 15y agoIt's a matter of purity inference. They already trivially know the value isn't used based on the AST, so they need to show that the function being called is pure to elide it. Naturally, in the general case this is undecidable, but there are fast algorithms for very weak purity inference that might do the trick, at least in this case. There may be other Python-specific concerns I'm missing - my work in this area is in Ruby static analysis - but one other thing is that allocating memory is a side-effect itself. The main side-effect visible to Python is that it might raise an exception for being out of memory - this would have to be special-cased as an acceptably ignored side-effect by any purity analyzer.
- jckarter 15y agoThe more fundamental mismatch is that they're testing an interpreter (libc's printf implementation) against a compiler (pypy's format string jit). A C++0x or D library that parsed format strings at compile time would likely still beat pypy.
- icebraining 15y agoBut Pypy can optimize dynamic strings, while a static compiler can't. Replace the constant string with argv[1], and run the code: for Pypy, there is no real difference, but the C/C++/D compilers are unable to optimize.
- repsilat 15y agoI think this is still a library problem, not a language problem. "Compiling" a string at runtime for `sprintf` isn't any more difficult than doing it at compile-time, and plenty of regex libraries do very similar things. Compiling of printf strings isn't done, though, because nobody cares about string performance unless they're writing UNIX command-line utils. If you're writing C you're probably only dealing with strings for (infrequent) IO, spending the vast majority of your time crunching away on pointers and integer types (floats in niche cases). In the end, you're probably only printing something out because someone needs to read it, and how fast can humans read, anyway? This goes just as much for the printing of floating point numbers. (http://www.serpentine.com/blog/2011/06/29/here-be-dragons-advances-in-problems-you-didnt-even-know-you-had/ http://www.serpentine.com/blog/2011/06/29/here-be-dragons-ad...)