8 ms·
Also memory-safe languages with GC allow for simpler API and design. That in turn gives more time to think on errors in logic.
by fpoling 6y ago
Also memory-safe languages with GC allow for simpler API and design. That in turn gives more time to think on errors in logic.
- erichocean 6y agoThey're simpler only if you could care less about performance. C and C++ are primarily used in situations where you do care about performance.
- saagarjha 6y agoThey do well in those contexts. They’re used in other places too, but generally with poorer justification and results.
- _ph_ 6y agoMemory safety and performance are not a contradiction, they are widely independant. Yes, some strategies like GC induce an overhead. But in the age of multiprocessor machines, this overhead gets very much reduced by parallel collection. And practice has shown, in programs with a lot of dynamic memory allocation, garbage collected languages often perform even better. There are different approaches, like memory safety by the compiler as Rust does it. And with "performance" in mind, you shouldn't forget, that most large C/C++ programs tend to use libraries to provide some amount of safety, but those libraries are of course adding some overhead too. Finally, the less time you spend on questions of memory management, the more time you have to write an actually fast program.
- dirtydroog 6y agoSorry, this is hand wavy nonsense. One counter example, we switched from Cassandra (JVM) to Scylla (C++). It was a win in terms of both query latency and infrastructure costs as we required fewer machines to handle the same load. As for having more time to write a fast program... that's funny. If you want a fast program on something JVM based you're pretty much going to be spending the majority of your time writing things in a way where the GC plays as little role as possible.
- _ph_ 6y agoSorry, this is hand wavy nonsense. One counter example, we switched from Cassandra (JVM) to Scylla (C++). It was a win in terms of both query latency and infrastructure costs as we required fewer machines to handle the same load. Sorry, this is not hand wavy nonsense. And what you are providing is called annectodal evidence. Also, your universe seems to consist only of the JVM as a memory-safe alternative to C++. Yes, there are a lot of bloated, badly performing programs implemented in Java. However this isn't a given. Yes, some design decisions for Java introduce the risk of bloat, but you can avoid them at much less effort (and risk) than memory corruptions and new features like the value classes are reducing the bloat quite a bit. But still, the JVM is extremely high performance, so for speed in surprisingly many cases, it often beats C++. Virtual method calls are just better optimizable at run time, the Java JIT creates excellent code and Java has some of the best garbage collectors, so at really dynamic memory loads, it beats any manual management by a wide marging. And of course, there is a whole world beyond Java as alternatives. Rust has been explicitly designed to excel at tasks C++ traditionally shines for, while giving your full safety.
- dirtydroog 6y agoThere is an open-source project by LMAX (a forex trading company) called Disruptor[1] that squeezes as much as possible out of the JVM. It's awesome. I ported it to C++ years ago when I wanted to learn about low-latency techniques. However, if you look at the code they need to actually break out of the JVM's safety net to get the performance they need[2]. I couldn't help but ask myself why they didn't just use C++, and when asked one of the devs did admit that their own C++ ports had an approx 10% performance increase (although this was ~7 years ago maybe) Rust is certainly interesting and it's on my radar. I wonder though, when it comes to having it in use in anger if its guarantees turn out to be over sold, just like the JVM's safety claims were. Time will tell. Edit: I tend to focus on comapring against the JVM because pretty much any framework you use on The Cloud is JVM based. I'm of the opinion that there are cost savings to be had if these were ported to more appropriate languages, hence the Cassandra vs Scylla comparison. The money saved was 'noticeable'. [1] https://github.com/LMAX-Exchange/disruptor https://github.com/LMAX-Exchange/disruptor [2] http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot-unsafe/ http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot...
- citrin_ru 6y ago> Yes, some strategies like GC induce an overhead. But in the age of multiprocessor machines, this overhead gets very much reduced by parallel collection. If you unlucky and given GC is not well optimized for given workload, then memory usage overhead can be huge. Just a few days ago had such problem with Go (HeapIdle grew until OOM). Go GC is less mature than Java GC, but Java GC is not free too - sometimes you need to spend a lot of time time to tune GC settings or to optimize code to avoid GC problems. In my case case it would be faster to use malloc/free than to spend time fighting with GC (looking for a workarounds). On average GC saves development time and allows to avoid memory management bugs, but in some cases overhead is big and developers have to spend more time, not less.
- _ph_ 6y agoI have not claimed that a GC is always faster. Indeed, having a GC enables some to write a totally bad performing program. However this doesn't contradict that fact, that in many cases a GC does not only not mean a slower program, but sometimes a faster program. Usually, you don't have to "fight" the GC. In situations, where manual management is vastly better, you do use object pools and preallocated arrays even in a language with a GC.
- thePunisher 6y agoThere are quite a few areas in software where determinism is a must, such as games, real-time and systems software.
- pjmlp 6y agoYes, for those there are real time GCs as well. https://www.ptc.com/en/products/developer-tools/perc https://www.ptc.com/en/products/developer-tools/perc https://www.aicas.com/cms/en/JamaicaVM https://www.aicas.com/cms/en/JamaicaVM One of the Java vendors acquired by PTC, Aonix, used to sell real time Java implementations for military deployments, including weapons controls and targeting systems. You don't want a couple of ms pause when playing with such "toys".
- thePunisher 6y agoSounds more like snake-oil to me.
- fetbaffe 6y agoBoth C and C++ have zero built in knowledge about parallelism, so in a modern world where most things are parallel and asynchronous I don’t agree at all with that statement.
- sigotirandolas 6y agoBoth C and C++ have had a concurrent memory model and threads in the standard library for a decade now. And POSIX threads which are pretty much the same thing have been there for a quarter century on *NIX.
- fetbaffe 6y agoSure, there are libraries for concurrency, but there are no language constructs like in other languages.
- cogman10 6y agoWhat do you mean by language constructs? As in, a `synchronized` keyword? Or are you thinking along the lines of `async` `await`? If you mean the `synchronized` keyword, then correct, they don't have that. Most languages do not have that concept. C++ does have mutexes and has had them since C++11 (nearly a decade). C++ also has as part of the language spec the concept of threads, again, there since C++11. If you meant co-routines, then C++ just added them with C++20. Or do you mean something different like green threads (ala go)? C++ certainly has concurrency constructs and has been expanding them since C++11.
- fetbaffe 6y agoLike Gos goroutines or Erlangs processes. And more of message passing. C++ has added many of these things later on in the standard library, bolted on afterwards.
- erichocean 6y agoIf you think that using libraries to do things in C++ means they are "bolted on", then you don't understand C++. The entire design of C++ is to enable efficient libraries for these kinds of things to be built. And it does, and has, and will continue to for decades more.
- SomeoneFromCA 6y agoThe real point of using C and (less so, but still) C++ is not to have the ultimate performance, but to have ultimate control over the program execution. Garbage collection and real-time code are not compatible, because GC introduces random, unexpected stalls in the program flow; even simple reference counting can be harmful, if the last reference get eliminated in the wrong time, and creates a cascade of deallocations.
- pjmlp 6y agoThen using C and C++ is a mistake, because there isn't an ultimate control about how memory allocator interacts with the OS. So much that in the 90's there were vendors that could make a business out of selling specialized memory allocators.
- SomeoneFromCA 6y agoReally? What about an OS kernel code? How does "it's allcator" interacts "with the OS"? And what these allocators were written in?
- pjmlp 6y agoUsually in a mix of Assembly and whatever is used in OS systems implementation language, not necessarily C. https://inf.ethz.ch/personal/wirth/ProjectOberon/Sources/Kernel.Mod.txt https://inf.ethz.ch/personal/wirth/ProjectOberon/Sources/Ker... The malloc() exposed in a ISO C standard library implementation isn't necessarily related to whatever means the OS does memory allocation.
- pjmlp 6y agoNowadays, back in the 80's and early 90's no sane developer would used them on 8 and 16 bit home platforms if they cared about performance. What C and C++ have going for them is 40 years of investment in optimizing compilers, to detriment of other languages, and abuse of UB in optimizers. Now with shared compiler backends becoming a mainstream thing across most OSes, that advantage is getting thinner.
- Too 6y agoIn many ways yes but not always. After writing lots of C++ and then going back to managed world I often find cases where the opposite is true. Questions like "will this be mutated?" or "will the library shallow copy, deep copy, or hold a reference to this object?" are very hard to answer in most GC languages.
- fpoling 6y agoI can agree with that when comparing with plain C code. But reference-counting in C++ and Objective-C leads to exactly the same problem as with managed code. What saves C is that reference-counting there leads to a lot of boilerplate and bugs. To avoid that one needs very clear ownership model.
- Gibbon1 6y agoI saw an essay by someone discussing going back to C and eschewing leet pointer and decentralized memory allocation for a system of centralized memory allocation and passing handles[1] instead of pointers. Which appeared to make most of the memory safety problems go away. [1] handles could be unboxed to expose a pointer. But unboxing had machinery to detect and trap on bad handles
- fpoling 6y agoThat reminds me about early Fortran where everything was statically allocated including local variables and function return address. To simulate data structures one used arrays of various dimensions. Effectively array indexes where handles. This was not memory safe as there were no bounds checks. But add those when the compiler cannot eliminate them, and one gets fast and memory safe language. Edit: that static allocation was essentially a centralized store. Everything repeats itself.
- fetbaffe 6y agoYou probably mean this essay https://floooh.github.io/2018/06/17/handles-vs-pointers.html https://floooh.github.io/2018/06/17/handles-vs-pointers.html
- kzrdude 6y agoIt's so easy to create thread safety related bugs in C# because it's easy to use parallelism and there are no checks for threading issues.
- fetbaffe 6y agoCorrect, that is true for any language where you deal with raw threads, managed or unmanaged. That tells us that we should avoid using raw threads and instead use some other API to achieve parallelism.
- nicoburns 6y agoIt's not true in Rust. In Rust, objects cannot be concurrently accessed from multiple threads unless they are explicitly marked as thread-safe (with the Sync trait), or wrapped in a a Mutex, which ensures that the safety variants are upheld.
- fetbaffe 6y agoRust does not compile if you don't use the techniques you described?
- ansible 6y ago> Rust does not compile if you don't use the techniques you described? Yes, exactly. https://kkimdev.github.io/posts/2019/04/22/Rust-Compile-Time-Memory-Safety.html https://kkimdev.github.io/posts/2019/04/22/Rust-Compile-Time... Of course, you can bypass this by using 'unsafe' code, where you are explicitly telling the compiler that you have manually verified Rust's safety guarantees. This is why a significant portion of Rust's community gets agitated with (possibly unnecessary) use of 'unsafe' in popular libraries.
- fetbaffe 6y agoThen I stand corrected and applaud the creators of Rust for haven taken these measures for writing thread safe code, because it is supereasy to get threading wrong, even for the most experienced developer.
- zetafunction 6y agoMy personal experience from reading code that uses Chromium's C++ garbage collector is that that's often not true. While there might no longer be use-after-free errors, it's also no longer possible to make assertions like "object X must outlive Y" because object Y could be referenced arbitrarily and kept alive longer than expected. To get around that, objects might have an explicit shutdown step. But shutting down a large graph of objects is often fraught with peril, especially when that work can span multiple processes.