Golang performance in OpenGL
Вставка
- Опубліковано 10 чер 2024
- I was curious how the performance of Golang is impacted by using libraries through CGO. Specifically I wanted to see how the performance drops when I use OpenGL in Golang instead of C++. So I wrote a benchmark similar to bunnymark in Go and C++ to compare average frame times.
⁍ Wishlist Spruce: bit.ly/SpruceOnSteam
⁍ Twitter: bit.ly/UnitOfTimeOnTwitter
⁍ Discord: / discord
Thanks for watching. Happy to answer any questions! - Наука та технологія
1:00
That is the true windows development experience.
Haha. I'm finally a true windows developer now :)
More like CMake development experience.. If the dude had simplified his build system (using .bat files, keeping dependencies usage as low as possible) he wouldn't have this kind of problem.
Impecable. There's always some overhead with OpenGL calls, even in plain C, so I'd say you're on the right track. At some point "it goes faster" just stops being a practical thing and becomes more of a benchmark game anyhoo.
Yeah I totally agree. It's really easy to fall into the trap of micro-optimizing one part of a program, only to realize that it wasn't the thing slowing you down in the first place :)
That comment sounds like it was written from someone who doesn't have a single clue what he's talking about.
Have you ever written a single line of C? Have you ever written a single line of OpenGL?
@@michaelzomsuv3631 I've written a fair bit and it's all public: anyone can read my code and decide for themselves how much I know.
Great stuff, keep it up! Missed your streams, will try to catch them next weekend.
Thanks! Yeah I actually didn't have time to stream last weekend. So you didn't miss much! Hoping for next weekend!
nice video short and to the point thanks for making it
Really good and explicative content right here, keep it up!
Thanks. Appreciate it!
Found your channel because of this. I just subscribed. You’ve got a real talent for writing and making programming fun. Keep this up and you’ll be famous. Also, very cool to see you do all of this in Go. It makes more fun for me since I’m a Go dev too!
Hey thanks for the kind words. I really appreciate it! Glad that a fellow Go dev enjoyed it :)
If you're writing particles, you dont typically use one draw call, but for normal situations (ie, a couple of objects) we use individual draw calls for each. Mainly because there are actually negative returns at low object counts
Yeah. There are definitely some tradeoffs to consider when deciding if its worth it to do CPU batching!
Thank you for this video.
Dear @UnitOfTime, thanks for the nice video. Please, could you share your benchmark project? Cheers!
Hey Fabio, Thanks for reaching out. I don't have time to clean the code up (maybe I'll do that in the future). But you can see my baseline go code here: github.com/unitoftime/experiments - Looks like the 'regular' (ie non-batching) code is panicing for some reason; I'll have to look into that at another date. The 'batch' binary should be functioning, though.
It's somewhat modified from its original form because I had to record the benchmark separately (at fixed interval timesteps) to make the video. I never converted it back to the original.
I included the cpp code (it won't compile) that I used for the non-batching benchmark. It's an adaptation from LearnOpenGL.com. Lastly, For the batching benchmark, I modified the raylib 'bunnymark' codebase to match the functionality of my batch code.
Enjoy!
Awesome! Thanks a lot @UnitOfTime !
C++lang my favourite
Thanks for another pleasant speed comparison 🥰
Actually Im impressed seeing 78% I thought Go is as fast as C++ is
Glad you liked it!. Yeah Go has to do some extra work to translate memory from Go world to C world when calling the OpenGL bindings. Go has a special Foreign Function Interface called CGO which does the translation, but it causes a small performance hit. In the first example I make a lot more OpenGL calls because I do no in-memory batching so the performance hit is much more noticeable.
Thanks for watching :)
Making a video like this about 3D games would be great
:) Thanks for the suggestion! Still working on more videos!
Noice
and manim graph looks dope
Haha thanks. Yeah Manim looks super clean
I think the takeaway here is that it's better to use a declarative approach rather than an imperative one. If you need something done fast, try to find a way to make the library do it for you.
Yeah I tend to agree with your second sentence: "If you can find a library that does what you want, just use it" (Unless of course your trying to learn or build some new features). I'm not sure I fully understand what you mean by declarative vs. imperative; I guess I prefer imperative programming at the micro level, but declarative at the more macro level (ie each function implemented imperatively, but the ability to use those functions as declarative building blocks).
Cheers!
It's surprising to see such a difference in performance between Windows and a Linux distro. Are you sure your powerplan/powerdraw are the same between the two?
Yeah if I had to guess, the NVIDIA drivers aren't as good in Linux which is why the performance is lower. I wasn't really trying to do a Windows Vs. Linux comparison here, so I didn't do much in the way of normalizing the two OSes. I might investigate this more in the future, I think it'd be interesting to see if the performance gap is similar for an AMD card. Or what the real cause of the difference is.
Interesting video, thanks :)
Really interesting
Given that Go is a compiled language, and the compiler doesn't bother with optimisation such as C/C++ does, perhaps it is possible to have an unofficial compiler than cranks on optimisation and render Go faster than C++.
Interesting Idea. I know there's a GCC-based Go compiler called gccgo, though I haven't looked much into how it performs compared to the regular Go compiler. I actually think the compiler optimizations that the Go compiler performs are pretty good. The problem in the case of using OpenGL (or calling any C-based library from Go), is that we have to do some extra work to translate the memory from its form in the Go memory space to its form in the C memory space. Go uses a foreign function interface wrapper called "CGO" which does this translation for us, but at a mild performance cost.
Thanks for watching! :)
@@UnitOfTimeYT oh, you're right. I believe the GCC compiler comes by default in Linux. I thought of this because a friend told me the other day there's an unofficial interpreter for Python that's said to run faster, or something to that effect.
Nice use of Manim library!
Thank you!
1:03 how did you fix that? "error in configuration process" please
If I recall, that was because I didn't have the correct C++ compiler installed on my system. I believe that was resolved once I had Visual Studio setup correctly. Maybe check this out: stackoverflow.com/questions/47443018/cmake-error-in-configuration-process-project-files-may-be-invalid-visual-studi
What about Ebiten being pure go. does it make it similar to cpp?
Ebiten (as far as I know) still has the performance penalty of CGO despite the fact that they recently moved (or are moving?) to the purego lib. I think the purego stuff mostly makes it so that when you cross compile you don't have to install windows toolchains (for example, if you're on Linux). That's my understanding at least, so I hope I didn't butcher it :) Someone more familiar with Ebiten would probably have a better answer than me. Seems very cool though!
this is gonna blow up during The War
Gotta make sure to sharpen our benchmarks so that we can be victorious!
@@UnitOfTimeYT yeah lol
Hi, pls don't stop making videos
Haha thanks! Not planning to. I'm having to take a small break through the holiday season. I'll hopefully be back in Jan/Feb with more!
+1
I mean, your initial results are actually way more impressive than I would have thought, considering the garbage collection.
Yeah I agree. I think GC problems can definitely creep up if your not careful. I was mostly preallocating data so I think in this case it minimized the GC impact. Thanks for watching!
you're measuring the driver and the application wrappers.
Yes Definitely!
I would be interested in a similar test for 3d
Yeah that would be interesting. From what I know, I'd think that the larger meshes become, the worse Go will perform relative to C++. This is because you'd be less likely to batch large meshes, which would cause you to make more draw calls. But that's just me guessing with no actual proof lol
do a rust vs c++ comparison like this too.
Yeah that would also be an interesting experiment to run; my expectation would be that C++ and Rust would be similar performance. Rust has super low overhead for making OpenGL calls (According to some googling I did).
This is probably the third time I’ve watched this video, I think I might try to do the same thing in another language
haha - Thanks! Yeah let me know if you do it in another language. You can run it against my Go code. Curious to see the results!
@@UnitOfTimeYT I will!
What about C++ vs Rust?
I don't know Rust very well. But my understanding is that Rust's Foreign Function Interface (FFI) to make C calls has no overhead. Because of this I'd expect the performance to be very similar. Or at least I'd expect that you could get the same performance from both if you tried hard enough.
Rust people, feel free to correct me if I'm wrong.
i like your animation style! reminds me of 3blue1brown
Thanks! I actually used 3blue1brown's animation library which is open source and very good!
@@UnitOfTimeYT nice
The bitrates in this video are off the chart. Imagine what they would be in 4K or 8K.
Haha - I'm not sure of what typical bitrates look like. I did have some trouble compressing the gophermark demo sections though, with all those gophers moving around in each quadrant.
Raylib is anything but the “peak of rendering performance” lol.
Lol yeah you're definitely right about that. I was trying to write a joke, but looking back I think it was a little too dry
that last frame at 2:47 made my heart flutter
Haha glad you liked it! :)
i saw that(Dart)
C++ on Linux ≈ Go on Windows ? Makes me sad.
Yeah. It would be interesting to compare different drivers and GPUs to see if it's possible to make Linux closer to windows in terms of performance
You want fast? Just use vulkan but seriously though nice vid!
Thanks! Yeah I haven't dabbled in Vulkan just yet. But one day I want to check it out!
To be honest, 78% is ain't that bad!
Yeah I agree, it really isn't. I think that Go can be a great target for games that aren't targeting the cutting edge graphics/physics simulations of the AAA world.
weird how performance of both programs is better on windows than linux
Yeah. My guess is that since Windows is the most common gaming platform, NVIDIA has more obligation to write high performance drivers there.
@@UnitOfTimeYT ahh that makes sense, plus Nvidia also lowkey hates linux lol. Linus did made a statement that Nvidia is the worst company they have dealt with, even said f u nvidia while flipping them off. Altho it has been some while, but I get a feeling that Nvidia still doesn't care
Haha yeah. Sounds like some drama :) I'd be curious to see if AMD cards have a similar performance gap.
@@UnitOfTimeYT Seems like it in my experience, also since I have a 5600XT I am cursed with random crashes by the GPU driver when I stress the card out a bit too much, the only perfect GPU support I've had on Linux has been Intel's integrated graphics sadly
try with Rust
Yeah! I'm actually working on a new video that compares Rust Vs. Go, but it compares physics performance, not rendering.
youtube compression hates you
Haha. Yeah some of that might be self-imposed :P
C++ did not solve C problems.
Rust did not solve C++ or C problems.
Go did not solve C++ or C or Rust problems.
We really need new language that solve C and C++ problems. if we do no body will care about Rust or GO 😎😎🥰😎😎
Haha. Maybe you can look at Jon blows language Jai? He seems to have a different path from Rust/Go. That said, I do like a lot of Go's design decisions.
RAII does seem to solve a lot of memory related problems though
C++ did solve C problems.
Type-system of C was too weak, it accepts a lot of ill-formed code that can be detected as compile-time errors.
C++ solves this problem by having a stronger type system. Most of the run-time errors of C are now compile-time errors in C++.
C++ also introduced RAII, a much superior paradigm to manage dynamically allocated resources.
@@yigitpolat read the article of The Linux Creator and you will understand that C++ does not solve C problems neither Rust
Rust is much newer than Go, and in my opinion tries to be something that C++ already fulfills well. Go is great for servers especially, I prefer C for most other things though
You're 300IQ but have a cringe dialog.
Haha thanks!
I like the video, very informative. However, the humbragging bothered me. You say "very unscientific" as if it's some sort of virtue. It's not. If your method really was unscientific, then you should have stopped the video right there.
Thanks for the feedback. Sorry that it bothered you. It was more of me trying to throw some lighthearted, self-deprecating humor in here and there, but I may have oversold it. Whenever I benchmark things, it seems very easy to miss or not have time to control for all variables. In this case, I do think that I could have done a better job to make it more accurate:
1. Better control on compilation and compilation modes for native/cross compilation
2. Better control for batch renderer test (where I just used raylib instead of writing a batch renderer in C++)
3. Better control on background processes (especially in Windows)
Thanks for watching!