The benchmark is really crappy. If the language uses O(n+m) concatenation for strings of length n and m, then the total runtime would be O(n^2). That would happen if strings are immutable and no "stringbuilder" is being used. If that special case was optimized or if the strings are mutable, total runtime is O(n).
Here is the corrected C version:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (int argc, char const *argv[])
{
char *str = malloc(sizeof(char) * 238890);
char buf[5];
int i, n = 0, len;
for (i = 0; i < 50000; ++i) {
len = sprintf(buf, "%d", i);
strcat(str + n, buf);
n += len;
}
return 0;
}
It runs 100 times faster than the original program.
Edit: If you think I "cheated" by doing some calculations that I shouldn't do, here is a C++ version that runs just as fast as the improved C version:
#include <string>
#include <cstdio>
int main()
{
std::string str;
char buf[6];
for (int i = 0; i < 50000; ++i)
{
sprintf(buf, "%d", i);
str += buf;
}
}
Agreed - and I'd be interested to see what happens if you replace the sprintf interpreter with a function like itoa.
While I'm not surprised that V8 beats existing Ruby implementations, that's more a demonstration that those implementations aren't very fast. When your benchmark tells you you're beating C, it's probably a good idea to check that your C code isn't stupid, before posting results on your blog...
Here is the corrected C version:
It runs 100 times faster than the original program.Edit: If you think I "cheated" by doing some calculations that I shouldn't do, here is a C++ version that runs just as fast as the improved C version: