HNHacker News
TopNewBestAskShowJobs

NobodyNada

3,649 karma · joined May 9, 2019

submissionscomments
NobodyNada··on Total monthly number of StackOverflow questions over time
Shog9 was probably the best person on staff in terms of awareness of the moderation problems and ability to come up with solutions.

Unfortunately, the company abruptly stopped investing in the Q&A platform in ~2015 or so and shifted their development effort into monetization attempts like Jobs, Teams, Docs, Teams (again), etc. -- right around the time the moderation system started to run into serious scaling problems. There were plans, created by Shog and the rest of the community team, for sweeping overhauls to the moderation systems attempting to fix the problems, but they got shelved as the Q&A site was put in maintenance mode.

It's definitely true that staff is to blame for the site's problems, but not Shog or any of the employees whose usernames you'd recognize as people who actually spent time in the community. Blame the managers who weren't users of the site, decided it wasn't important to the business, and ignored the problems.

NobodyNada··on Modern SID chip substitutes [video]
Similar idea: https://monster6502.com/

But note:

> Does it run at the full speed of an original 6502 chip?

> No; it's relatively slow. The MOnSter 6502 runs at about 1/20th the speed of the original, thanks to the much larger capacitance of the design. The maximum reliable clock rate is around 50 kHz. The primary limit to the clock speed is the gate capacitance of the MOSFETs that we are using, which is much larger than the capacitance of the MOSFETs on an original 6502 die.

So if you built a SID using the same techniques and components, you couldn't run it in real-time without the pitch being way too low or without modifying the design. I'm not sure how hard this would be to avoid with better-spec'd components, but intuitively it makes sense for a much larger circuit to run much slower.

NobodyNada··on Using LLMs at Oxide
LLMs also generally don't put spaces around em dashes — but a lot of human writers do.
NobodyNada··on Extra Instructions Of The 65XX Series CPU (1996)
That's exactly right. There's a really good article about it here: https://www.pagetable.com/?p=39
NobodyNada··on You can't fool the optimizer
Let's throw this into godbolt: https://clang.godbolt.org/z/qW3qx13qT

    is_divisible_by_6(int):
        test    dil, 1
        jne     .LBB0_1
        imul    eax, edi, -1431655765
        add     eax, 715827882
        cmp     eax, 1431655765
        setb    al
        ret
    .LBB0_1:
        xor     eax, eax
        ret

    is_divisible_by_6_optimal(int):
        imul    eax, edi, -1431655765
        add     eax, 715827882
        ror     eax
        cmp     eax, 715827883
        setb    al
        ret
By themselves, the mod 6 and mod 3 operations are almost identical -- in both cases the compiler used the reciprocal trick to transform the modulo into an imul+add+cmp, the only practical difference being that the %6 has one extra bit shift.

But note the branch in the first function! The original code uses the && operator, which is short-circuiting -- so from the compiler's perspective, perhaps the programmer expects that x % 2 will usually be false, and so we can skip the expensive 3 most of the time. The "suboptimal" version is potentially quite a bit faster in the best case, but also potentially quite a bit slower in the worst case (since that branch could be mispredicted). There's not really a way for the compiler to know which version is "better" without more context, so deferring to "what the programmer wrote" makes sense.

That being said, I don't know that this is really a case of "the compiler knows best" rather than just not having that kind of optimization implemented. If we write 'x % 6 && x % 3', the compiler pointlessly generates both operations. And GCC generates branchless code for 'is_divisible_by_6', which is just worse than 'is_divisible_by_6_optimal' in all cases.

NobodyNada··on Human brains are preconfigured with instructions for understanding the world
That's pretty close to escaping the Earth's gravity well, but not quite out, since the Moon is definitely still orbiting the Earth.
NobodyNada··on Human brains are preconfigured with instructions for understanding the world
Humans have not left Earth's gravity well. We've built probes that have, but humans have only gotten as far as orbit.
NobodyNada··on Show HN: I built a synth for my daughter
> On one hand, the fact that the same sound can be named A# and Bb may be puzzling for a kid

I think that, given the toy is (currently) diatonic, and doesn't really have any ability to visualize the chromatic scale (like a piano keyboard does), using the formally correct note names is more intuitive. That way, only the accidentals change when you change modes ("when I change it to C minor, the B becomes a Bb"). This naturally teaches a simple and correct mental model: "the slider chooses a letter and pushing the orange knob makes letters flat or sharp".

If you only ever use sharps instead of sticking to the correct notation, then the notes change inconsistently between different keys ("changing from C major to C minor turns the B into an A#, but changing from C# major to C# minor changes the F into an E"). This is incomprehensible unless you've already memorized the piano keyboard layout.

The OP's choice of restricting to the diatonic scale seems sensible to me -- it helps the kid learn the vocabulary of Western music (if that's your goal!) and it benefits the parents as well by making it hard to create something that sounds bad.

NobodyNada··on Show HN: I built a synth for my daughter
That is fantastic, I love it!

If I may submit an extremely pedantic music nerd bug report: at 46s in the video demo (https://www.youtube.com/watch?v=qboig3a0YS0&t=46s), the display should read Bb instead of A#, as the key of C minor is written with flats :)

(The precise rule is that a diatonic scale must use each letter name for exactly one note, e.g. you can't have both G and G# in the same key, and you can't skip B. This has many important properties that make music easier to read and reason about, such as allowing written music to specify "all the E's, A's, and B's are flat" once at the start of the piece instead of having to clutter the page with redundant sharps or flats everywhere.)

NobodyNada··on Open-source Zig book
If no references are involved, writing unsafe Rust is significantly easier than writing correct C, because the semantics are much clearer and easier to find in the documentation, and there's no insane things like type-based aliasing rules.

If references are involved, Rust becomes harder, because the precise semantics are not decided or documented. The semantics aren't complicated; they're along the lines of "while a reference is live, you can't perform a conflicting access from a pointer or reference not derived from that reference". But there aren't good resources for learning this or clarifying the precise details. This area is an active work-in-progress; there is a subteam of the Rust project led by Ralf Jung (https://www.ralfj.de/blog/) working on fully and clearly defining the language's operational semantics, and they are doing an excellent job of it.

When it comes to Zig, the precise rules and semantics of the memory model are much less clear than C. There's essentially no documentation, and if you search GitHub issues a lot of it is undecided and not actively being worked on. This is completely understandable given Zig's stage in development, but for me "how easy it is to write UB-free code" boils down to "how easy is it to understand the rules and apply them correctly", and so to me Zig is very hard to write correctly if you can't even figure out what "correct" is.

Once Zig and Rust both have their memory models fleshed out, I hope Zig lands somewhere comparable to where Rust-without-references is today, and I hope that Rust-with-references ends up being only a little bit harder (and still easier than C).

NobodyNada··on Disassembling terabytes of random data with Zig and Capstone to prove a point
Every reverse engineer learns very quickly that "add [rax], al" has the machine code representation "00 00".
NobodyNada··on The Single Byte That Kills Your Exploit: Understanding Endianness
> There's a "logical" bit order that these operations follow, which starts with the MSBit and ends with the LSBit

Well, normally when bits are numbered, "bit 0" is the least significant bit. The MSB is usually written on the left, (such as for left and right shifts), but that doesn't necessarily make it "first" in my mind.

NobodyNada··on Étude in C minor (2020)
CDs use 44.1kHz because your sample rate needs to be double the highest frequency you want to encode to avoid aliasing artifacts: https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampli...

20kHz is the top of the human hearing range, and picking something a little bit higher than 40kHz gives you room to smoothly roll off frequencies above the audible range without needing an extremely steep filter that would create a large phase shift.

NobodyNada··on FFmpeg to Google: Fund us or stop sending bugs
> publicly disclosing these for small resource constrained open source project probably creates a lot more risk than reward.

You can never be sure that you're the only one in the world that has discovered or will discover a vulnerability, especially if the vulnerability can be found by an LLM. If you keep a vulnerability a secret, then you're leaving open a known opportunity for criminals and spying governments to find a zero day, maybe even a decade from now.

For this one in particular: AFAIK, since the codec is enabled by default, anyone who processes a maliciously crafted .mp4 file with ffmpeg is vulnerable. Being an open-source project, ffmpeg has no obligation to provide me secure software or to patch known vulnerabilities. But publicly disclosing those vulnerabilities means that I can take steps to protect myself (such as disabling this obscure niche codec that I'm literally never going to use), without any pressure on ffmpeg to do any work at all. The fact that ffmpeg commits themselves to fixing known vulnerabilities is commendable, and I appreciate them for that, but they're the ones volunteering to do that -- they don't owe it to anyone. Open-source maintainers always have the right to ignore a bug report; it's not an obligation to do work unless they make it one.

Vulnerability research is itself a form of contribution to open source -- a highly specialized and much more expensive form of contribution than contributing code. FFmpeg has a point that companies should be better about funding and contributing to open-source projects that they rely on, but telling security researchers that their highly valuable contribution is not welcome because it's not enough is absurd, and is itself an example of making ridiculous demands for free work from a volunteer in the open-source community. It sends the message that white-hat security research is not welcome, which is a deterrent to future researchers from ethically finding and disclosing vulnerabilities in the future.

As an FFmpeg user, I am better off in a world where Google disclosed this vulnerability -- regardless of whether they, FFmpeg, or anyone else wrote a patch -- because a vulnerability I know about is less dangerous than one I don't know about.

NobodyNada··on Zig and the design choices within
> it's just silly to draw a a particular sharp line between Rust and Zig because they perform exactly the same (in terms of sound guarantees; we're ignoring any softer effects) for most top weaknesses.

There is a very clear sharp line between them in that Rust has no undefined behavior outside of an unsafe block. This matters because the effects of undefined behavior -- particularly memory-corrupting undefined behavior -- are unbounded. Security issues caused by logic bugs are limited to only having local effects on the program -- a SQL injection bug can lead to the wrong SQL query being executed, a path traversal bug can lead to the wrong path being accessed, and a shell escaping bug can lead to execution of the wrong shell command. These are severe problems that can lead to data exfiltration or remote code execution, but the relationship between bug and effect is straightforward: "I'm passing user input to a shell here; this could have catastrophic consequences so I'd better review this carefully." In contrast, undefined behavior can happen anywhere in your program, and it can do anything. That is a clear and measurable difference, and emperical evidence from the last 10 years clearly indicates both that it is nigh impossible to write large C/C++ applications without both spatial and temporal memory safety vulnerabilities, and that adopting Rust measurably decreases the incidence of such vulnerabilities.

Zig is certainly an improvement over C on this front, but it is still a UB-heavy language, and that's where the sharp line is. It's hard to make emperical comparisons because Zig is so young, but the comparision between Deno and Bun in the article is a reasonably strong demonstration that Zig has not achieved a comparable level of memory safety to Rust.

> Sure, but then you might as well also consider softer effects. For example, maybe a language that's easier to review because it's more explicit, or a language that's faster to compile and is easier to test wins.

> And I agree that we should consider all these, but then we start seeing why correctness is such a complicated topic, and we could speculate just as easily that it is Zig that "clearly" wins.

This doesn't really have anything to do with my point that the CVE list does not provide evidence to dismiss temporal memory safety as irrelevant; it's more of a general statement on writing correct software. But regardless, "Zig has nullability and bounds checks" and "Rust has an affine type system, statically-checked immutability and exclusivity, language-level resource management, and no undefined behavior" are not in the same league of program correctness. Rust wasn't designed after some ideal of memory safety at the expense of clarity and correctness: the lifetime and type system came from a goal of reducing logic bugs in complex concurrent programs, and the fact that it is powerful enough to achieve memory safety without garbage collection was a happy accident. The emperical results that Rust programs have fewer memory-safety vulnerabilities demonstrate that Rust's static approach to software correctness is successful, and not just for the specific problem of memory safety, because Rust's tooling for achieving program correctness is generalizable to arbitrary application invariants. This lines up with my own experience; software I write using Rust is far easier to get right, more reliable, and easier to successfully maintain and refactor than anything else I've done.

Certainly Zig has its strong points as well -- explicitness can reduce complexity and compile times, but it also has downsides of pushing complexity into application code (thus making it harder to review and introducing more opportunities to create mistakes). A proper comparison of the two approaches is worthwhile, but just as "Rust is more memory safe" is an overly reductive generalization of the langauges' approach to software correctness, "there's a rather small difference between Rust and Zig" simply isn't true.

NobodyNada··on Zig and the design choices within
Limiting to the "top 5" vulnerabilities by number of CVEs feels like cherry-picking. It's true that spatial memory safety is lower-hanging fruit than temporal memory safety, sure; but the CVE list is dominated by vulnerabilities in web applications which are mostly already written in fully memory-safe languages (additionally, these vulnerabilities are typically mitigated by library/API design rather than by programming language design, in which case Rust gives you quite a lot more tools than Zig for designing APIs that have concepts of unsanitized/untrusted data, but I digress). If you filter for vulnerabilities relevant to applications that would typically be written in C/C++/Rust/Zig, use-after-free is easily within the top 5.

The exact positioning within the top 10 is also quite noisy: if you look at last year's list, UAF is in the #1 spot for actively exploited vulnerabilities, even beating out all the web ones: https://cwe.mitre.org/top25/archive/2023/2023_kev_list.html

Lastly, filtering on CVEs has a high selection bias: just because security researchers go for the easy vulnerabilities first doesn't mean that the harder ones can be ignored. As high-profile projects adopt tooling and mitigations to reduce the impact of spatial memory safety problems, it's common to see a sudden increase in CVEs related to temporal memory safety. This is not because use-after-free bugs somehow became more common or severe -- it's because once you eliminate the easy source of vulnerabilities, the attackers shift their attention to the new lowest-hanging fruit.

NobodyNada··on Zig and the design choices within
> As a small example wrt Rust: resetting an arraylist/vector while reusing its memory is a weirdly complicated trick

A bit of a nitpick here: the trick is for creating a new vector of a different type, that reuses the allocation of an existing vector, using only safe code. "Resetting an arraylist/vector while reusing its memory" is just vec.clear() if you're not changing the type. And it's trivial to change the type of a vector with unsafe (the docs even have examples of this); the only advantage of the "trick" is to ensure you'll get a panic if you screw up the alignment of the types.

And after that blog post, the Rust team accepted a proposal to introduce a vec.recycle() function to change the type of a vector without needing that trick (and with compile-time checks for alignment compatibility): https://github.com/rust-lang/rust/pull/148416

But that example aside, I agree with your overall premise -- Zig and Rust share different design goals here, and Zig's lower level of abstraction makes it more approachable to learn than a language like Rust.

NobodyNada··on A Note on Fil-C
> I'm not familiar with the guy

Graydon Hoare is the creator of Rust.

So of course he likes Rust. And of course his blog post is going to be comparing Fil-C to Rust. Anyone can write a blog post evaluating Fil-C, but only Graydon can compare it to his own design choices and motivations when he attempted to solve a similar problem. That's the whole thing that makes this post interesting.

NobodyNada··on The Rust Foundation Maintainers Fund
I think that both languages deserve to be evaluated on their technical merits, of which there are many. I would say they are both very well-designed languages that occupy different points in the design space and each have unique innovations of their own, and are worthy of the attention they get. I also think both languages have strong communities and good technical leadership.

What I'm frustrated about is a general pattern in online discourse of treating programming language adoption as a zero-sum game and pitting the communities against each other. This is nothing remotely new -- holy wars over tooling are just about as old as computing itself -- but Rust seems to have become right at the center of it in the last few years, and I think this is likely just a result of it becoming "mainstream" enough for people to care about it outside of a niche circle. I consider that a community issue with Rust, but probably an unavoidable one given the scale of the Internet.

The thing that feels different to me about Zig is that the language's leadership participates in the "holy war", which is different than what I have observed from Rust's leadership. It's one thing if random netizens are trash talking the "opposing team" like a sports fan, but I would expect people who are deeply involved in programming language design and representing their community to know better and behave better than that. It's surprising and disappointing to me; it drags down the overall quality of discourse and sets a bad example for the language communities.

Maybe my own perspective on this is skewed, perhaps I'm looking at Rust's past with rose-tinted glasses. But I think my experiences are comparable. From 2015-2020 I was primarily working with Swift and closely following that language's design and development, and the Rust community (which I was not involved in at all) felt like friendly neighbors. The two communities shared similar goals and had a lot of like-minded people, and because of that there was a lot of overlap and amicability between the communities. Both languages' teams were frequently comparing notes and copying features from one another.

Now I'm primarily working with Rust and closely following that languages' design and development, and it seems to me like the Zig community (which I am not involved with at all) should be on the same friendly terms for the same reasons, but the vibes I see from them are "this town isn't big enough for the two of us", and I'm bothered by that.

> I've looked at the major rust implements from big corp. It's all Arc, copy/clone, and people getting fired.

I have no idea what this is supposed to mean. Are you saying you've seen projects implemented in Rust go poorly? If so, I don't know what to say without any context, besides that I don't think there's a "one size fits all" for programming languages.

Or are you saying big companies' contributions towards the Rust project itself have gone poorly? I don't really know what to say about that either. I have felt that the direction the project has taken over the past few years has represented me and addressed my needs well, so I have confidence in their technical direction and leadership for the time being.

NobodyNada··on The Rust Foundation Maintainers Fund
> people who didn't like Rust flocked to Zig as an alternative, and were keen to promote it as an alternative to Rust by criticising Rust, as wider usage would provide them more of an ecosystem to use in their own Zig programs.

> People who were happy with Rust didn't have same need to criticise Zig in online spaces as Rust is the established player in the C alternatives space. (Though Rust is on the other side when compared to C once you expand the space to "all low level programming languages").

I think that this effect is...more real and intentional than I wish it was or think is healthy.

There's no denying that Rust benefited greatly from heavy "language evangelism" from around 2014-2022 or so (rough subjective range of dates, ending with when I feel like Rust became sufficiently mainstream that "comment section evangalism" is no longer the primary driver of the language's growth). The atmosphere that surrounded the language evangalism during this era -- from my recollection as someone who was aware of Rust but explicitly not interested in it at the time -- felt like one of curiousity and exploring new innovation in the programming language design space, and it didn't come across as pushy or some kind of moral imperative.

Additionally, most of the evangelism was not driven by the Rust project itself, but more of a grassroots thing from:

- Early users

- People who thought the language was interesting without having used it

- The attention that came from prolific early Rust projects like Servo and ripgrep

- The attention that came from the language's technical innovations

(The only person I remember regularly seeing in Rust threads who was actually associated with the project was Steve Klabnik, and I consider him a stellar example of how to represent a project online in a way that's respectful and not pushy or combative.) And eventually I had a programming task where, thanks to those deep, insightful, and respectful comment threads, I recognized that Rust was the right tool for the task I was trying to accomplish, learned the language myself, found it a joy to use, and began using it more regularly.

But once Rust became mainstream, the eternal September kicked in. Now there seem to be quite a lot of people who are more interested in "language wars" than in healthy, technical discussion of programming languages, and it's exhausting. Many threads about C or C++ or Rust or Zig or Fil-C or whatever seems to get overtaken by these obnoxious, repetitive, preachy, ideological comments about why you should or shouldn't be using Rust, often with very ill-informed armchair takes.

I think this is just something that comes from mainstream Internet culture and is not very representative of "the Rust community", and especially not the Rust project -- most of the serious writing and comments coming from people actually involved with Rust have that spirit of respect, openness, and curiousity about programming language design that I remember from the 2010's. A lot of people who work on Rust are deeply interested in the tradeoffs and innovations of new programming languages and fundamentally excited about the possibility of Rust becoming obsolete because something better has come along. But now that Rust adoption is increasing and the broader Internet culture is being forced to consider it, you see a lot of unhealthy reactionary takes from people who act like programming languages are a zero-sum game and they need to pick a side.

Now Zig is where this gets a little bit odd to me. My impression (as an outsider to the Zig community as well) is that Zig's leadership has chosen to view adoption as a zero-sum language war. It's as if they considered:

- How Rust benefited from language evangelism during the 2010's

- How many other "C-replacement" languages over the past 25 years have failed to gain large-scale adoption

- How "language war" discourse is extremely effective for enagement on places like HN

...and decided that the best way to increase Zig adoption is by intentionally leaning into that high-engagement "language war" discourse. Maybe it's not intentional -- and there's certainly a lot of cool ideas and high-quality technical discussion that comes out of the Zig community -- but I've also seen a consistent pattern of snarky or hostile comments from Zig leadership towards Rust people (such as calling Rust users "safety coomers", or jumping into in-depth technical discussions of Rust's downsides like compiler performance with substance-less cheap shots). Whereas I can't remember ever seeing anything but respect and curiosity from people involved in the Rust project towards other communities.

I'm just tired of seeing people draw battle lines around programming languages instead of promoting a spirit of learning from each other and making our tools better.

NobodyNada··on Futurelock: A subtle risk in async Rust
I was sloppy with my wording, I should have said "it doesn't run all the futures to completion".

> making them all tasks means that they are all polled and therefore continue progressing until they are dropped. It doesn't mean that select! would have to run them all the way to completion.

This is exactly correct, but oftentimes the reason you're using select is because you don't want to run the futures all the way to completion. In my experience, the most common use cases for select are:

- An event handler loop that receives input from multiple channels. You could replace this with multiple tasks, one reading from each channel; but this could potentially mess with your design for queueing / backpressure -- often it's important for the loop to pause reading from the channels while processing the event.

- An operation that's run with a timeout, or a shutdown event from a controlling task. In this case I want the future to be dropped when the task is cancelled.

The example in the original post was the second case: an operation with a timeout. They wanted the operation to be cancelled when the timeout expired, but because the select statement borrowed the future, it only suspended the future instead of cancelling it. This is a very common code pattern when calling select! in a loop, when you want a future to be resumed instead of restarted on the next loop iteration -- it's very intentional that select! allows you to use either way, because you often want either behavior.

NobodyNada··on Futurelock: A subtle risk in async Rust
> if tokio::select!() only accepted tasks (or implicitly turned any futures it receives into tasks, like Python's asyncio.gather() does) then it wouldn't have this problem?

Yes, this is correct. However, many of the use cases for select rely on the fact that it doesn't run all the tasks to completion. I've written many a select! statement to implements timeouts or other forms of intentionally preempting a task. Sometimes I want to cancel the task and sometimes I want to resume it after dealing with the condition that caused the preemption -- so the behavior in the article is very much an intentional feature.

> even if the async runtime is careful, is it still possible to create and fail to poll a raw Future by accident?

This is also the case. There's nothing magic about a future; it's just an ordinary object with a poll function. Any code can create a future and do whatever it likes with it; including polling it a few times and then stopping.

Despite being included as part of Tokio, select! does not interact with the runtime or need any kind of runtime support at all. It's an ordinary function that creates a future which waits for the first of several "child" futures to complete; similar functions are also provided in other prominent ecosystem crates besides Tokio and can be implemented in user code as well.

NobodyNada··on 10M people watched a YouTuber shim a lock; the lock company sued him – bad idea
Note that the courts ruled this technique invalid in Sega v. Accolade: https://en.wikipedia.org/wiki/Sega_v._Accolade

But that was in a pre-DMCA world, before the anti-circumvention provisions gave these companies more legal weapons to criminalize fair use and competition.

NobodyNada··on How I turned Zig into my favorite language to write network programs in
> Stackful coroutines need more memory, because you need to pre-allocate large enough stack for the entire lifetime. With stackless coroutines, you only need the current state, but with the disadvantage that you need frequent allocations.

This is not quite correct -- a stackful coroutine can start with a small stack and grow it dynamically, whereas stackless coroutines allocate the entire state machine up front.

The reason why stackful coroutines typically use more memory is that the task's stack must be large enough to hold both persistent state (like local variables that are needed across await points) and ephemeral state (like local variables that don't live across await points, and stack frames of leaf functions that never suspend). With a stackless implementation, the per-task storage only holds persistent state, and the OS thread's stack is available as scratch space for the current task's ephemeral state.

NobodyNada··on How I turned Zig into my favorite language to write network programs in
> The Rust folks adopted async with callbacks

Rust's async is not based on callbacks, it's based on polling. So really there are three ways to implement async:

- The callback approach used by e.g. Node.js and Swift, where a function that may suspend accepts a callback as an argument, and invokes the callback once it is ready to make progress. The compiler transforms async/await code into continuation-passing style.

- The stackful approach used by e.g. Go, libtask, and this; where a runtime switches between green threads when a task is ready to make progress. Simple and easy to implement, but introduces complexity around stack size.

- Rust's polling approach: an async task is statically transformed into a state machine object that is polled by a runtime when it's ready to make progress.

Each approach has its advantages and disadvantages. Continuation-passing style doesn't require a runtime to manage tasks, but each call site must capture local variables into a closure, which tends to require a lot of heap allocation and copying (you could also use Rust's generic closures, but that would massively bloat code size and compile times because every suspending function must be specialized for each call site). So it's not really acceptable for applications looking for maximum performance and control over allocations.

Stackful coroutines require managing stacks. Allocating large stacks is very expensive in terms of performance and memory usage; it won't scale to thousands or millions of tasks and largely negates the benefits of green threading. Allocating small stacks means you need the ability to dynamically resize stacks at runtime, which requires dynamic allocation and adds significant performance and complexity overhead if you want to make an FFI call from an asynchronous task (in Go, every function begins with a prologue to check if there is enough stack space and allocate more if needed; since foreign functions do not have this prologue, an FFI call requires switching to a sufficiently large stack). This project uses fixed-sized task stacks, customizable per-task but defaulting to 256K [1]. This default is several orders of mangitude larger than a typical task size in other green-threading runtimes, so to achieve large scale the programmer must manually manage the stack size on a per-task basis, and face stack overflows if they guess wrong (potentially only in rare/edge cases).

Rust's "stackless" polling-based approach means the compiler knows statically exactly how much persistent storage a suspended task needs, so the application or runtime can allocate this storage up-front and never need to resize it; while a running task has a full OS thread stack available as scratch space and for FFI. It doesn't require dynamic memory allocation, but it imposes limits on things like recursion. Rust initially had stackful coroutines, but this was dropped in order to not require dynamic allocation and remove the FFI overhead.

The async support in Zig's standard library, once it's complete, is supposed to let the application developer choose between stackful and stackless coroutines depending on the needs of the application.

[1]: https://github.com/lalinsky/zio/blob/9e2153eed99a772225de9b2...

NobodyNada··on Tesla Recalls Almost 13,000 EVs over Risk of Battery Power Loss
It's definitely not a collective singular, you say "the moving parts are", not "the moving parts is"; and "there are hard problems", not "there is hard problems".

Either way, the usage in the original comment was exactly the same as the dishwasher example: "the only moving parts are X, Y, and Z" => "X is one of the only moving parts".

NobodyNada··on Tesla Recalls Almost 13,000 EVs over Risk of Battery Power Loss
That's not correct; you can say sentences like "The only moving parts in a dishwasher are the two pumps, the sprayer arms, the water inlet valve, and the detergent dispenser"; or "there are only two hard problems in computer science". So "one of the only" sounds just fine to me.
NobodyNada··on The longest baseball game took 33 innings to win
This is because the final few minutes of a contended game are the most strategically complex, as the teams are fighting not just for scoring and control of the ball but also for control of the clock. Usually, the team that's behind is trying to slow down the clock (minimizing time-per-play and maximizing actions that require the clock to stop between plays), while the team that's ahead is trying to run out the clock to seal their win (unless their opponent is likely to score, in which case they may want to slow the clock so they have time to respond, etc). And since the stakes are so high, the teams spend a lot more huddle time to deliberate strategy, as well as going for more complicated or unusual plays that often require more careful review from the refs.

It's by far the most interesting part of the game, but if you're only passively watching and waiting for it to be over, it can feel agonizingly slow.

NobodyNada··on EVs are depreciating faster than gas-powered cars
Isn't one "recharge cycle" a full discharge / recharge? So charging from 68% to 75% at work would just be 7% of a cycle, and about the same amount of wear as if you'd skipped that top up and just fully charged at home.
NobodyNada··on Mysterious Intrigue Around an x86 "Corporate Entity Other Than Intel/AMD"
> I was asked to relay this to binutils/LKML.

> As of 2025, the following are in active use by a corporate entity other than Intel/AMD.

> Any collisions with them should be avoided.

What's the purpose of sending this email to these mailing lists -- who cares about assigning x86 instruction opcodes other than Intel and AMD? Do Linux and binutils need to know about unused x86 opcodes in some way? And even if they did...why do unaffiliated open-source projects need to care about a nonstandard architecture extension from a company so secretive about it they won't even name themselves?

← PreviousPage 3 of 22Next →