Hacker Newsnew | past | comments | ask | show | jobs | submit | Negitivefrags's commentslogin

Why is it such a terrible idea?

No need to add complexity, dependancies and reduced performance by using these libraries.


Lots of reasons:

The code is not portable between architectures.

You can’t actually define your data structure. You can pretend with your compiler’s version of “pack” with regrettable results.

You probably have multiple kinds of undefined behavior.

Dealing with compatibility between versions of your software is awkward at best.

You might not even get amazing performance. mmap is not a panacea. Page faults and TLB flushing are not free.

You can’t use any sort of advanced data types — you get exactly what C gives you.

Forget about enforcing any sort of invariant at the language level.


I've written a lot of code using that method, and never had any portability issues. You use types with number of bits in them.

Hell, I've slung C structs across the network between 3 CPU architectures. And I didn't even use htons!

Maybe it's not portable to some ancient architecture, but none that I have experienced.

If there is undefined behavior, it's certainly never been a problem either.

And I've seen a lot of talk about TLB shootdown, so I tried to reproduce those problems but even with over 32 threads, mmap was still faster than fread into memory in the tests I ran.

Look, obviously there are use cases for libraries like that, but a lot of the time you just need something simple, and writing some structs to disk can go a long way.


Some people also don't use protective gear when going downhill biking, it is a matter of feeling lucky.

On the other hand some people have things to ward off evil demons, and aren't bothered by evil demons.

The parent has actually done the thing, and found no issues, I don't think you can hand wave that away with a biased metaphor.

Otherwise you get 'Goto considered harmful' and people not using it even when it fits.


As proven by many languages without native support for plain old goto, it isn't really required when proper structured programming constructs are available, even if it happens to be a goto under the hood, managed by the compiler.

My point is it's bad debating style. 'Everyone knows C is bad for all kinds of reasons ergo, even when someone presents their own actual experience, I can respond with a refrain that sounds good'

Not using goto because you've heard it's always bad is the same kind of thing. Yes it has issues, but that isn't a reason to brush anyone off that have actual valid uses for it.


Since I am coding since 1986, lets say I have plenty of experience with goto in various places myself.

C allows most of this, whereas C++ doesn't allow pointer aliasing without a compiler flag, tricks and problems.

I agree you can certainly just use bytes of the correct sizes, but often to get the coverage you need for the data structure you end up writing some form of wrapper or fixup code, which is still easier and gives you the control versus most of the protobuf like stuff that introduces a lot of complexity and tons of code.


__attribute__((may_alias, packed)) right on the struct.

Check your generated code. Most compilers assume that packed also means unaligned and will generate unaligned load and store sequences, which are large, slow, and may lose whatever atomicity properties they might have had.

That is not C, but a non-standard extension and thus not portable.

> non-standard extension and thus not portable

Modern versions of standard C aren't very portable either, unless you plan to stick to the original version of K&R C you have to pick and choose which implementations you plan to support.


I disagree. Modern C with C17 and C23 make this less of an issue. Sure, some vendors suck and some people take shortcuts with embedded systems, but the standard is there and adopted by GCC, Clang and even MSVC has shaped up a bit.

> GCC, Clang and even MSVC

Well, if that is the standard for portability then may_alias might as well be standard. GCC and Clang support it and MSVC doesn't implement the affected optimization as far as I can find.


What do you think the standard is for standardization?

Within the context of this discussion portability was mentioned as key feature of the standard. If C23 adoption is as limited as the, possibly outdated, tables on cppreference and your comments about gcc, clang and msvc suggest then the functionality provided by the gcc attribute would be more portable than C23 conformant code. You could call it a de facto standard, as opposed to C23 which is a standard in the sense someone said so.

That seems highly unlikely. Let's assume that all compilers use the exact same padding in C structs, that all architectures use the same alignment, and that endianness is made up, that types are the same size across 64 and 32 bit platforms, and also pretend that pointers inside a struct will work fine when sent across the network; the question remains still: Why? Is THIS your bottleneck? Will a couple memcpy() operations that are likely no-op if your structs happen to line up kill your perf?

I guess to not have to set up protobuf or asn1. Those preconditions of both platforms using the same padding and endianness aren't that hard to satisfy if you own it all.

But do you really have such a complex struct where everything inside is fixed-size? I wouldn't be surprised if it happens, but this isn't so general-purpose like the article suggests.


There are at least 10 steps between protobuf and casting a struct to a char*.

"Portable" has originally meant "able to be ported" and not "is already ported"

No defined binary encoding, no guarantee about concurrent modifications, performance trade-offs (mmap is NOT always faster than sequential reads!) and more.

Doesn't that just describe low level file IO in general?

Because a struct might not serialize the same way from a CPU architecture to another.

The sizes of ints, the byte order and the padding can be different for instance.


C has had fixed size int types since C99. And you've always been able to define struct layouts with perfect precision (struct padding is well defined and deterministic, and you can always use __attribute__(packed) and bit fields for manual padding).

Endianness might kill your portability in theory. but in practice, nobody uses big endian anymore. Unless you're shipping software for an IBM mainframe, little endian is portable.


You just define the structures in terms of some e.g. uint32_le etc types for which you provide conversion functions to native endianness. On a little endian platform the conversion is a no-op.

It can be made to work (as you point out), and the core idea is great, but the implementation is terrible. You have to stop and think about struct layout rules rather than declaring your intent and having the compiler check for errors. As usual C is a giant pile of exquisitely crafted footguns.

A "sane" version of the feature would provide for marking a struct as intended for ser/des at which point you'd be required to spell out every last alignment, endianness, and bit width detail. (You'd still have to remember to mark any structs used in conjunction with mmap but C wouldn't be any fun if it was safe.)


The reason you use DX12 in a new project is so that you can get good linux support.

I'm making a joke, but it's also true.


How good does Wine support DX12?


Support for DX12 under Proton in linux is incredibly good. Some games actually run faster under DX12 in Proton than the native versions do.


I don't think it's faster than a windows game running Vulkan, though, is it? Like, if you benchmarked a game that has native DX12 and Vulkan modes (such as Wolfenstein: The New Colossus, I believe), it will probably have higher FPS in Vulkan mode, right?


Well our game runs faster in DX12 under Proton than Vulkan under Proton.

Of course since Proton uses Vulkan to implement DX12, it means that our Vulkan implementation is simply worse than the one that Valve created to emulate DX12.

I'm sure it's possible to improve that, but it implies that there way to get the best performance out of Vulkan is less obvious than the way to get it out of DX12.


DXVK does not need wine.


Never mind, DXVK isn't for DX12.


it translates the calls to vulkan.


> If the singularity does happen, then it hardly matters what people do or don't believe.

Depends on how you feel about Roko's basilisk.


God Roko's Basilisk is the most boring AI risk to catch the public consciousness. It's just Pascal's wager all over again, with the exact same rebuttal.


The culture that brought you "speedrunning computer science with JavaScript" and "speedrunning exploitative, extractive capitalism" is back with their new banger "speedrunning philosophy". Nuke it from orbit; save humanity.


As a manager, this is 100% the answer. The people who do this are incredibly valuable.

At every performance review I tell all the people who don't do this that they need to do it more. None of them ever do.

For all I can tell, it's an immutable characteristic that 90% of people will never bring something up unless you ask them.


I have never liked the word "manager" because it's rarely useful in practice, the best managers are actually doers who can cut through the performative transparency and "DDoS attack" of constant updates to see when communication is being used to manipulate or mask failure rather than report progress, because the last thing you want is for your employees to become politicians


It's quite interesting to me the way that different "programming cultures" exist around debuggers.

If you grew up doing windows C++ development, looking at things in a debugger is your first step. You only resort to printing values if you can't immediately see what happened in the debugger.

A lot of other envioronment/language cultures are the opposite. Obviously both have their place, but I do feel like more people should use the debugger as the first step instead of the last.


For embedded applications, especially robotics, it tends not to be a great default because it stops the process, which tends to be bad for realtime control loops. That said, a complete hang is the situation where I absolutely would try to get a debugger attached and get a backtrace as one of the first things to try.


If you’re working in robotics and don’t have fully deterministic event based replay you need to find a new middleware.


I print first and get a feel for the code... Debuggers always slowed me down, and yes this was for c++


At my company I just tell people “You have to stand behind your work”

And in practice that means that I won’t take “The AI did it” as an excuse. You have to stand behind the work you did even if you used AI to help.

I neither tell people to use AI, nor tell them not to use it, and in practice people have not been using AI much for whatever that is worth.


The difference I see between a company dealing with this as opposed to an open source community dealing with this is that the company can fire employees as a reactive punishment. Drive-by open source contributions cost very little to lob over and can come from a wide variety of people you don't have much leverage over, so maintainers end up making these specific policies to prevent them from having to react to the thousandth person who used "The AI did it" as an excuse.


When you shout "use AI or else!" from a megaphone, don't expect everyone to interpret it perfectly. Especially when you didn't actually understand what you were saying in the first place.


>I neither tell people to use AI, nor tell them not to use it, and in practice people have not been using AI much for whatever that is worth.

I find this bit confusing. Do you provide enterprise contracts for AI tools? Or do you let employees use their personal accounts with company data? It seems all companies have to be managing this somehow at this point.


Shouldn't this go without saying though? At some point someone has to review the code and they see a human name as the sender of the PR. If that person sees the work is bad, isn't it just completely unambiguous that the person whose name is on the PR is responsible for that? If someone responded "but this is AI generated" I would feel justified just responding "it doesn't matter" and passing the review back again.

And the rest (what's in the LLVM policy) should also fall out pretty naturally from this? If someone sends me code for review, and have the feeling they haven't read it themselves, I'll say "I'm not reviewing this and I won't review any more of your PRs unless you promise you reviewed them yourself first".

The fact that people seem to need to establish these things as an explicit policy is a little concerning to me. (Not that it's a bad idea at all. Just worried that there was a need).


You would think it's common sense but I've received PRs that the author didn't understand and when questioned told me that the AI knows more about X than they do so they trust its judgement.

A terrifying number of people seem to think that the damn thing is magic and infallible.


The smartest and most sensible response.

I'm dreading the day the hammer falls and there will be AI-use metrics implemented for all developers at my job.


It's already happened at some very big tech companies


One of the reasons I left a senior management position at my previous 500-person shop was that this was being done, but not even accurately. Copilot usage via the IDE wasn't being tracked; just the various other usage paths.

It doesn't take long for shitty small companies to copy the shitty policies and procedures of successful big companies. It seems even intelligent executives can't get correlation and causation right.


Some people who just want to polish their resume will feed any questions/feedback back into the AI that generated their slop. That goes back and forth a few times until the reviewing side learns that the code authors have no idea what they're doing. An LLM can easily pretend to "stand behind its work" if you tell it to.

A company can just fire someone who doesn't know what they're doing, or at least take some kind of measure against their efforts. On a public project, these people can be a death by a thousand cuts.

The best example of this is the automated "CVE" reports you find on bug bounty websites these days.


What good does it really do me if they "stand behind their work"? Does that save me any time drudging through the code? No, it just gives me a script for reprimanding. I don't want to reprimand. I want to review code that was given to me in good faith.

At work once I had to review some code that, in the same file, declared a "FooBar" struct and a "BarFoo" struct, both with identical field names/types, and complete with boilerplate to convert between them. This split served no purpose whatsoever, it was probably just the result of telling an agent to iterate until the code compiled then shipping it off without actually reading what it had done. Yelling at them that they should "stand behind their work" doesn't give me back the time I lost trying to figure out why on earth the code was written this way. It just makes me into an asshole.


It adds accountability, which is unfortunately something that ends up lacking in practice.

If you write bad code that creates a bug, I expect you to own it when possible. If you can't and the root cause is bad code, then we probably need to have a chat about that.

Of course the goal isn't to be a jerk. Lots of normal bugs make it through in reality. But if the root cause is true negligence, then there's a problem there.

AI makes negligence much easier to achieve.


If you asked Claude to review the code it would probably have pointed out the duplication pretty quickly. And I think this is the thing - if we are going to manage programmers who are using LLM's to write code, and have to do reviews for their code, reviewers aren't going to be able to do it for much longer without resorting to LLM assistance themselves to get the job done.

It's not going to be enough to say - "I don't use LLM's".


Yelling at incompetent or lazy co-workers isn't your responsibility, it's your manager's. Escalate the issue and let them be the asshole. And if they don't handle it, well it's time to look for a new job.


...what makes you think i2talics isn't the manager in this situation??


>> Yelling at incompetent or lazy co-workers isn't your responsibility, it's your manager's

First: Somebody hired these people, so are they really "lazy and incompetent"?

Second: There is no one who's "job" is to yell at incompetent or lazy workers.


> At my company I just tell people “You have to stand behind your work”

Since when has that not been the bare minimum. Even before AI existed, and even if you did not work in programming at all, you sort of have to do that as a bare minimum. Even if you use a toaster and your company guidelines suggest you toast every sandwich for 20 seconds, if following every step as per training results in a lump of charcoal for bread, you can’t serve it up to the customer. At the end of the day, you make the sandwich, you’re responsible for making it correctly.

Using AI as a scapegoat for sloppy and lazy work needs to be unacceptable.


Of course it’s the minimum standard, and it’s obvious if you view AI as a tool that a human uses.

But some people view it as a seperate entity that writes code for you. And if you view AI like that, then “The AI did it” becomes an excuse that they use.


"Yes, but you submitted it to us."

If you're illiterate and can't read maybe don't submit the text someone has written for you if you can't even parse the letters.


The policy in TFA is a nicer way of saying that.


Bad example. If the toaster carbonized bread in 20 seconds it's defective, likely unsafe, possibly violates physics, certainly above the pay grade of a sandwich-pusher.

Taking responsibility for outcomes is a powerful paradigm but I refuse to be held responsible for things that are genuinely beyond my power to change.

This is tangential to the AI discussion though.


> If the toaster carbonized bread in 20 seconds it's defective, likely unsafe, possibly violates physics, certainly above the pay grade of a sandwich-pusher.

If the toaster is defective, not using it, identifying how to use it if it’s still usable or getting it replaced by reporting it as defective are all well within the pay grade of a sandwich pusher as well as part of their responsibilities.

And you’re still responsible for the sandwich. You can’t throw up your arms and say “the toaster did it”. And that’s where it’s not tangential to the AI discussion.

Toaster malfunctioning is beyond your control, but whether you serve up the burnt sandwich is absolutely within your control, which you will be and should be held responsible for.


That's exactly what I said and at odds with your last comment. You take responsibility for making the sandwich if possible. If not, you're not responsible for the sandwich, but for refunding the customer or offering them something else.

If I'm required to write code using AI without being given time to verify it, then it's also not fair for me to be held responsible for the quality. Agency matters. I will not take responsibility for things that I'm not given the power to address. Of course if I choose to write code with an AI and it comes out badly, that's within my responsibilities.

It's a bad example because typically "whether to toast the sandwich" depends on customer preference (imposed externally) but "whether to use AI" is still mostly up to the worker.


That’s why you make some written protest. While it would not save you from layoff, you won’t be made into a scapegoat.


No it’s not. If you burn a sandwich, you make new sandwich. Sandwiches don’t abide by the laws of physics. If you call a physicist and tell them you burnt your sandwich, they won’t care.


I think it depends on the pay. You pay below the living wage? Better live with your sla.. ah employees.. serving charcoal. You pay them well above the living wage? Now we start to get into they should care-territory.


But "AI did it" is not immediate you are out thing? If you cannot explain why something is made the way you committed to git, we can just replace you with AI right?


> we can just replace you with AI right?

Accountability and IP protection is probably the only thing saving someone in that situation.


Why stop there? We can replace git with AI too!


If you generate the code each time you need it, all version control becomes obsolete.


They'll version control the prompts because the requirements change.


Not if we AI-generate the requirements!


That only works if those colleagues care about what you think of them


I think it's not unlikely that we reach reach a point in a couple of decades where we are all developing win32 apps that most people are running some form of linux.

We already have an entire platform like that (steam deck), and it's the best linux development experience around in my opinion.


It’s not incorrect.

The code says that if x is true then a=13 and if it is false than b=37.

This is the case. Its just that a=13 even if x is false. A thing that the code had nothing to say about, and so the compiler is free to do.


Ok, so you’re saying it’s “technically correct?”

Practically speaking, I’d argue that a compiler assuming uninitialized stack or heap memory is always equal to some arbitrary convenient constant is obviously incorrect, actively harmful, and benefits no one.


In this example, the human author clearly intended mutual exclusivity in the condition branches, and this optimization would in fact destroy that assumption. That said, (a) human intentions are not evidence of foolproof programming logic, and often miscalculate state, and (b) the author could possibly catch most or all errors here when compiling without optimizations during debugging phase.


Regardless of intention, the code says this memory is uninitialized.

I take issue with the compiler assuming anything about the contents of that memory; it should be a black box.


The compiler is the arbiter of what’s what (as long as it does not run afoul the CPU itself).

The memory being uninitialised means reading it is illegal for the writer of the program. The compiler can write to it if that suits it, the program can’t see the difference without UB.

In fact the compiler can also read from it, because it knows that it has in fact initialised that memory. And the compiler is not writing a C program and is thus not bound by the strictures of the C abstract machine anyway.


Yes yes, the spec says compilers are free to do whatever they want. That doesn’t mean they should.

> The user didn’t initialize this integer. Let’s assume it’s always 4 since that helps us optimize this division over here into a shift…

This is convenient for who exactly? Why not just treat it as a black box memory load and not do further “optimizations”?


> That doesn’t mean they should.

Nobody’s stopping you from using non-optimising compilers, regardless of the strawmen you assert.


As if treating uninitialized reads as opaque somehow precludes all optimizations?

There’s a million more sensible things that the compiler could do here besides the hilariously bad codegen you see in the grandparent and sibling comments.

All I’ve heard amounts to “but it’s allowed by the spec.” I’m not arguing against that. I’m saying a spec that incentivizes this nonsense is poorly designed.


Why is the code gen bad? What result are you wanting? You specifically want whatever value happened to be on the stack as opposed to a value the compiler picked?


> As if treating uninitialized reads as opaque somehow precludes all optimizations?

That's not what these words mean.

> There’s a million more sensible things

Again, if you don't like compilers leveraging UBs use a non-optimizing compiler.

> All I’ve heard amounts to “but it’s allowed by the spec.” I’m not arguing against that.

You literally are though. Your statements so far have all been variations of or nonsensical assertions around "why can't I read from uninitialised memory when the spec says I can't do that".

> I’m saying a spec that incentivizes this nonsense is poorly designed.

Then... don't use languages that are specified that way? It's really not that hard.


From the LLVM docs [0]:

> Undef values aren't exactly constants ... they can appear to have different bit patterns at each use.

My claim is simple and narrow: compilers should internally model such values as unspecified, not actively choose convenient constants.

The comment I replied to cited an example where an undef is constant folded into the value required for a conditional to be true. Can you point to any case where that produces a real optimization benefit, as opposed to being a degenerate interaction between UB and value propagation passes?

And to be explicit: “if you don’t like it, don’t use it” is just refusing to engage, not a constructive response to this critique. These semantics aren't set in stone.

[0] https://llvm.org/doxygen/classllvm_1_1UndefValue.html#detail...


> My claim is simple and narrow: compilers should internally model such values as unspecified, not actively choose convenient constants.

An assertion you have provided no utility or justification for.

> The comment I replied to cited an example where an undef is constant folded into the value required for a conditional to be true.

The comment you replied to did in fact not do that and it’s incredible that you misread it such.

> Can you point to any case where that produces a real optimization benefit, as opposed to being a degenerate interaction between UB and value propagation passes?

The original snippet literally folds a branch and two stores into a single store, saving CPU resources and generating tighter code.

> this critique

Critique is not what you have engaged in at any point.


Sorry, my earlier comments were somewhat vague and assuming we were on the same page about a few things. Let me be concrete.

The snippet is, after lowering:

  if (x)
    return { a = 13, b = undef }
  else
    return { a = undef, b = 37 }
LLVM represents this as a phi node of two aggregates:

  a = phi [13, then], [undef, else]
  b = phi [undef, then], [37, else]
Since undef isn’t “unknown”, it’s “pick any value you like, per use”, InstCombine is allowed to instantiate each undef to whatever makes the expression simplest. This is the problem.

  a = 13
  b = 37
The branch is eliminated, but only because LLVM assumes that those undefs will take specific arbitrary values chosen for convenience (fewer instructions).

Yes, the spec permits this. But at that point the program has already violated the language contract by executing undefined behavior. The read is accidental by definition: the program makes no claim about the value. Treating that absence of meaning as permission to invent specific values is a semantic choice, and precisely what I am criticizing. This “optimization” is not a win unless you willfully ignore the program and everything but instruction count.

As for utility and justification: it’s all about user experience. A good language and compiler should preserve a clear mental model between what the programmer wrote and what runs. Silent non-local behavior changes (such as the one in the article) destroy that. Bugs should fail loudly and early, not be “optimized” away.

Imagine if the spec treated type mismatches the same way. Oops, assigned a float to an int, now it’s undef. Let’s just assume it’s always 42 since that lets us eliminate a branch. That’s obviously absurd, and this is the same category of mistake.


It's the same as this:

    int random() {
        return 4; // chosen by dice roll
    }
Technically correct. But not really.


Also even without UB, even for a naive translation, a could just happen to be 13 by chance, so the behaviour isn't even an example of nasal demons.


I recently compared performance per dollar for CPUs and GPUs on benchmarks for GPUs today vs 10 years ago, and suprisingly, CPUs had much bigger gains. Until I saw that for myself, I thought exactly the same thing as you.

It seems shocking given that all the hype is around GPUs.

This probably wouldn't be true for AI specific workloads because one of the other things that happened there in the last 10 years was optimising specifically for math with lower size floats.


That makes sense. Nvidia owns the market and is capturing all the surplus value. They’re competing with themselves to convince you to buy a new card.


It's coz of use cases. Consumer-wise, if you're gamer, CPU just needs to be at "not the bottleneck" level for majority of games as GPU does most of the work when you start increasing resolution and details.

And many pro-level tools (especially in media space) offload to GPU just because of so much higher raw compute power.

So, basically, for many users the gain in performance won't be as visible in their use cases


The person who runs the hotel isn’t doing it to house the homeless out of the goodness of their heart.

If a person abuses the shared kitchen, they get kicked out. This is a business. Maybe don’t do it next time.

And that is a good thing. It forces people to actually abide by the social contract.

And there will be people who can’t deal with that, and can’t live anywhere, but here’s the thing.

You need a first step on the ladder for people who are ready to actually enter society. Otherwise they never will.


> If a person abuses the shared kitchen, they get kicked out. This is a business.

Not any business, it's a landlord-tenant relationship.

You can't simply kick out a tenant. You have to do a formal eviction process. In many cities this requires collecting evidence of contractual breach, proving that the tenant was notified they were being evicted (such as through a paid service to officially serve and record delivery of the notice), and then following the appropriate waiting period and other laws. It could be months and tens of thousands of dollars of legal fees before you can kick someone out of a house.

Contrast that with the $213 inflation-adjusted monthly rent that the article touts. How many months of rent would they have to collect just to cover the legal fees of a single eviction?


>It forces people to actually abide by the social contract.

"social contract" is just "abide by the terms of the contract they signed" or "hold up their end of the deal" in this case.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: