简体   繁体   中英

C++ move semantics performance compared to Java

I wanted to prove that C++ using move semantics is much faster than Java and I landed in a big surprise that it is actually much slower.

EDIT: I am on purpose inserting elements in a vector despite I know such insertion fits better with a list. However this is a typical benchmark to benchmark move semantics in C++. Thus I wanted to use this specific test to see the differences with Java as well.

I might have done a mistake: what I did are the following 2 programs: http://melpon.org/wandbox/permlink/abZlAmZrOC9fJV8r and http://melpon.org/wandbox/permlink/3QGQMEIoF5kc3xtY

The result is quite surprising as it suggests that Java is faster with a factor 6! I supposed the code might run on different machines, thus I tried on my machine with msvc 2012x64 and the following compilation options:

cl /EHsc /Ox cppPerf.cpp

Compared to

jdk1.8.0_73\\bin\\javac.exe javaPerf.java

The result give a ratio of 10 in favor to java !

How could it be that java is that much faster than C++ that is furthermore using move semantics ?

Another interesting point is that using Java7 gives performance quite far from Java8 but still better that C++: http://melpon.org/wandbox/permlink/CJXwHCwp5rGwr1Gc

EDIT: I removed the code which is accessible through the links.

EDIT:

I think I found the problem, Java optimized away some code. These are updated versions which show that C++ is much faster: http://melpon.org/wandbox/permlink/GsflztloK7ir2jea http://melpon.org/wandbox/permlink/CLwKoZzbfqstDOfn

EDIT: This is another test which provides benchmarks for C++ using references as suggested by @dasblinkenlight which shows huge differences between C++ and Java (note I did note use unique_ptr because I wanting to check against C++03 and I wanted to avoid boost thus no scoped_ptr either): http://melpon.org/wandbox/permlink/bYQjNpjsIZu3vp3f

Results are:

C++14:
USE_MOVE  USE_REFERENCES  TIME
    Y             Y         30 to 55ms
    N             Y         30 to 60ms

    Y             N         370 to  210ms
    N             N         390 to  270ms (Implicit move of elements in vectors)

C++03:
USE_REFERENCES  TIME
        Y         45 to   70ms
        N       1370 to 1650ms (No implicit move of elements in vectors)

Java:
               11300 to 13000 ms

The problem is that you are not comparing apples to apples:

  • Java's String s are immutable, so copying them into a container amounts to storing a reference.
  • More importantly, your code inserts at the beginning of the vector, so the vector ends up performing O(n 2 ) copy operations.

I think the second point accounts for the bulk of the difference. Inserting at the end with vec.insert(vec.end(), std::move(myString)) or with push_back and a corresponding change in Java should make times much closer to each other.

To fix the first point as well, allocate your strings dynamically, and make a vector of std::unique_ptr<std::string> instead. This would copy pointers instead of copying content, bringing performance times closer to each other.

I wanted to prove that C++ using move semantics is much faster than Java and I landed in a big surprise that it is actually much slower.

If someone asks you to prove that C++ is faster than Java than turn around and go away. the industry does not need such a proof.

The result is quite surprising as it suggests that Java is faster with a factor 6!

Nope.

In a nut shell , this is what C++ do :

for 10000 times, Do:
 1. measure the literal size
 2. allocate enough memory to hold the literal (EXPENSIVE!)
 3. Copy the literal memory into the newly allocated memory 
 4. check if there is enough memory in the vector to hold current size + 1 string objects, if false - allocate new chunk and move all the existing objects to that chunk of memory (EXPENSIVE!)
 5. move the existing strings inside the vector forward by 1 index (EXPENSIVE!)
 6. move the string object to `vec[0]`
for 10000 times, Do:
 7. build new string objects from r-value reference returned from `vec[i]`
 8. free the string memory (EXPENSIVE!)

you build 10000 string objects from a literal, so you have to allcoate 10000 chunks of memory, re-calculate the literal length again and again and repeatedly move the strings objects inside the vector.

What Java does:

 1. when the program goes up, the JVM builds a string object containing the literal just once
for 10000 , Do: 
 2. copy the pointer (Cheap.)
 3. check if there is enough memory in the vector to hold current size + 1 string pointers , if not - allocate new chunk of memory and copy the existing pointers to that memory block (Cheap.) 
 4. move the existing string pointers inside the vector forward by 1 index (Cheap, probably uses `memmove` behind the scenes)
 5. copy the pointer to `Vector[0]` (Cheap.) 
for 10000 , Do:
 6. Copy the string pointer pointed by `vec[i]`

The string object is created only once, and its pointer is being copied again and again. the Java program does nothing like the C++ program.

So basically, this program only shows that copying pointers is cheaper than copying objects. nothing that we didn't already knew. if you really want to do fair benchmarking, either benchmark string pointers in C++, either make the Java program re-clone the string again and again.

C++ vector s insert method uses reallocation if insertion is not at the end:

Because vectors use an array as their underlying storage, inserting elements in positions other than the vector end causes the container to relocate all the elements that were after position to their new positions. This is generally an inefficient operation compared to the one performed for the same operation by other kinds of sequence containers (such as list or forward_list).

Replace vector with list and you will see that performances are almost the same.

Vector as an abstract type is almost the same in Java and C++, but their respective implementations can differ seriously...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM