HNHacker News
TopNewBestAskShowJobs

jstimpfle

4,224 karma · joined May 21, 2015

http://jstimpfle.de
submissionscomments
jstimpfle··on Understanding the Odin programming language
> Nope, destructors have nothing to do with this and this was never something you mentioned before. If it was you could show it with godbolt.

How about you simply Ctrl+F for "build time" or "compile time" and admit you have been lying, have been extremely adversarial, and have been incredibly lazy?

> Show me. They are just functions, usually one or two lines.

Isn't it strange that I'm now creating a godbolt containing absolute C++ basics as a youtuber personality fangirl, since apparently I'm only repeating stuff I don't understand, which has to be why I can't express myself and provide evidence?

It is beyond me how you don't seem to know what I'm talking about, but here you go... This should provide reasonable evidence of the lack of ergonomics when using C++, and how problematic this class stuff is from various technical standpoints.

As you mentioned, in C style programming, we could instead simply forward declare a struct, than forward declare some functions. One line for each. Good header hygiene. Clean. Done. But noo, this is C++ and we can't have straightforward code and low coupling.

Full link: https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaP...

jstimpfle··on Understanding the Odin programming language
> Now we're firmly into the insults phase.

We have been from about your 2nd comment on.

> "I haven't considered that"

Considered WHAT?

> I repeated what was in the comments. This is another example of claims without evidence, you realize that right? You didn't explain it and how I was wrong, you just said "no, nu uh".

I was merely giving you a second chance to notice by yourself that the Sleep-Code in question is code that is being debugged, not part of this project. But instead of double checking, again you've been relentlessly continuing on your trajectory.

You've ended up furthering your wild accusations without entertaining the possibility that I might be not completely wrong on all fronts, and you might be only half right (or less).

> Are you talking about build times now? What happened to all the stuff about being terrible for the APIs and so toxic for the whole system that you can't write anything in godbolt?

It's one of the topics, one of the manifestations of the systemic issues I was talking about, if you had paid any sort of attention.

> Finally an explanation of some sort. Too bad this isn't true. Do you know that the implementation can be in a compilation unit just like C?

You are still not understanding? I gathered you seem to be a game developer of some sorts but you don't understand the simplest basic facts about C++?

Please show me how you can call a destructor in C++ without seeing the declaration of the destructor. (I mean calling it directly of course, since calling it indirectly would refute your claim that a destructor is needed -- since you can't have an arbitrary intermediate function called automatically by RAII).

Or show me how you can see the declaration of the destructor without seeing the definition of the class.

JUST DO IT. SHOW THE EVIDENCE. DONT TALK.

jstimpfle··on Understanding the Odin programming language
> Your own project

First, tone it down a little please, would you? It's not "my project", what is wrong with you?

> ... has plenty of the bugs that destructors and contained memory allocation avoid. Raw heap allocations, raw mem copies etc. https://github.com/EpicGames/raddebugger/issues/735 . Here's a complex memory cleanup race condition that's 'solved' with a sleep function. https://github.com/EpicGames/raddebugger/issues/855

Now you've provided two links and they contain little evidence to back up your claims. Linking issue 735 suggests that you've misunderstood the part about a "Sleep", which evidences either your lack of capacity to grok the context of the issue, or evidences your unhealthy adversarial stance (I strongly suspect the latter).

> You don't give any explanations, they are just claims, do you understand that? Do you know what evidence is? It's the thing you say you can't provide.

You haven't been able to take the most obvious uncontentious claim from me. But if I'm not explaining as you say, what are YOU doing?

Are you seriously too stubborn to accept that exposing a destructor (or any other method) in a header file requires exposing the class's definition (private method declarations including signatures, include internally used headers for internally used data structures, which again have methods, which have dependencies...) in C++? And when any of those not-real-dependencies changes, you have to rebuild everything needlessly? Are you somehow mentally unable to see how long compile times can subtly degrade a project over time?

Because I didn't need any youtuber personality to find that out for myself. And for some humility, the fact that I was able to see that suggests it's not particularly hard to find out.

> Why don't you link something besides a name of a big C project and explain it. The idea that someone making a project in C somehow means other features and tools are terrible isn't even logic. That would mean that one project in a language from the 70s would negate every garbage collected and dynamically typed scripting language.

And also I didn't claim it, you fantasized it and I can't help but ridicule you for having such wild ideas. To make such claims you would actually have a closer look at a project.

> By your own logic the fact that https://github.com/chromium/chromium has 1.7 million commits to your project's 4,385 means that modern C++ is more than 380 times as effective.

How is that by my own logic? But please accept that this is the work of mainly 1-2 persons, and compare _hours_ of build time (35 MLOC) to 3 seconds of build time (300K LOC).

> You think that somehow something simple like automatically running a function you have to run anyway is a problem, it's nonsense.

You are misrepresenting what I've said so badly it's not funny anymore. I've said multiple times that maybe this function shouldn't even exist. And even if the function has to exist, maybe it shouldn't be coupled so hard, at a language level, with the actual state & logic definitions. I did provide reasons why I've perceived the coupling to be an architectural problem.

I would be very open to a discussion when this can or can not be a serious problem and what are possible tradeoffs and points in the design space. It wouldn't make me feel bad and wouldn't take away from my claim that there is actual evidence for the issues being discussed. But with a person like you, that's not possible.

> That's a matter of dependencies and doesn't have anything to do with destructors.

I've explained multiple times why I think it does. If you want a destructor declared in C++, you have to give the full class definition.

> Now we're to the "I don't like how you're saying it" part of the no evidence playbook. This happens when someone can't admit that they don't have any information and they can't believe that people won't accept them repeating claims as evidence.

No, it happens when I can't believe how you haven't managed to stop talking down on me instead of making an effort to be anything other than an annoying adversary. That's all.

> I think it's time to admit to yourself that you have accepted some internet youtuber personalities as a religious belief and that you haven't questioned these beliefs with thoughts that go beyond the claims of the cult.

I think it's time for you to shut up. You are providing zero evidence for your baseless (even counter-factual) accusations towards myself. What you say makes ZERO sense.

jstimpfle··on Understanding the Odin programming language
> If you can't demonstrate it with actual source code then you just have claims and no evidence.

I can NOT demonstrate it in a tiny godbolt because the effects I am talking about don't apply on a micro-scale.

I CAN demonstrate it with actual source code, but you are unwilling to look it up. You are disagreeing without making the tiniest effort. Not being willing to make an effort by itself is fine. But you're being contrarian in the worst and laziest way.

Do you not understand the concept that I can't explain the world to you from the ground up? You say no to everything without trying to understand it. Your "rebuttals" indicate you're not willing to follow me in the slightest and you reject even the most common lore (for example the thing about C++ class features (destructors, methods...) leading to exposure of internals in public headers, leading to every TU including the world). Or you are intentionally trolling me. You are being uncooperative and you're the single worst interaction I've had on this platform. Now please get off my lawn.

jstimpfle··on Understanding the Odin programming language
> You bringing up something unrelated doesn't mean anything just because you keep bringing it up.

It's NOT unrelated. It is a real world demonstration of the simplicity possible by custom modeling of allocation and lifetime concerns instead of buying into a fixed scheme set by a language.

> There is one singular question and you seem to think it's absurd to answer it and not veer off into a hundred different directions about unrelated projects and your favorite influencers instead of being able to focus on it.

You made me do it by repeatedly talking down on me in a condescending tone, when I tried to keep it simple and referred to external sources. What the heck. You want a simple reply. I cannot give you one, except for, "RAII is this simplistic solution that makes the language complicated while still being by far not enough to handle interesting use cases. It has turned out to be wrong and misguided every time I've tried to use it, and here are a million examples why".

> If it automates things why would it have a typing cost? That makes zero sense.

It automates generating boring boilerplate code (which is good on one hand but it doesn't reduce the semantic complexity AT ALL, so actually it just promotes doing the wrong thing by making the wrong thing easier). To generate the boilerplate code it requires type machinery. What doesn't make sense about this?

Why don't YOU start telling ME?

>> it will "infect" your codebase,

> How? It can be used or not.

To use it e.g. in containers, you then have to also use it for the things contained -- e.g. unique_ptr<T> or vector<T> or whatever, you will have a bad time if you don't model T's destruction with a C++ destructor too. Also you can't just insert random manually managed objects within a group of RAII managed objects, because that will break the "reverse destructor calls" assumption.

It's a viral thing.

>> It will break modularization of your codebase, leading to subtle but substantive degradation.

>These are strange claims, they don't have any evidence

I explained why: internals have to get moved to public API in practice. This is almost the definition of breaking modularization.

>> This is part of what leads to long compile times

> No it isn't, it's running the same function at the end of a scope. Where are you getting this idea? Templates you could say this about, but a simple concept has nothing to do with it.

Why are you being so stubborn? Destructors (like other methods) practically require classes to be fully exposed (that you can protect them with silly public/private/protected specifiers doesn't change the fact they're exposed), requiring includers to pick up transitive dependencies. That results in huge amount of included code per TU, and results in far too many TUs that have to be rebuilt on incremental changes.

This is a very well known thing.

> "Temporal coupling" doesn't make any sense, you have to deallocate memory anyway, why would it be any different to not have to write the line explicitly?

Why doesn't it make sense? In practice, allocation is coupled with initialization and destruction is coupled with deallocation. It's literally in the name, Resource Allocation Is Initialization. You can work around it, sure, but it's painful and literally just an escape hook to escape the very thing you're arguing for.

> If you want to have a real explanation, especially to yourself, you should probably show a scenario on godbolt or something like that. It really seems like people have led you down a path that doesn't make sense and you haven't gone back and tested it yourself.

ON GODBOLT? Are you kidding me? I've been arguing all day how RAII is a simplistic rigid mechanism builtin to a language that will lead to slow creeping systemic issues, in practice, in my experience, in larger and more complicated systems, especially with performance and abstraction requirements. I CAN NOT explain to you what sucks about it in a godbolt. You can use RAII fine for simpler programs. You can use it fine in a godbolt. You can use it fine for leetcode. etc.

Asking for a Godbolt example of architectural coupling is like asking for an assembly listing proving that a database schema is hard to migrate.

jstimpfle··on Understanding the Odin programming language
> If this is so simple

I _never_ said it was simple. It is actually very subtle, which is also why I made many attempts at integrating RAII style programming for many projects. RAII works for applications with simple lexical and local lifetimes and ownership. But it's not a good fit for more complex systems with more global and coordinated allocation and ownership patterns in my experience. The concept of ownership and lifetimes encoded by it are too simplistic (when in reality, these terms are not even well defined), as is evidenced also by the various extensions to the machinery over the years (such as exceptions, move/copy asignment/constructors, rvalue references, unique_ptr, shared_ptr, trivially_copyable, trivially_destructible...) that contributed to form the probably most complex and hard to read language out there.

A big part of the problem is that there is no easy migration path from a smaller program with simpler lifetime and ownership patterns (relying on RAII) to a larger program with much more complex patterns (gradually discarding RAII/reworking allocation and ownership strategies). It is hard to refactor stuff that happens "between the lines" as part of the language rules, besides being hard to read also (unless the patterns are trivial).

>> raddebugger

> In what world does this have anything to do with anything being talked about? You need to focus.

Like, in the world where I've referenced this in 3 of my 4 previous comments, as an example of a serious application built without RAII, which leans heavily into arenas, resulting in extremely compact and fast code?

> Why don't you say what it is they actually have to say about destructors?

Is this an exam? I referenced these guys instead of regurgitating because they can do it better, the content is out there, and I hardly could do justice to the matter in a few lines. If you need a couple more catchy but badly written phrases, it's that RAII comes at a large cost in terms of typing, and even though it automates some painful code, it will "infect" your codebase, requiring an all or nothing approach or you're actually back to manually managing memory, in fact you can not insert manual frees between arbitrary RAII destructor calls.

It will break modularization of your codebase, leading to subtle creeping degradation. It breaks separation/abstraction of memory management from data representation across module boundaries. This is part of what leads to long compile times that are very common with C++ code bases, as typically type definitions (including any internal matters and their dependencies) will be fully exposed in the headers instead of hidden in implementation files.

RAII adds temporal coupling between memory allocation and data lifetimes, which is a disadvantage as you scale your codebase up. And under the hood, RAII is still fundamentally built on a model of individual object thinking, allowing for the typical classes of memory bugs, like use-after-free if you do tree type or even spider web type object graphs (which sometimes is just what you have to do).

Separate allocation approaches on the other hand allow for better modularization and abstraction, and allow to handle allocation more centrally instead of cluttering allocation conerns across all types of a codebase.

That's it finally for me, this is a rushed summary and as said other people have explained this much better. I've also had enough of your condescending replies. Have a good day.

EDIT: if you are looking for text content instead of video rants, checkout https://www.dgtlgrove.com/p/untangling-lifetimes-the-arena-a... as an example of a well written treatment in this area. But really, these 3 guys (besides others) are all very good at explaining that stuff in videos too, just use google please and make up your own mind.

jstimpfle··on Understanding the Odin programming language
Iterator invalidation is absolutely a huge deal for many datastructures in practice. From an ergonomic standpoint alone it makes a huge difference. 10 years ago I argued the opposite, but juggling indices simply is not fun. Replacing pointers with indices can be useful but it's not a good default.

You are also ignoring bookkeeping overhead and fragmentation that comes with individual allocation.

The important difference between arenas and RAII as far as I'm concerned is that the former allows exploitation of allocation patterns, like stack shaped allocations, which can reduce complexity in a meaningful way, requiring no cleanup code at all. RAII on the other hand does not give you that -- it is just a disciplined system to automate some code, but the complexity is still fully there, and a lot of constraints are put on the types and your internal organization in order for RAII to work.

Arenas are quite a good fit for frame memory in graphics programming, and they do not waste memory there if done right. On the contrary they probably save some, but that's not the point here. We're typically talking about a couple megs per frame at most, which is spare change.

Some people, like Ryan, have managed to apply arenas more widely, but personally I am more in favour of a varied mix, and don't mind a bunch of manual code either, but I definitely like to control allocation more closely compared to what e.g. malloc/free allow. I like to keep objects in their specific subsystems. I have written my own block allocator to do this. Now allocation does not show up anymore on my profile almost at all, it's <<< 1÷ of my CPU usage even though I recreate tens of thousands of objects per second. Also syscalls are ~zero as long as memory usage is roughly the same from frame to frame.

As I said elsewhere, performance and correctness/clean modelling always go hand in hand. The correct model must allow for the right level of performance, or else it's not the correct model.

jstimpfle··on Understanding the Odin programming language
I told you what to check out. I'm not regurgitating this, I've done it often enough.

Have you spent 1 minute cloning the raddebugger, 3 seconds to build it, and 0.5 seconds to launch it, to be convinced that it is a solid product?

> It's you and the three guys you are fans of against the entire world of systems programming

What is this "entire world of systems programming"? From what I've seen, there are very few accomplished experts who would disagree a lot with what e.g. Jon/Casey/Ryan have to say.

What are you working on?

jstimpfle··on Understanding the Odin programming language
> So lets hear them.

There are few people delivering more in-depth explanations of their claims, like literally thousands of hours of content. You can just look it up. If you disagree, please disagree. Personally I find what they say articulates almost 100% of my independent experience. And I do systems programming in C++ full-time (file systems / desktop app infrastructure). Personally I've made at least 9 serious attempts of building robust and maintainable systems on top of C++ features like RAII and templates and have always returned to simple straightforward C-style code. And I've had to work many times with existing C++ codebases that had bought into these features, and it always seemed like a giant waste of time, a way to add more spaghettis to a hot mess. And also, any technically convincing C++ codebase I've seen always seemed to make only very light use of C++ features. Not going to argue more here.

> Who cares? They have nothing to do with anything

Quite the opposite, it's a third person from the same circle making the same kind of claims (there are more persons), who have, contrary to what you say, actual evidence to back up their claims. You could just go ahead and check these works out yourself and see if it convinces you that the methods they claim to be better are actually better.

jstimpfle··on Understanding the Odin programming language
> This is the statement that no one seems to be able to back up.

Actually there are many explanations of systemic issues arising from reliance on RAII. Both Jon and Casey are very good explaining the matters.

> Instead you start talking about a third person making a debugger for some reason as if the solution to appealing to authority is more appealing to authority.

A third person (already mentioned in a parent comment), who is creating an extremely snappy and powerful debugger using those exact approaches under discussion.

jstimpfle··on Understanding the Odin programming language
> the main reason to choose arena allocators is for correctness, not speed. They make similar time/space tradeoffs to garbage collectors in that they grant higher allocation throughput in exchange for more memory usage.

I'm not quite sure, do you mean arenas are slower, and use more memory, compared to standard vector-style allocation (which does a lot of copying, iterator invalidation, and wastes like 0.25x memory on the average), or compared to individual malloc/free (which does a lot of book-keeping work and wastes book-keeping memory)?

jstimpfle··on Understanding the Odin programming language
You must mean confusing achievements in the area of creating large maintainable and performant systems on the one hand, with achievements in the area of creating large maintainable and performant systems on the other hand?

And let me incude Ryan Fleury here who graduated from Casey-school with honors, he is maybe the most impressive programmer I know. His work on the raddebugger is outstanding.

jstimpfle··on Understanding the Odin programming language
Correctness (the kind that comes from simplicity and maintainability) and performance pretty much always go hand in hand. The only additional ingredient to "bridge the gap" between the two is detail.
jstimpfle··on Understanding the Odin programming language
Apparently you're the school of dismissive person who can't even be bothered to look up their technical achievements.
jstimpfle··on Zig: All Package Management Functionality Moved from Compiler to Build System
If you use a JSON parser, URL parser, configuration file parser, async framework, and so on, maybe you have other problems. Not that I don't know these project or don't have to work on them, but I don't think it matters what JSON library or URL parser library or async framework you're using.

The actual problem is the complexity coming from the choice to use these things at all (and thinking they should play any important role in the system at all, instead of being entirely replaceable), which means to do anything useful you have to go through a lot of abstraction, which makes everything tedious and buggy and hard to fix.

jstimpfle··on Zig's new bitCast semantics and LLVM back end improvements
> You do the endianness conversion

Exactly my point.

jstimpfle··on Zig's new bitCast semantics and LLVM back end improvements
You may have never done socket programming, or do you use wrapper libs in Zig? Because you have to send the kernel big endian port numbers for example.

What do you do if you program a kernel in Zig, or just generally do low level networking?

My point is to refute the statement that everyone has agreed to little endian, and so there aren't use cases to want to do conversion. Programs do not exist in a vacuum, most programs do not.

jstimpfle··on Zig's new bitCast semantics and LLVM back end improvements
Does that mean there are no file formats thatbuse big endian? And network byte order isn't a thing?
jstimpfle··on Vulnerability reports are not special anymore
It's not as black and white as you claim. 99% is obviously much better than 0%, and 99.999% would be an exceptional, unheard-of improvement. In most software projects, this would find ALL bugs.

And most "memory safe" languages are not all that memory safe. Or they need escape hooks.

EDIT: To be clear it's not AT ALL black and white. You have drunken too much of the type safety kool-aid.

jstimpfle··on Vulnerability reports are not special anymore
It might just mean the opposite. Unergonomic and/or slow memory safe languages might not be needed anymore at some point, because LLM can check for reasonable programming patterns and can do some amount of vulnerability checking upfront. But seriously the first point -- as long as you keep to a known set of reasonable patterns (much larger set than the sets accepted by restrictive and cumbersome type systems), memory unsafe languages are actually pretty safe, and the code remains easy to understand, easy to maintain, and performant.

Already today, in my experience, widespread models like Claude 4.6 or 4.8 can quite reliably find some concurrency bugs that are easily missed by humans.

jstimpfle··on Ask for no, don't ask for yes (2022)
This is one of the articles where I'm immediately grateful to the author to have written it down. Very good and easy to pick up point, actionable advice. I would just slightly modify it, don't create a time bomb. "I would like to... until date XY" should achieve the same effect -- not inviting bikeshedding or delaying action, sending "I got this" -- without pressurising anyone else for taking a decision or too much responsibility.
jstimpfle··on Code duplication is far cheaper than the wrong abstraction (2016)
Code duplication is the wrong abstraction too -- unless it's not really code duplication but code that only happens to be similar for some really "unstable" reason.
jstimpfle··on Project Valhalla, Explained: How a Decade of Work Arrives in JDK 28
But why are there so many of them?
jstimpfle··on Project Valhalla, Explained: How a Decade of Work Arrives in JDK 28
> There’s nothing wrong with having non-normalized representations

There is a lot wrong with that: complexity, bloat, and slowness.

> But now client code can distinguish 2/3 from 4/6 using ==

That's a great way to obfuscate code. Not a good idea. The right way to do the comparison is, just make a function called CompareRational().

jstimpfle··on Project Valhalla, Explained: How a Decade of Work Arrives in JDK 28
OOP isn't just about values vs objects. Yes, the idea that everything needs identity is a big part of the problem. But another big problem is the idea that the implementation and representation of types should be hidden by default. The mindset that there isn't a known and useful data representation for a given type. That everything is done by methods parameterized by a type. It's a misguided idea. There is a place for objects and implementation hiding. But the idea that this should be done on a type granularity is a complete and utter failure.

To see why, consider that to do any useful work, data from different objects (also from different types) has to be combined. To be able to do that in the OOP framework, the encapsulation has to be unwrapped. That's why Java code is littered with getters and setters that don't do any useful work at all, they just make it too painful to get any real work done.

Again, there is a place for objects and implementation hiding, but it's at the highest levels of an architecture where different components get integrated.

jstimpfle··on I hate compilers
> your "platform" is also typically a framework, like QT or AppKit or whatever you end up using

That's not what I consider "low level programming". I don't use any of these.

Yes you can do try and do plain Javascript. Honestly Javascript is a much less pleasurable environment than a compiled statically typed procedural language. The main advantage of the browser is you get a viewport, you get font rendering etc. with almost no setup required at all.

jstimpfle··on I hate compilers
It's not so much about the browser (I'm not aware of major incompatibilities introduced by new browsers or new W3C standards). But the software ecosytems (like frameworks, or node.js) that web people are relying on in order to create their web apps.
jstimpfle··on I hate compilers
This is how I mean it: In case of low level programming, the "platform" is the hardware/OS/compiler. In case of web programming, the "platform" is the web framework.

If you update the OS, hardware, or compiler, you will see only few changes. If you update the web framework, you may see breakages, API deprecations or whatever. You may want to move to a different web framework entirely. TBH I don't really know, I don't know web programming beyond basic HTML/Javascript. That's what they say, though.

jstimpfle··on I hate compilers
Depends on what you mean by low level I guess. Compared to web application framework churn rate, simple procedural programming without many dependencies is remarkably stable. You tend to program in a way that works for most platforms (all targetted platforms). How to best do that you learn over the years. To me personally it's very refreshing if the environment around you does not constantly change. That affords learning a bag of tricks and a list of gotchas to avoid.
jstimpfle··on How memory safety CVEs differ between Rust and C/C++
I thought so, too, at some point, and I put it to practice, actually did that for a long time. (I'm not _that_ much of a talker, I can back up what I'm saying with real experience having erred on the opposite side for a long time).

I thought so too, for many other things, and did so too in practice. Then I was doing thousands of little tasks in order to improve "security" and "correctness" and "proving everything", and never got to actually do anything useful, and my code became bloated to the point it didn't get to do much useful work.

Now I'm more considerate, trying to weigh everything in the larger context, is it REALLY required to get my job done?

← PreviousPage 4 of 34Next →