>Then of course I remembered that std::map is a red-black tree, i.e. ordered, whereas the Go map is not. Change out std::map for std::unordered_map and C++ pulled ahead, 20% faster than the Go code.
upped it to 10M ops and used .reserve to avoid unwanted allocs.
Go 1.12 is 2X faster than C++.
This was totally unexpected as I feel the basic algorithms are simple and there is not much you can do to make it faster.
If you have know what is going on, please share.
golang: 7.76 real 8.67 user 0.08 sys
Java: 3.74 real 3.58 user 0.46 sys
public class Test {
public static void main(String[] args) {
final int numOfStrings = 100_000;
final int numIters = 1_000;
var numStrings = new String[numOfStrings];
for (int i = 0; i < numStrings.length; i++) {
numStrings[i] = Integer.toString(i);
}
for (int i = 0; i < numIters; i++) {
var strToInt = new java.util.HashMap<String, Integer>(numOfStrings);
for (final var s : numStrings) {
strToInt.put(s, s.length());
}
}
}
}swisstable (absl::flat_hash_map) is a popular choice right now for the hash table to use for C++ code that cares about performance. There are other choices as well (dense_hash_map, F14FastMap, etc), But honestly most choices these days are worse than std::unordered_map (well, boost::unordered_map is probably just as bad, since std's implementation was taken wholesale from boost without any thought!)
s/very close/close enough/
C++ is still multiple times faster in many/most situations [1]. And while it's hard to measure productivity, it's nearly impossible to beat out-of-the-box productivity Python offers [2].
But do people need the performance of C++? Usually not. They just need something faster than Python/Ruby that uses less memory than Java.
And do people need the productivity/prototyping of Python? Often not. Most work is on established code bases where static typing (even weak static typing) is a huge benefit.
Go is full compromises, but in ways that turn out to be very pragmatic.
[1] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
[2] Though if you're making a TCP or HTTP server, Go is pretty great. For a CLI, Python stdlib argparse is unparalleled.
You can change "productivity/prototyping", remove productivity and just keep prototyping.
Dynamic typing like python has has nothing productive.
Dynamic typing means replacing few minutes to fight against the compilers errors by hours of debugging in runtime/production of problems that could be avoided easily with typing.
That a problem that appears very qickly as soon as you leave the world of "quick and dirty prototype".
There's a lot of things though. Want to create a set of charts and graphs of data, especially in a repeatable way? Nothing better than matplotlib.
We absolutely 100% loved it for small contained pieces like monitoring checks.
When doing a basically boring API with user management some of us found it ok at best, others (like me) really hated it with a passion. Every task that should take 20 minutes and 20 lines of code in any web-first ecosystem (php+symfony, rails, flask) would take 3x as long with 2x as many lines of code, also because of "if err != nil". Sure, a lot of it might have been "Go beginners" but it just never felt smooth for controller-heavy web development.
The price one pays for simplicity is the need to discover and master various design patterns; it requires a bit of planning beyond syntax and module exports. It took me quite a bit of time before I felt downright fluent in Go.
I did get there, and I really enjoy the language, but I wasn't immediately productive.
In Go, you are expected to use the features that exist to accomplish the goal, so instead of knowing a ton of features at a somewhat surface level, you need to learn what is there fairly intimately, and use them to their full effect. For a simple example, there's no such thing as "class methods" in Go, so obviously anything best solved via class methods is impossible, right? Except of course it has "class methods". Class methods are just methods that don't reference the instance itself. Go doesn't have any syntactic label for them, but they exist just fine and I make fairly heavy use of them.
Personally, when I read someone complaining that they tried Go and it was "full of boilerplate, repetitive code everywhere and they kept having to copy&paste functions" that they were either A: in the completely wrong domain (see my other comment about how I don't think Go is good for math at all), or B: they didn't do this and were probably trying to jam a map/filter/reduce-heavy workflow, or an inheritance-heavy design, or something else not native to Go, into Go. My code isn't particularly repetitive. Even the error-handling in my mature code tends to be between 1/3-1/2 not "just return the error". (In prototyping it often starts out that way, but by the time I ship something, there's usually a lot more going on.)
As another for instance, you really need to learn to use interfaces to their fullest, as integrated into the type system. You can put methods on anything, even functions or other non-struct types, and anything with methods can conform to an interface. It's really helpful to be able to do that. If you reject all these options as "that's not how I want to design", you're in for a bad time.
Bizarrely, despite their incredible distance on my internal "map of all programming languages", this is one thing Go and Haskell kind of share in common, and something I took from my experiences with Haskell, where you are also handed a certain set of tools and expected to make them work. If you try to take Haskell and force it to be an object-oriented language, you're gonna have a bad time, and you'll complain about how stupid typeclasses are and how stupid immutable data is and how stupid it is that all your code has to be written in IO so why is it even separated out and all kinds of other things. But the solution is to learn how to actually do things the Haskell way, at which point you'll find that while it may not be the best choice for everything, it certainly has some interesting things to say. Go actually does too, around the virtues of structural typing and the privileging of composition over inheritance. It's much less profound than what Haskell has to say, but it's still something.
Neither Go nor Haskell are unique in this characteristic. You really ought to come in to every language you learn with the viewpoint to learning how it does things, rather than coming in and trying to make it be some other language. It's just the simple languages that tend to really put this in your face. The languages with bazillions of features usually have something on offer that looks close enough to what you want that you can force your way through into turning the language into a different language. (And when you ponder what it looks like when you've got a team of 50 people doing that, you start to see some of what Go is designed to fix.)
Your point about using Go's type system (esp. interfaces) rings particularly true. When I finally figured out how to effectively use the type system, I suddenly found myself writing extremely malleable code. You can move data types and functions around quite freely, and this makes it easy to design & refactor without losing your place.
The flip side, as you say, is that extreme flexibility requires you to build your own skeleton.
BTW, are you github.com/thejerf? If so, I've contributed to Suture, and use it quite often, so thanks for that.
The JVM and .NET think otherwise.
I like C# and Java, certainly much more than C++, but Go hit that sweet spot of little ceremony (try to write a single file Java or C# program), performance, deployability (again, try to deploy a Java or C# program as an Ubuntu service on a low-end 512 MB Digital Ocean host or provide a Java or C# cmd-line program to a Mac user) and programmer productivity.
This is simply not true. Go is nowhere near that even when only new Greenfield projects are considered. I see many of the start-ups using it but most new projects are still in Java or c#. But go has captured the Dev ops tools area quite a bit.
Are you saying that Go is significantly more popular than Java for backend, server-side development? I'd like to see a citation on that, because pretty much any statistic I've read has said otherwise. If you are saying it's significantly more performant, then I'd like to see evidence for that too.
Go is simple, easy to install, and the benifits of a compiled language are huge. I can apply all of my systems knowledge to understand how my app is performing. The JVM is a career in of itself, and locks you into an ecosystem that is very proprietary and frankly full of lame enterprise salesmen and big business fogies. Go is fun. It’s branding is fun, it’s community is passionate, and a lot of big names are on the tin that speaks to a lot of us who love and grew up on Unix.
I mean, do you want to support Oracle and Larry’s bid to buy more islands or ken and rob?
You're not really arguing in good faith. This reads more like a parody.
… and so is just saying stuff :-)
C# was a windows-only show until very recently with the introduction of.NET Core, and ASP.NET Core is gaining in popularity very fast.
IMHO Go's current adoption rate has more to do with politics and Google's aura than anything else, really.
And I really don't see your assertion on Go eating Java's lunch. Sometimes Java appears to be the only game in town wrt backend development, with Python appearing in second place.
> try to deploy a Java or C# program as an Ubuntu service on a low-end 512 MB Digital Ocean host
I have no idea how a generi C# or Java program fares with so little resources, but I've deployed ASP.NET Core and Spring apps on Hetzner's smallest VMs (2GB) without any problem. I had to google digital ocean's micro VMs to check if such a thing really existed, and I have to say that the price difference (Hetzner's 2GB VM for 3€/month Vs Digital Ocean's 512MB VM for $2.50/month) hardly justifies the trouble.
So unless you're compelled to save about $0.50/month on hosting, I hardly see the point of your example.
Apparently there is a new Java project [1] floating around that is promising a way to use Java exactly in this use case, but I haven't played around with it.
[1]: https://quarkus.io/
You can run an empty Spring Boot service in 15MB of RAM or so.
Others have already pointed out doing this with .NET, and yes, it's also possible in Java land. I have done this, even running a Spring Boot service which is generally considered more heavy weight than other frameworks like Dropwizard. A plain Spring Boot service runs in about 15-20MB RAM if I recall. And now with the GC improvements in Java 11+, it's even better.
> Now Java is showing it’s age and cross compiling is no longer the problem it once was.
I see numerous flaws in this sentence. How Java is showing it's age, language wise, comparing to eg. Go? It is fully OO, has generics and recent versions with advanced functional stuff are making Java pretty modern language on (almost) Scala level.
Regarding cross compiling, it is still the problem. If Go gives you 3-4 platforms out of the box, you can't say cross compiling is solved problem; try to work with MIPS or slightly less popular embedded platforms.
Honestly, the only ads I see for Go developers are for blockchain projects, which suggest buzzword-driven development.
What we do know is that Kubernetes, Docker, Terrafofm, Prometheus, Caddy, et al. have taken off in part because Go is easily accesible and can scale. Go has risen metorically to the top just like Java did, and there are lots of really huge deployments of Go out there. The JVM will always have certain limitations and require it’s users to specialize in JVM tuning and architecture. Many users are also hesitant to support a company like Oracle, and the enterprise shilling that comes with the Java ecosystem.
And in fact performance itself is a very objective criteria. Either a piece of software is fast enough or it isn't. This doesn't refer only to percieved performance, but also hard performance indicators established in the requirements of a project. Sw dev 101 really.
Furthermore, languages and their implementations can be assigned to different performance personalities, from very fast (e.g C) to slow (e.g. Ruby). Go doesn't belong in the very fast bucket, it's one level below, hanging out with Java, C# and others.
The arguments regarding Oracle are frankly worthless, but if you want to go there, at least Oracle admit they're evil and restrict their evilness to price gouging on their products. They don't pretend to be some force of good while surveilling billions of people through devices, apps and web platforms like Google does.
It might be trendy or fashionable to poopoo on Java, but that criticism isn't driven by technical arguments.
I just feel like I've been lied to in University. Java was presented as the silver bullet in University. "It runs anywhere and models the real world". "In Java, you can't compare apples and oranges!". Turns out you can, if someone implements an AppleOrangeComparator. Great.
I'm just venting at this point, don't mind me.
What a strange comment. Python and Go are good at different things and you can use both.
I’ve seen plenty of projects switching to mypy and asyncio kicking themselves that they can’t just use something like Go.
I don't have to write for loops in Python. Go makes me.
I say this not to defend Go, but to encourage anyone creating a JSON-based API to at least test with a statically-typed language. It's too easy in a dynamically-typed language to create a field that is either a number or a list of numbers, but you just boned all the static languages in the process. Unless you know you're only talking internally, and you're never going to change to a static language of any kind, JSON APIs should generally be written in a subset of JSON that is static-friendly.
It's not that crazy of a requirement anyhow; it's not really a great plan in dynamic languages either because it complexifies the code there, too, just not as much. It's a bit of discipline, yeah, but it's good for you even in a purely-dynamic environment.
So I think we could both be right.
How do you measure this? By feelz?
Because I've been a programmer and tech lead for 15+ years, and C++ projects are always done faster than PHP ones.
PHP may be "easy", but better programmers with better tools will always win on development speed.
The power of a universally quantified interface cannot be underestimated!
In a theoretical Go:
func id<A>(a A) A
This only has one terminating, non-panicking valid implementation.
The lack of generics hasn't bothered me so far. You just find different solutions to the problem. Composition, interfaces, or if all else fails an empty interface{}. It's rare to really not be able to work around it. It does make it near impossible to build reusable and performant data structures in Go though. (say that you want to build your own heap or list, hashtable etc.) So that's annoying, but something that you rarely run into.
Bigger issue is that GO modules are still not ready for production since the ecosystem didn't catch up: https://github.com/golang/go/issues/24661