-3

I translated a Java program into C++, and I was getting very slow performance from C++ as compared to Java. Looking at the activity monitor, I saw that the Java program, which I ran first, was using over 90% of the CPU, while the C++ program was using around 30%.

Java vs C++ CPU utilisation for identical program

It appears that the JVM is able to harness the full power of the CPU without user intervention. What changes should I make to use the CPU better for the C++ case?

tf3
  • 447
  • 1
  • 4
  • 16
  • 1
    Looking at CPU usage isn't a good metric. Run an actual profiler, figure out where the bottlenecks are, and then you can decide if utilizing multiple threads or processes is a good solution. – Stephen Newell Dec 03 '20 at 16:00
  • 2
    I don't think Java can magically parallelize your program without your help. Are you sure you aren't using multiple threads there yourself? I don't know Java - maybe there are some "Parallel" operations which might hide multithreading inside? – Vilx- Dec 03 '20 at 16:01
  • I would be happy, when the same program would use only one third of my CPU. This gives room for more useful work – Olaf Dietsche Dec 03 '20 at 16:02
  • Which takes less time to run a task to completion? – user4581301 Dec 03 '20 at 16:05
  • 1
    I think we need more information about what the program does and how you translated it. AFAIK Java does not use multiple cores unless the code is explicitly using threads. – 0x5453 Dec 03 '20 at 16:05
  • @Vilx- I am using a Priority Queue in both the programs. Maybe there are some parallel operations going on beneath the surface in the java library I'm using. But I'm doing nothing explicitly parallel on my own – tf3 Dec 03 '20 at 16:06
  • @user4581301 java takes less time – tf3 Dec 03 '20 at 16:07
  • Are you compiling optimized or unoptimized? – user4581301 Dec 03 '20 at 16:09
  • @user4581301 i am optimising with -O3 – tf3 Dec 03 '20 at 16:10
  • 1
    Are the data access patterns cache friendly? – user4581301 Dec 03 '20 at 16:11
  • By the way, how many CPU cores/threads do you have? – Vilx- Dec 03 '20 at 16:12
  • Oh, yeah, @user4581301 is totally right! Check this out: https://lwn.net/Articles/250967/ – Vilx- Dec 03 '20 at 16:14
  • if the C++ program can do the same as the Java program with less CPU, then whats the problem? – 463035818_is_not_an_ai Dec 03 '20 at 16:20
  • Is the output of a competed task correct? – user4581301 Dec 03 '20 at 16:22
  • Suggestion: Use the profiling tool that came with your development tools to help narrow down what's causing the slowdown. – user4581301 Dec 03 '20 at 16:22
  • @user4581301 I don't know too much about optimising C++ code by making it cache friendly. I did read a chapter from Optimized C++ and it said a few things like frequently used code blocks and memory locations are cached and give better performance. But on reading it further, very soon I found myself wanting to go deeper into CS fundamentals like compilers and architecture, maybe that is the price for learning C++ – tf3 Dec 03 '20 at 16:55
  • @largest_prime_is_463035818 no, in this particular case, I did not run the programs to completion. I used a bigger input only for the sake of capturing the CPU usage, as the difference in runtimes is not very noticeable with smaller inputs – tf3 Dec 03 '20 at 16:57
  • @user4581301 the outputs are correct – tf3 Dec 03 '20 at 16:58
  • I mainly wanted to suggest, as others have already pointed out, that CPU utilization isn't the best metric always. Assume both program really do the same and finish in same time, then less CPU would acutally be a plus. – 463035818_is_not_an_ai Dec 03 '20 at 17:00
  • @largest_prime_is_463035818 agreed, only that C++ is taking longer. I am actually transferring my meagre learnings from an algorithms course I took in Java to C++, and turns out there's a lot more to real performance than identical looking code. – tf3 Dec 03 '20 at 17:02
  • @Vilx- I have got a dual core cpu – tf3 Dec 03 '20 at 17:05
  • 1
    Java to C++ ports are one of the trickiest because the code looks so similar even though the underlying ideologies are radically different. You typically can't literally translate code any better than you can literally translate spoken languages. The best option is to port the behaviours. Your answers to my probing suggests you aren't doing anything outright silly, and your description of the problem low speed AND low CPU use suggest you aren't doing something obvious. – user4581301 Dec 03 '20 at 18:17
  • 1
    Recommendation: Make a small example that runs slower in C++ than in Java for people to pick apart. I'm not sure if the question would be better received at Stack Overflow or its sister site Code Review. I suspect Stack Overflow because what you describe is more "buggy" than the performance/style improvement that Code Review specializes in. Anyway, make an example, see if you can figure it out on your own with the help of a profiler, and if not, ask here. – user4581301 Dec 03 '20 at 18:23
  • 1
    If you can figure it out, but think there's still room for improvement consider asking at [Code review](https://codereview.stackexchange.com/help/asking). Yes, I linked to the Asking help pages on purpose. You'll want to read them before posting in order to make sure you hit all of the requirements. – user4581301 Dec 03 '20 at 18:25
  • 1
    Low speed and low CPU suggests the program is spending a lot of time waiting on something. This is probably access to a resource, but without more information we can't make useful suggestions. – user4581301 Dec 03 '20 at 18:26
  • 2
    If this is a literal translation, and the C++ program uses the heap similar to the Java program, then this might be one area to look into. – Olaf Dietsche Dec 03 '20 at 18:47
  • @user4581301 i think that this answer tells me a bit about the problem I face https://stackoverflow.com/a/18268325/2672154 . I am indeed invoking "new" a lot and creating objects on the heap. But for C++, dynamic memory allocation is a slower operation as compared to Java, which uses preallocated memory, according to other answers and comments on the above link. Also, I used XCode Instruments to profile my C++ code while the Java prog was running, I saw C++ cpu usage ~ 85% while Java was consistently around 150-250% (this piece of info might be less important than the memory alloc issue) – tf3 Dec 04 '20 at 13:31
  • @user4581301 I took a look at this too and it says the same thing https://stackoverflow.com/a/2163570/2672154 . Apparently, one needs to "roll their own malloc" to match Java's prowess in dynamic allocation. – tf3 Dec 04 '20 at 13:44
  • @OlafDietsche it is essentially a literal translation, I use the "new" operator a lot and this is where my C++ program is taking more time than the Java one. – tf3 Dec 04 '20 at 13:47
  • 1
    Rational for this: In C++ you don't pay for what you don't use. Java's memory management scheme has a cost that many (probably most) programs written observing C++'s idioms would not encounter. You do not want to roll your own `malloc`. That's for the Java case where you `new` everything. In C++, and no suitable container already exists in the Standard Library, you write an allocator or a custom `new` for those few objects that you do dynamically allocate. this allows you to optimize for the object and the access patterns in ways the one-size-fits-all custom `malloc` cannot. – user4581301 Dec 04 '20 at 16:17
  • 1
    In C++, `new` should be one of the last tools in your toolbox you reach for. See [Why should C++ programmers minimize use of 'new'?](https://stackoverflow.com/questions/650031) And instead follow the advice of Stroustrup: don’t store data unnecessarily, keep data compact, and access memory in a predictable manner. Rules you should follow in all languages. – user4581301 Dec 04 '20 at 16:19

1 Answers1

3

Read a good C++ programming book then see this C++ reference. Read also the documentation of your C++ compiler (perhaps GCC).

Read also some operating system textbook.

Consider using frameworks such as POCO or Qt or Wt.

With a multi-core processor, you might use C++ threads. You'll need to synchronize them, e.g. using mutex and condition variables.

On GNU Linux, you could read advanced linux programming and use the syscalls(2) related to process creation and management (e..g. fork(2), execve(2), waitpid(2)...) and profiling (see time(7), profil(3), gprof(1), perf(1)).

On Windows, you need to use the WinAPI.

I translated a Java program into C++

In general, that is a bad idea. Learn your programming language and your operating system, and design your software for it.

Take inspiration from existing open source software on github or gitlab (e.g. RefPerSys, Firefox, Tensorflow, OpenJDK, Clang static analyzer, Fish ...)

Java implementations (e.g. JVMs) have some garbage collection and some class loader.

C++ implementations do not have any garbage collection. So read the GC handbook. Notice that circular references are hard to handle efficiently in C++, and this could explain your performance issues.

On Linux/x86-64, you might load plugins with dlopen(3) with dlsym(3) (or generate machine code at runtime using asmjit or libgccjit)

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • I am learning C++ using much the same resources you have mentioned. I will check the references you gave for the Operating Systems and other topics. Thanks. – tf3 Dec 03 '20 at 16:09
  • Accepted this answer since it tells me that there is much more for me to learn to effectively use C++, a realisation which dawned upon me after reading more. – tf3 Dec 04 '20 at 14:11