5 ms·
Sorry, but this is just goofy and bad. If you depend on copy-on-write functionality, then you need to use an API that is specced to guarantee copy-on-write fun
by jblow 10y ago
Sorry, but this is just goofy and bad.
If you depend on copy-on-write functionality, then you need to use an API that is specced to guarantee copy-on-write functionality. If that means you use an #ifdef per platform and do OS-specific stuff, then that is what you do.
Anything else is amateur hour.
If copy-on-write is a desirable feature, then as the API creator, your job is to expose this functionality in the clearest and simplest way possible, not to hack it in obscurely via the implementation details of some random routine. (And then surprise people who didn't expect copy-on-write with the associated performance penalties.)
This is why we can't have nice things.
- kccqzy 10y agoI think the author's point is opportunistic optimization. He didn't ask us to rely on this behavior.
- jblow 10y agoIf you don't know whether or not you are really getting an optimization, then how much do you really care? If you really care, then you actually profile your system and see what takes how much time, under which circumstances. The results of such a profile are almost always surprising. I guess this is a basic cultural difference -- almost nobody in the HN crowd really cares whether their software runs quickly; there is just a bunch of lip service and wanting-to-feel-warm-fuzzies, with very little actual work. In video games (for example) we need to hit the frame deadline or else there is a very clear and drastic loss in quality. This makes this kind of issue a lot more real to us. If you look at the kinds of things we do to make sure we run quickly ... they are of a wholly different character than "guess that calloc is going to do copy-on-write maybe."
- kllrnohj 10y agoAt the same time why would you ever opt to malloc & memset instead of calloc? calloc might have clever optimizations, whereas malloc + memset won't. Intentionally choosing something slower, buggier, and that requires more work on your part is moronic.
- astrobe_ 10y agoPredictability sometimes trumps optimizations. For a striking illustration of this, see timing attacks.
- jblow 10y agoExactly. I would avoid using calloc simply because I don't know what it actually does.
- firethief 10y agoThe implementation details of malloc aren't specified as part of its interface either...
- jblow 10y agoWhich is why high-end games do not use generic system malloc; in general we link custom allocators whose source code we control and that are going to behave similarly on all target platforms. (In fact we go out of our way to not do malloc-like things in quantity unless we really have to, because the general idea of heap allocation is slow to begin with.)
- takeda 10y agoYou know what it does: The calloc() function contiguously allocates enough space for count objects that are size bytes of memory each and returns a pointer to the allocated memory. The allocated memory is filled with bytes of value zero. You should not care how it does it.
- zik 10y agoNeither copy on write nor size checking are specced as part of the calloc() definition. Here's the specification of calloc from the ISO standard: 7.22.3.2 The calloc function Synopsis #include <stdlib.h> void *calloc(size_t nmemb, size_t size); Description The calloc function allocates space for an array of nmemb objects, each of whose size is size. The space is initialized to all bits zero. Returns The calloc function returns either a null pointer or a pointer to the allocated space.
- jblow 10y agoYes, and that is exactly my point. The article says you should use calloc because it provides these optimizations. I am saying no, that's goofy, because it is not specced to provide these optimizations.
- caf 10y agoAn implementation that lets the size overflow and returns a pointer to a block that isn't large enough for "an array of nmemb objects, each of whose size is size" is not conforming with that specification. That specification gives the implementation exactly two options: return NULL, or return a pointer to a block of sufficient size.
- mannykannot 10y ago>Anything else is amateur hour. Such as writing the optimizing compilers that make it feasible for you to use C at all?
- jblow 10y agoI don't understand your reply. How is this not a non sequitur?
- sowbug 10y agoThe output of a modern C compiler is unpredictable in terms of performance. Yet mannykannot suspects you still use such tools. Please explain your inconsistency.
- et1337 10y agoEven if this weren't a fallacious argument, he's actually in the process of replacing Thekla's C/C++ workflow with a custom language called Jai.
- megabochen 10y agoIsn't Jai piggybacking on C?
- et1337 10y agoHe started with two backends. One generates bytecode for an internal interpreter, and this is still needed because all Jai code can be run at compile time. The other backend generates C code, but it's a temporary measure. He just added the LLVM backend: https://www.youtube.com/watch?v=HLk4eiGUic8 https://www.youtube.com/watch?v=HLk4eiGUic8
- megabochen 10y agooh thanks, I didn't see the last one :)
- AndyKelley 10y agoIgnoring the multiplication issue, I think once again it all comes down to communicating intent. If you want to allocate zeroed memory, use calloc. If you don't need your memory to necessarily be zeroed, use malloc. I'm agreeing with you here - if your intent is to have copy-on-write functionality, that's not what you're communicating when you use calloc. It's okay for an implementation to try to optimize given the constraints of intent, but I agree that if an implementation is doing something non-straightforward (copy-on-write in this case), that is a smell that perhaps the API needs to expose an additional layer.