1. Java (possibly on Windows, right?) without -server flag is like gcc without any optimisation.
2. Vector?!!! Man, are you kidding? Add mutex_lock / unlock into your C++ loop and *then* compare. Java's Vector is thread safe, C++ vector is not. Or better use ArrayList.
3. Test running for a less than 1 second on an outdated Java means nothing.
To summarise:
double triple facepalm.
Other flaws:
4. Storing a raw pointer to a string in a std::vector is a bad idea for many reasons. This is a bug waiting to happen, because strings are mutable and additionally, who is the owner? The container? If so, who is gonna delete them? What if your container needs to live longer than the current scope the string is in? Therefore modern C++ programmers advocate using shared_ptr. ;)
5. C++ strings don't support unicode, you should use wide strings to make these tests comparable. This is however important in value test only, which C++ lost anyway *even using short strings*, at least in the Athar's test.
----------------------------------------------
Java code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
import java.lang.Double;
import java.lang.String;
import java.util.List;
import java.util.ArrayList;
class VectorTest {
private static void test() {
final int COUNT = 1000000;
List<String> v = new ArrayList<String>(COUNT);
String s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for(int i = 0; i < COUNT; ++i)
v.add(s);
}
public static void main(String[] args) {
long b = System.currentTimeMillis();
for (int i = 0; i < 1000; ++i)
test();
long e = System.currentTimeMillis();
System.out.println("Time: " + (e - b) / 1000.0);
}
}
| |
Equivalent C++ code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
#include <vector>
#include <string>
#include <memory>
#include <ctime>
#include <iostream>
void test() {
const int COUNT = 1000000;
std::vector<std::shared_ptr<std::string> > v;
v.reserve(COUNT);
std::shared_ptr<std::string> sp(new std::string("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
for(size_t i = 0; i < COUNT; ++i)
v.push_back(sp);
}
int main() {
std::clock_t b, e;
b = std::clock();
for (int i = 0; i < 1000; ++i)
test();
e = std::clock();
std::cout << "Time: " << (double(e - b)/CLOCKS_PER_SEC) << '\n';
return 0;
}
| |
Options and versions:
C++ - gcc 4.6.1, 64bit, optimisation level -O3 (checked also -O2, but no huge difference)
Java 6 update 30, 64 bit, -server (not really needed, because on ubuntu it defaults to -server)
And now the timings:
C++: 6.07 s
Java: 2.59 s
Without reserving space and just letting the vectors grow as more elements are added:
C++: 21.07 s
Java: 4.81 s (4.51 s when used -XX:+UseCompressedOops optimisation)
Ok, you may point out, that shared_ptr is not fair, because *sometimes* you know your string will outlive the container, and you can use your raw pointers. Ok, so with raw pointers (just used std::string* instead of shared_ptr):
C++ with space reservation: 2.65 s
C++ without space reservation: 9.12 s
So to conclude: C++ matched Java performance only once in this test, and had to use non-garbage collected, raw pointers and had to specify the vector size in advance. In all other cases, Java was 2-4x faster. Reasons are simple:
1. In Java raw pointers are both *better* in terms of functionality and *much faster* than shared_ptrs in C++.
2. In Java memory allocation / reallocation is much faster (the test without prior reserve shows it cleanly).