5 ms·
Why is C inappropriate for applications work?
by daymanstep 3y ago
Why is C inappropriate for applications work?
- TillE 3y agoTry writing a generic, reusable data structure in C. It's agony.
- bluetomcat 3y agoYou don’t need to write generic and reusable data structures in C. You write a data structure suited for the problem at hand, which often means that it’s going to be simpler and more performant because of the known constraints around it.
- grumpyprole 3y agoIt could be more performant because of the known constraints around it, or it could be an ad-hoc, informally-specified, bug-ridden, slow implementation of half of some data structure. At least with a generic and resuable data structure you have a known reliable building block. Again, performance over safety.
- commonlisp94 3y ago> It could be more performant No, it almost always is. The designers of a generic library can't anticipate the use case, so can't make appropriate tradeoffs. For example, compare `std::unordered_map` to any well written C hash table. The vast majority of hash tables will never have individual items removed from them, but a significant amount of complexity and performance is lost to this feature.
- SubjectToChange 3y agoNo, it almost always is. A library author can spend ridiculous amounts of time refining and optimizing their implementations, far more than any application programmer could afford or justify. The designers of a generic library can't anticipate the use case, so can't make appropriate tradeoffs. This is definitely not true. Take C++ for instance, not only is it possible to specialize generic code for particular types, but it's absolutely routine to do so. Furthermore, with all sorts of C++ template features (type traits, SFINAE, CRTP, Concepts, etc) even user-defined types can be specialized, in fact it's possible to provide users with all sorts of dials and knobs to customize the behavior of generic code for their own use case. This functionality is not just a quality-of-life improvement for library users, it has profound implications for performance portability. For example, compare `std::unordered_map` to any well written C hash table. std::unordered_map is a strawman. There are a plethora of generic C++ hash tables which would match, if not soundly outperform, their C counterpart. Also, even if we blindly accepted your claim, then how do you explain qsort often being beaten by std::sort or printf and its variants being crushed by libfmt? What about the fact that Eigen is a better linear algebra library than any alternative written in C?
- commonlisp94 3y ago> A library author can spend ridiculous amounts of time That's true. But simply having knowledge of the goal and a few simplifying assumptions can beat all the optimization in the world. In other words, a polished sub-optimal approach isn't as good as just having a better approach. `std::unordered_map` is heavily optimized, but can't make any tradeoffs because it's a general tool. > plethora of generic C++ hash tables which would match, if not soundly outperform, their C counterpart. Post one. > not only is it possible to specialize generic code for particular types, but it's absolutely routine to do so. Yep, it can do type base specialization, not application based specialization though. That requires a programmer. > how do you explain qsort often being beaten by std::sort a standard library C function often cannot be inlined to remove the comparison function pointer call, whereas std::sort trivially can. If you wrote one yourself for a particular problem, it would not have this issue. This is actually a great example of where C excels because the choice of sorting algorithm so much depends on the kind of data you are sorting. Let me be clear about my claim: tailor made solutions to each problem will almost always be faster than generic solutions. Do you really disagree with that? If you want to argue that maybe it's not productive to work that way, that's a different argument.
- SubjectToChange 3y agoLet me be clear about my claim: tailor made solutions to each problem will almost always be faster than generic solutions. Do you really disagree with that? I disagree with it in the sense that I disagree with the statement "A human will always be able to write the same or better assembly than a C compiler, because humans can learn the compiler's tricks and make optimizations which the compiler is not allowed to make." It's a true statement, but it's so detached and irrelevant that it hardly matters. Generic code has proven itself time and time again, even Go caved in and supported it.
- commonlisp94 3y agoThe assembly example isn't a good comparison. We have compilers that can generate a lot of assembly tricks most programmers wouldn't write. We don't have a way compiler that can analyze the logical constraints of a programming problem and simplify the data structures in the library. > Generic code has proven itself time and time again, even Go caved in and supported it. I'm not saying anything against the language feature generics. There is plenty of use for them even in a self contained code base.
- mcguire 3y agoFor one example, https://github.com/tmmcguire/rust-toys/blob/master/alternatives/anagrams-hash.c https://github.com/tmmcguire/rust-toys/blob/master/alternati... is a program that mmap's an anagram dictionary file and builds a fast-n-dirty hashmap dictionary over the file data. It took about an afternoon to write and was pretty decent. https://maniagnosis.crsr.net/2014/08/letterpress-cheating-in-rust-0110-part-2.html https://maniagnosis.crsr.net/2014/08/letterpress-cheating-in...
- snovv_crash 3y agoUnordered map is a known design issue, on the same order as std::vector<bool>. C doesn't even have std::vector<int>>
- NavinF 3y agoThat must be why every C project has its own string, dynamic array, hashtable, etc. It's definitely more performant to have several different implementations of the same thing fighting for icache
- overgard 3y agoTo be fair, most C++ projects (outside of embedded and games) use STL for string/dynamic array/hashtable, and while that standardization is certainly convenient I'm not sure STL is generally faster than most hand written C data structures, even with the duplicated code.
- commonlisp94 3y agoIt's a nice thought, but in practice C binaries are orders of magnitude smaller than any other language. Also compilers make that tradeoff for inlining all the time.
- mcguire 3y agoEntirely true. Unfortunately, that comes at a cost of programming time and effort and a decent amount of risk.
- StillBored 3y agoAgony might be a bit much, and i'm not trying to defend C because this is one of the strong reasons for using C++/STL... But, generally one should just reach for a library first before doing a complex data structure regardless of language. And for example, the linux kernel does a fine job of doing some fairly complex data structures in a reusable way with little more than the macro processor and sometimes a support module. In a way the ease of writing linked lists/etc are why there are so many differing implementations. So, if your application is GPL, just steal the kernel functions, they are reasonably well optimized, and tend to be largely debugged, are standalone, etc.
- sn_master 3y agoTry doing the same in Go and it's even worse.
- commonlisp94 3y agoThat's writing some other language in C syntax. You use arrays or you write a specialized version for the use case.
- memefrog 3y agoWhat does that have to do with writing an application?
- grumpyprole 3y agoThe technical arguments should be obvious, e.g. spending ones complexity budget on manual memory management and avoiding footguns. But one amusing anecdote is that the open source GNOME project founders were so traumatized by their experience building complex GUI apps in C (already a dubious idea 20 years ago), that they started building a C# compiler and the Mono project was born.
- seabass-labrax 3y agoIn 2023, you'll be hard pushed to find a GNOME application actually using C# and Mono. The vast majority of GNOME components are written in C, with a large number of them written in Vala and some in Rust and JavaScript.
- grumpyprole 3y agoIt was indeed a big yak to shave. Cloning a Microsoft technology probably wasn't a good idea for OSS adoption either.
- seabass-labrax 3y agoI'm sure; there are still threads that come up from time to time in GNU circles about whether Mono is actually FOSS (TLDR: it is), in which those of a more paranoid personality allege an EEE attempt by Microsoft. If this were the case, Microsoft clearly did not succeed even without Java as a legitimate competitor! Interestingly, Mono has had most success from its use in the Unity game engine.
- memefrog 3y agoYou don't spend "complexity budget" on manual memory management. Manual memory management is much simpler and easier than trying to manage complex arrangements where things are being allocated and deallocated all over the place, all the time. Gnome programs are largely still written in C, but it isn't actually C. Not really. It's glib, which is almost a whole new language written on top of C. It's its own little world and it's not a good world. For example, it calls abort() whenever it fails to allocate memory.
- mcguire 3y agoThe short answer is that C makes it easy to do things that you probably shouldn't ought to be doing. (The the answer to the opposite, "what work is C appropriate for?" is systems and embedded stuff, where doing-things-you-probably-shouldn't is largely the name of the game.) Another answer is that C doesn't have much in the way of guardrails; in a world where programmer time is much more expensive than machine time, guardrails make programming much faster.
- memefrog 3y agoEvery language makes it easy to do things that you probably shouldn't be doing. I don't know how many times I've seen naive accidentally-quadratic string handling code in high level languages, for example. Your answer is just buzzword after buzzword. What makes C bad for writing applications?