Over the long term I think Go is going to offer a much more sane environment for implementing high performance servers.
Over the long term I think Go is going to offer a much more sane environment for implementing high performance servers.
It also allows for running just the constructor in an area of already-allocated memory, if you're particularly crazy.
With that said it's hard to argue that Go makes concurrency easier at this point, which can certainly make it more useful for many of the types of problems programmers are seeing today.
It is difficult to implement multiple allocation strategies in the same application. In another time, I actually did quite a bit of work in this area: http://accu.org/index.php/articles/1308
Do you mean something like operator overloading where a given type has a different implementation of new that is used for it? Or a way to select different implementations of the global operator new at runtime? It seems to me that it should be possible for the latter to make it switchable, although the code would be inelegant to say the least.
AFAIK the former is possible as well, but the problem is that I think the type-specific operator new/delete have to be members of the type which means that you can't add it on later.
That's a great article btw.
That would be a gigantic change to the language, which I'm sure I don't understand the implications of.
After thinking about this some more, I'm going to stand by my original, even if poorly argued, comment that C++ doesn't really live up to the promise of "precise control" when it comes to memory allocation, and this is one area that can have a big effect on performance. C++ has all the overhead of a low level language, with a promise of control that when you really need it is often difficult to access.
The problem with C++ is exactly the opposite, it has too many options, which makes it difficult to create a global memory management policy, unless you define you own complete framework. Quite the opposite of what you said.
I won't opine on whether it actually is unnecessary.
Now you're correct that the standard library provided with C++ does not quite give you this same level of control. If you want node elements placed somewhere specific you either have to pick the right container, write a custom allocator (including rebind support so that any required container-internal elements also can use your allocator), etc.
But this is a complaint about a C++-only feature that C doesn't even provide.
On the very few times that C does provide an standard library function that will automatically allocate storage from the heap, it is even less customizable than the C++ equivalent. Normally your only option is something allocated with malloc(3), you're told to use free(3) when appropriate, and if you need something different you run into trying to replace malloc/free and friends and then somehow telling your custom malloc when to use custom behavior and when to use stdlib behavior. But you could do this in C++ code too.
Now you can certainly easily write your own library with better support for custom allocation/deallocation. Things like the Apache Portable Runtime, for instance, or glib.
But once you've bought into the idea of simply ignoring the language standard library anyways, you've bought into something else that you could do in C++ if you really felt like it were useful.
The problem with C++ is that the standard library makes it almost straightforward to do what you want and still be able to use standard containers without having to write your own, but we have to remember that we're talking about a problem that essentially can't even be spoken about in C. So it's not so much that C "doesn't have a problem", as that this problem couldn't even be expressed in C.
Are you trying to argue that C++ programs can't use custom allocators because of language restrictions? That's demonstrably false; Gecko and WebKit, just to name a couple of C++ codebases I'm relatively familiar with, use custom allocators everywhere.
The tricky part, to me at least, is when overloading. It's possible to overload new in a way that "new int" calls the original new, and "new int, foo" calls your overloaded allocator (foo could be an object used for the sole purpose of knowing which new to call, or it could actually be used by that new -- maybe it's a memory pool). That's easy enough to do. The surprise comes from the fact that while you can overload operator delete, it's a real pain to call the overloaded version (plus, of course, you have to remember which memory came from which version of new). Assuming you use "foo" to specify your overloaded new and delete, "delete p, foo" is a syntax error. You need to call something like "::operator delete(p, foo)". At least that was the case with C++03; I don't know if C++11 changed anything. Personally, I just overload new, but call a destroy() function instead of an overloaded delete.
I don't quite follow, who's stopping you from using sbrk(), mmap() and all the other low level allocation system calls if you really have to? AFAIK, many high performance applications have their own allocation mechanism. Furthermore, new/malloc is worlds apart from GC when it comes to precise memory management.
Now, to be fair, I have no experience implementing high performance servers. But speaking for games, GC gets in the way a lot. You can make it work by essentially avoiding allocation altogether, at least on systems where you can use tons of memory, but that's just a very crude workaround.
From a pure language perspective, nothing.
From a standard library perspective... it's probably more difficult. I won't say impossible, as the STL allocator concept certainly seems general enough to allow this, but definitely more difficult.
At any rate, Go certainly does offer some nice tradeoffs vs C++.