- I wonder if I'm the only one for whom the bun project vanished completely.
In software code is only part of the package. Stability and trust are big part of it, too. And for me 1800 files change PRs created by Anthropic overseen by one person is not necessarily adding to the package.
Even it that'd be the best code and design in the world, I won't use it. I don't trust it.
- I was willing to gloss over the AI usage because I really like the Bun DX. I used Bun in Shell scripts and small prototypes before and decided to use it for something bigger.
But then in a week or so of use, tons of issues appeared. Use-after-free bugs when a client disconnects (both in Zig and the Rust port, funnily enough) which will kill Bun. Unimplemented feature which just return “0” always. Many backpressure bugs which means something like “return new Response(fs.createReadStream(bigFile))” will greedily read and OOM your box.
All of these have been reported, robobun has made fixes of various quality, but none of this has been addressed. Some of them have been reported for months.
I’d prefer Bun to work on stability rather than fancy features like image processing or threads.
- Everyone's excited about using AI to make their quick end products. But no-one wants to actually build on or rely on vibe-coded frameworks, languages, or tools.
- I am constantly confused at work that people see AI as binary: it’s either a person writing the code and taking ownership of it, or it’s AI and the poor person has no control. It’s rather bespoke or entirely vibe coded. Why? When I use AI it’s still me writing the code, I just get better autocomplete and a tool that can verify my changes using fuzzy sentence as the linting rules. Why did so many people just immediately assumed that it all must be vibe coded now? Maybe it’s because everyone hates reviewing code they didn’t write?
- I shouldn't have used the term "vibe-coded" as that's an extreme charicature. But I would argue in general heavy use of LLMs just does lead to sloppier code, and I think there's a general feel for that. Has AI use helped Microsoft make better software lately?
People live to benefit from AI for their own work, but are understandably uneasy about depending on code written by AI, even if it's (mostly) human reviewed. 2-3% more bugs may not seem like a big deal, but when you start building stacks of things these bugs bubble up and increase exponentially.
- I think AI is fine, the problem is what you mentioned: vibe coding.
Have AI do work for you, it’s certainly faster in most cases. But just know exactly what it’s generating and building before putting it into production. That’s not some massive bar to surpass.
- Yeah, but you dont know who is vibe coding and who actually knows the output of what they had LLM make
This leads to lack of trust, which the entire open source community is based on. Even if that vibe coded slop is flawless, the stigma will never go away.
- What is vibe coding?
- The term was coined by Andrej Karpathy in early 2025 where he wrote:
> There’s a new kind of coding I call “vibe coding”, where you fully give in to the vibes, embrace exponentials, and forget that the code even exists. […] I ask for the dumbest things like “decrease the padding on the sidebar by half” because I’m too lazy to find it. I “Accept All” always, I don’t read the diffs anymore. When I get error messages I just copy paste them in with no comment, usually that fixes it. The code grows beyond my usual comprehension, I’d have to really read through it for a while. Sometimes the LLMs can’t fix a bug so I just work around it or ask for random changes until it goes away. It’s not too bad for throwaway weekend projects, but still quite amusing. I’m building a project or webapp, but it’s not really coding - I just see stuff, say stuff, run stuff, and copy paste stuff, and it mostly works.
- The entire RIIR saga , not the fact that it's rewritten in a different language, but how the author selectively choose to let certain information surface without clarification, tells you a lot
Personally not interested in performative/marketing-driven decision so I am done with the project and the author. Quite disappointed
- Yeah, I have prepared our company software for migration back to node.
I would like to read the promised Jarred's blog post (if it ever comes out) before pulling the plug though.
- I’m amazed folks ever migrated to it at a workplace level TBH. It’s a VC funded runtime, something was always going to happen to it. Node is boring but its governance and ownership is clear.
- Well, it was (is?) significantly easier to use, faster, the team behind it is fantastic, and generally had enough compatibility to run the projects I needed it to.
When it’s enough of a drop-in replacement, that’s more than good enough. As long as we’re not adding a hundred bun-specific things, it’s not terribly difficult to back out of, either. Kind of a no-brainer.
- Faster I get. But easier to use?
- There is no comparison when running a TypeScript project with Bun vs with Node. Or when mixing ESM and CJS. Or when setting up unit testing.
Node and its ecosystem was considerably behind in multiple regards.
- OP said:
> it’s not terribly difficult to back out of, either
Things like ESM/CJS interop are great but backing out of an ecosystem that uses it is absolutely not trivial.
Either it’s a trivial replacement you can drop in with no changes or it’s a notable change you can’t easily switch out. It’s not both.
- Yeah. Take a look at the docs. So much niceties
- Take a look at Deno. It's pretty great and now has exceptional node compatibility
- > Take a look at Deno.
It's still heavily AI driven. Maybe less than Bun.
And they've gone in the route of just taking Node native libraries and what not just because they gave up on working out the compatibility. It's a bit of tacked on mess now.
- "Even it that'd be the best code and design in the world, I won't use it. I don't trust it."
Nothing about this sentence makes sense. What don't you trust about code you can see and audit yourself? What's untrustworthy about "the best code and design in the world"?
- I don't have the time to audit all the code in a JavaScript runtime myself, so I am forced to make assumptions about the quality of the code based on my trust of the authors.
Additionally, even if the code is good today, I am trusting their process will produce good code tomorrow (as migrating to/from bun has a non-trivial cost). A single person approving the code of an LLM is not such a process with today's technology.
- I think this is precisely why I don't mind it that much. I can't audit a huge codebase like a JavaScript runtime, whether the code is by a human from scratch or not. I just have to trust it as a black box.
I've seen LLMs produce terrible code indeed, but I have also seen humans produce terrible code. I haven't dug in to JS runtimes specifically but have read plenty of code in openjdk and cpython - there are many points that could be done better, but there's also no point since it's working, and keeping working code unchanged tends to be a smart decision in software engineering.
So of course the last point brings up whether it was a good idea to rewrite bun if it was working. Apparently the bun team thought the difficulty in getting changes in zig upstream meant it is. I don't intend to hold LLM code to a higher bar than human code - notably if the runtime continues to work, that is as good as I can expect from what is otherwise a huge black box of extreme programming (not that agile kind).
- The difference is you can evaluate a small bit of the output of a human or a team of humans and expect all their other code to be roughly in the same ballpark of quality.
An LLM can’t be trusted to produce code and make higher level project structure choices of the same quality at all times, because it can’t be trusted at all - trust is for deterministic systems. But still it begs us to trust it. Every prompt that yields good results sets us up to expect good results, so we get lazy - and then the next prompt it spews out garbage.
- As long as the odds are good enough (and/or you know the distribution), there is nothing wrong in relying on and profiting from stochastic systems despite not every outcome being positive. What matters is the sum of outcomes, not the individual ones.
It means you need to be able to handle failure, but you should always have a good grip on how to correct if you intend to set things out in the real world which messes up everything always anyways.
- Sure, but that’s not how most llm coding is done, because if a human has to carefully supervise the llm then what’s the point - might as well write it yourself.
Add to that, we’re very good at anthropomorphizing, and very bad at supervising systems that are usually right. Makes for a mess.
Oh, and this all relies on the ai providers not changing things up behind the scenes and feeding you a dumber model sometimes.
- jhack's perspetive is something that is all too common in tech. The implication that if code is open source the owners and maintainers don't owe consumers anything because "you can always fork or build it yourself"... as if that were ever possible for the average user, or in a digital world where anything you do with a computer depends on endless recursive sub-dependencies.
It's analogous to saying "it's your fault because you didn't read the T&C's", when all the T&C's you've implicitly agreed to already would take more than a human lifetime to read and understand. That is not a reasonable implication or expectation for the vast majority of people, the vast majority of the time; therefore it is logically corrupt, and should not be entertained.
This is ofcourse a fair point of view for 1-few person codebases built for fun, or to solve their own problems, open sourced out of the kindness of their hearts, but when the open source code is built or maintained as part of a job function (receiving a paycheck) &/or to generate profit (either directly or indirectly to influence standards, gain market share, etc) the open-sourcing is more of a means to build trust and becon attention or adoption in the age of relentless enshittification.
Open sourcing should not be an accepted path for profit seeking orgs or individuals to exploit and screw over consumers, as though they are eternal beta testers whose trust and dependence are worthless externalities. It also completely ignores the time and effort consumers must invest themselves to learn your product, workaround any errors, and build it into their workflow. That is arguably worth significantly more than whatever fee they could pay you for your code.
- I still really don’t understand what is so entitled about asking for a level of base empathy and care from maintainers.
People now yell at you that their only obligation is whatever is spelled out in the license they attached to the code. I think this is the same place where the logic of Code = Law comes from. People who think that you can encode the legal/judicial system into a set of axioms. This is not how the law works nor is it how it is taught and asserting this is a fundamental misunderstanding of human systems. It is incredibly destructive when people start applying maths as ground rules for human interaction. People do not live in black/white. We live in grey.
I am certainly not old enough to have experienced it, but I would venture a guess that the reason the BSD/MIT licenses originally existed was so that the universities had a CYA clause. I think you can see this erosion from a group of people sharing software in academic and hobbyist circles into weird legal absolutism as software becomes more of a business. For instance, Bill Gates’ famous letter to hobbyists or the PKZIP fiasco.
- > I still really don’t understand what is so entitled about asking for a level of base empathy and care from maintainers.
> People now yell at you that their only obligation is whatever is spelled out in the license they attached to the code.
Let’s turn your implied question around: if a person wants to share code without any expectation of care and maintenance, what should they do? Is the entire concept bogus, and the developer should just keep the code to themselves forever? Or put a “DO NOT USE FOR YOUR BILLION DOLLAR COMPANY” in a README? What communication other than the license could reasonably be provided?
I think the person you’re responding to made a pretty good point that open-source is sometimes the passion of an unpaid 1-person “team” and sometimes the product of a VC-funded attempt to buy goodwill. The idea that asking for more from maintainers is entitled is clearly suitable for the former case but not the latter. Now that Bun has been bought out perhaps they are more deserving of scrutiny.
- I honestly trust code reviewed by llms multiple rounds more than human reviewed code. Here is the thing. I don't know the human who wrote the code but i am familiar with the model they use, which might already be better than many human.
- It's called "mileage". This new codebase doesn't have any. Who knows what gremlins lurk in some of its darker corners.
- > new codebase doesn’t have any
Claude Code & Prisma use it as of last week.
- That comment had me reaching for the skull emoji.
- original comment:
>> new codebase doesn’t have any
> No longer accurate. As of last week, Claude Code (an incredibly popular CLI tool) runs on Bun’s Rust rewrite.
- Claude is riddled with bugs. That doesn’t inspire confidence.
- How can you trust that they won't just rug pull all of the code you've hand-audited when they merge some 1800 file PR written by an LLM? Even if you decide to hold off on any security updates or minor bumps until you can hand audit again, what's the point? You could just go back to Node where they aren't engaging in a modern day Ship of Theseus every other week.
- I do not agree with OP but to not understand “i don’t have the knowledge and/or resources to audit/review a language port of an entire JS runtime, but I still understand that a big-bang language port is something to be cautious of” is almost wilful tonedeafness
- First word of second sentence:
> Stability
ie: lack of volatility, ie: integrity, ie: I know it does what it says and don’t have to second guess that.
- Anthropic stuff runs on Bun, that's why they bought it. Should they be careful with Bun? Could Anthropic be a high value target for someone?
- I was already not much interested into it, now even less.
- The problem is that you need to twist the cube
- > And for me 1800 files change PRs created by Anthropic overseen by one person is not necessarily adding to the package.
Bun is mostly AI written and AI reviewed at this point (all automated).
The 1-person is luxury.
- citation needed
- go clone the repo and run `git blame`.
- might as well use openclaw at this point. that's the same vibe I'm getting with bun. from engineering excellence and jesus this guy really sweats the details (using zig woah!) to wow this is just openclaw ai permagenerated stuff. not a fan
- So you were fine with AI writing zig code, but AI writing rust is a step too far?
- For me it’s still up in the air. I won’t bet against them just yet. Also, did they say only one person reviewed it? I really doubt that. Don’t assume that what you can see on GitHub is the sum of all actions taken.
- Yea, more likely for the majority of the code nobody reviewed it. It was over a million line diff.
- If we are generous and assume a review speed of 1 line per second, that is still over 11 continuous uninterrupted days of review by a single person.
- [dead]
- Im here with ya :)
- It looks like quite a lot of analysis went into the rewrite
https://bun.com/bun-unsafe-audit
If the tests pass, then why not accept the rewrite?
An interesting article of Prisma using the rewrite:
- Just think about what "tests pass" means for a rewrite. If you rewrite from language A to language B then any unit tests have to be rewritten during the rewrite.
So either "tests pass" does not include unit tests or unit tests were rewritten probably by the same AI that is doing the rewrite!
- The good part about a language runtime is there's a massive corpus of tests that are in that language and agnostic to the implementation language.
For a JS engine that's Test 262: https://github.com/tc39/test262
For node that's its unit tests which are mostly JS: https://github.com/nodejs/node/tree/main/test
Node also runs the web platform tests too: https://web-platform-tests.org/
Bun has a similar large corpus of JS/TS tests: https://github.com/oven-sh/bun/tree/main/test
You're right about general purpose rewrites, but language runtimes are a lot easier.
- People are forgetting that "if the tests pass" is not a good measure of reliability. CS 101 from Dijkstra: tests cannot prove the absence of bugs.
- [dead]
- Given that even the unsafe audit article appears to be written by AI that doesn't seem like much thought to me.
- It explicitly says "AI-generated" at the top, so there's no doubt about it.
- Almost no test suite is comprehensive enough to cover even the kinds of bugs that will appear commonly in wide production use, let alone all of them. A big rewrite needs a lot of actual use as well to shake out the issues not covered by the test suite.
- The ones who accept rewrites are expected to support it indefinitely.
That's why Jared didn't consider using it for Bun even if it's undeniably better, they don't have human resources to support it
- > quite a lot of analysis went into the rewrite
Literally just prompted for an LLM to review it and asked for a fancy presentation. That is not "quite a lot of analysis". That is anything but.
> If the tests pass, then why not accept the rewrite?
Because (1) tests passing are absolutely not a guarantee that no regressions were introduced in a change, and (2) even if they were, those tests are the result of thousands of hours of human labour, which is all well and good for the codebase as it currently exists, but who is going to be writing the tests for the 1m loc repo of unread code in the future? Unless you've proven that specifically LLM-generated tests can prevent all possible regressions, you're condemning the future of the project because nobody will be able to continue writing robust tests.
- I hear a lot of complaints about bun but nothing concrete about what broke in the migration.
You are also assuming one prompt, and then arguing against your assumptions with zero evidence. It is lazy arm chair criticism.
- >I hear a lot of complaints about bun but nothing concrete about what broke in the migration.
Because it hasn't been released yet (at least not outside of some unstable branches). You can find some criticism of the actual slop here though: https://old.reddit.com/r/rust/comments/1t4033y/buns_rewrite_...
- Hmm, it sounds like the main example of “slop” there is 1000 global variables.
I’m curious if that matters if humans are never going to even read this code?
- >I’m curious if that matters if humans are never going to even read this code?
If by never even read you don't include attaching a debugger to solve an issue. 1,000 global mutable variables would make debugging anything an absolute nightmare.
- For us, but for an LLM with the right tooling? Idk…
- Poe's law is making it hard to tell if your comment is sarcasm or AI-induced psychosis.
- Dude, stop with “slop”. We should aim to have conversations that don’t need resort to this culturally charged BS. How about, let things stand (or fall) on their merits (or lack thereof). We don’t want or need your value judgement descriptor.
- >Dude, stop with “slop”.
No.
It's a useful term, just like "clickbait" was 10 to 15 years ago (and still is). Trying to police other people calling it slop is reminiscent of Microsoft autobanning anyone using the term "Microslop" on their Discord, it's idiotic language policing and I'm not going to do it, simple as.
- We've repeatedly seen that these test-driven LLM rewrites consistently produce absolute garbage.
- Got any specific examples? I believe you, I'd just like some concrete examples to show my coworkers.
- [dead]
- I’m the author of this PR.
This PR is an implementation of the design from https://webkit.org/blog/7846/concurrent-javascript-it-can-wo.... I think it would be really cool if JavaScript had true shared object multi-threading without compromises (SharedArrayBuffer, postMessage are not that). If we had both threads and structs, it’s likely the TypeScript compiler would never have needed to be rewritten in Go.
The title should be changed to clarify that it’s a PR to Bun’s JavaScriptCore fork and not the upstream WebKit.
This PR is scarier to merge than Bun’s Rust rewrite PR. There are a good number of benchmarks/stress tests, unit tests, and also TSAN runs and security scanner runs, but this is a more complex change than the Rust rewrite (yes, really). I’m also worried about syncing with upstream - today the “fork” is mostly a bunch of patches, but with this PR, changes to the JIT need to be reviewed for behavior when multiple threads are in use. Our best bet for this to move forward is figuring out a way for some constrained version to be upstreamed into WebKit proper, if that makes sense and if they’re interested.
And yes, the PR description is entirely Claude.
- > I’m the author of this PR.
> And yes, the PR description is entirely Claude.
If you didn't write it, you're not the author. That's how it works, man.
I would also love to read that blog post about the Rust rewrite, when you get it published.
- The dogmatism on both ends of this argument grows tiresome.
- Indeed. And so is reading “x is the real thing. Real y, real z.” Plus all the other filler crap.
If you can command a model, you can tell it to write without fluff.
The amount of effort to ask an LLM to do work is massively lower than the effort for a human to review it.
- This is at odds with the idea that devs should take full accountability for LLM generated code.
He also didn't even say the code was generated by Claude, just the description, although a decent amount of the code probably was.
- This wouldn’t fly in college and it won’t fly for me. Claiming authorship means that you did the work. If you just prompt claude, then you authored the prompt. Not whatever claude slops out.
Jarred should be putting the prompts in github, since that’s the only original work involved.
And to be clear, I don’t think that being responsible for what is produced and claiming authorship are the same thing. I do agree that Devs are responsible for what they ship.
- Tell your boss I’ll do your job for 20% of your pay
- [flagged]
- From your profile page: "Not impressed with the LLM hype"
Why have you decided to make being anti AI your entire personality?
- Why do you feel so threatened that a person is ‘not impressed’ with a thing? Is it a moral fault to have doubts and concerns now?
‘Quick! Get him! We have found a skeptic’ - sounds like a cult to me.
- Not at all, I just found it curious how overzealous they seem to be about it. I wasn't being hostile even though you are trying to make it sound that way...
- Claiming that something is someone's "entire personality" is extremely reductive and definitely hostile
- Why have you chosen to have no personality?
(If we're going by excerpts from HN profiles that is)
- [dead]
- I've seen the Bun Zig->Rust MR a few weeks ago when it was current. Now I'm seeing this, and I have to ask, since you're here:
Is there no way to make this changeset smaller?
At work, I've usually written large patches. I used to be worse at it. I was mentored out of it, and while I still like my patches to be complete, I balance that with the available bandwidth of the team and what the team can reasonably actually process.
For perspective, my "large patches" were PRs on the order of 10-12kLOC for relatively big features. I consider those to be on the upper end of what is reasonably reviewable by a small, non-dedicated team, and towards the upper limit of the kind of PR where I can speak for nearly every line of code, what it does, and why it's there.
On the other hand, now, LLMs are part of the equation, and they can (and often do) write code in insane volumes. They arguably tend towards extreme verbosity, without even talking about docs/markdown files. While LLMs are part of the workflow, my company, and those my friends work at, have all instituted policies of the developer attaching their name to the code ultimately being responsible for the output (which IMO is a lazy strategy, but I can't think of a much better one under the circumstances).
I cannot, personally, fathom how you can stand behind a single changeset spanning 2000 files and a quarter-million lines of diff. Do you consider this sustainable?
At this point the code bases are very quickly getting away from us in the open source community and even in proprietary code bases, and these are important code bases. Often very complex, often legacy. Who ultimately still owns these? Who's really going to be accountable if things go wrong?
- How the heck do anyone in their sane mind justify 10-12k LoC PRs?
And Im not even going to get into OPs monster PR
- It makes no sense. If a feature takes 10k loc to implement, it'd be a huge disservice for the reviewer and yourself to split it up into multiple PRs.
Your comment is equivalent to saying that no feature ever takes 10 loc to implement. It'd be quite ridiculous to say that aloud.
- Ideally, you could find pieces of that 10k that would also work as a standalone improvement to the app. I understand that team cultures can vary, but doing small features or refactors in service of a larger goal is nice, because while the reviewer knows you must be up to something, they can still approve your preparatory PRs as face value beneficial.
- I have some disagreement here. There are factors other than just code review to worry about when implementing changes, quite notably quality assurance.
It does not one any favours if your 10k LoC gets split in 5 changes that aren’t supposed to regress anything (but need to be validated not to) then 1 tiny on that brings things together.
Some features will be confusing for end users if you drip feed them. We had a whole host of changes recently overhauling our moderation system to be able to track and audit compliance with DSA and the key factor is ensuring the system makes sense to our users and that they can enable, have documentation and on-boarding materials for the changes in functionality and that it’s all QA tested.
In this case we did still review smaller chunks of code, we accumulated them into 1 large merge request at the end and merged it after QA.
- It's easier to justify in a fast-moving greenfield code base with a verbose language... but I won't defend it. I've gotten better and I'm still getting better at breaking these things up.
I brought the 10-12kLOC PR up as an example supporting my point of view. I don't encourage the behaviour. Most of my PRs these days fall under the 1500LoC mark, tops -- maybe a bit more if it's a tricky component that needs a ton of tests.
- you can read a 10k pr in ~1-2hr. there’s nothing wrong with a 10k pr. i would rather review 1 10k pr than 10 1k prs or 50 200 line prs.
attitudes like this make it seem like computers are incomprehensible and we’re lucky to ever land code at all
- 10k in 2hrs is 1.5 lines of code per second for 2 hours straight without spending any time to make comments, think about what the code is doing, etc.
In pre-ai era that is just skimming and trusting the person who wrote it or the code changes are largely auto-generated or there exists an exceedingly simple test suite that is incredibly verbose.
Post-ai you are ruining your code base, I probably have to spend 3-5x longer reviewing ai generated code, the code they write tends to be too verbose, mediocre, filled with subtle bugs, adds unnecessary comments, etc. If someone gives me 10k loc pr it's a sure thing they've just let the ai run loose and I'd just tell them what they need to change in general terms instead of wasting days of my time reviewing junk.
- > Post-ai you are ruining your code base
if a pr is bad, i will reject it. that's the point of code review.
- > I was mentored out of it, and while I still like my patches to be complete, I balance that with the available bandwidth of the team and what the team can reasonably actually process.
I struggle with the same issue. In my experience you can't reduce the total number of lines. If the feature took 10k or 15k loc to deliver it, you aren't going to be able to reduce that meaningfully.
You can usually break it into stacked series of commits. New code can be split up into stand alone modules, which all compile and pass their unit tests. They could even be shipped, although they wouldn't be used because the changes to the UI are always the last piece of the puzzle. If you are refactoring, you can usually find a way to split the refactor into smaller steps, each building on the previous one. That is almost certainly possible in this case.
The issue with both approaches is while you can review each step independently, what you miss by looking at just that commit is the motivation for doing it. You can only get that from the big picture, and to get the big picture you need the entire 10k or 15k loc available.
That means you have to push the entire series of commits. If you want to make it plain they are individually reviewable you push them as stacked PRs. Either way, it's a 15k loc push.
I don't see a way out of that for the same reason neither bottom up nor top down design works on their own. You have two edges - the upper (often the UI), and the lower (the OS, standard library - things you have to use to get anything done). You work from both edges simultaneously, each working towards the other, hopefully so that when they meet in the middle and the two fit together nicely. The point is, you have to review like that too. You can't just look at how neatly the blocks are stacked on the foundations, you have to evaluate if they are taking the best route to the destination. The review can fail in both ways - the UI can be beautiful but it stands on a mess, or the code could have built up a beautiful series of abstractions that bubble through to the top level and ultimately confuse the end user. So you have to review the code from both perspectives, and to do that you ultimately need to get your head around all 15k loc.
This means a reviewer demanding they be spoon fed a few thousand lines of code at a time is being as unreasonable as the person delivering 15k loc in one commit. They are demanding a simple solution to their problem, and it is wrong. They should be demanding all 15k loc be delivered in the form the author intends to ship, but split into digestible commits that clearly explain the path and reasoning taken between the top and bottom edges, so both the top and bottom level designs are plainly visible.
What happens when I do that is I get into fights over forced pushes. Everyone hates them, and for good reason. They asked for a simple change in their review, and what they want to see is a small commit reflecting their request. Hiding that by doing a rebase is met with howls of pain: "no forced pushes!". So you insert your commit reflecting just the change they asked for into the stack of commits the large feature necessitated. Doing that rebases every commit that depends on it, of course. You push the result and are treated with a chorus of "NO FORCED PUSHES".
Forbidding all forced pushes makes about as much sense as forbidding a 15k loc change, even through its well-structured into commits. It makes me wonder if unis bother to teach modern software engineering practices.
- While you're here, what's the status of the Rust rewrite and that blog post you promised to write?
- It's a strange world.
Rust rewrite: 6 days.[0]
Blog post: 37 days and counting.
[0] https://xcancel.com/jarredsumner/status/2060050578026189172
- Is it possible to merge it, but keep it disabled by default? This could allow users to play with it on Bun while maintaining the expected behavior of JSC.
Maybe a separate build could work too.
- If the goal of this change is to:
>mostly share read-heavy graphs and coordinate through a few hot objects, which is what Lock/Atomics are for.
Then it is a clear overkill to me. I’d rather built an in-memory DB on top of shared array buffer. Would work almost as good as an object graph but does not require a full system overhaul.
- I ran your proposed changes by TC39 and their initial reaction was simply "no".
Is Bun the new IE6, then?
- I have respect for past you, whose accomplishments are incredible. Current you I think of like a circus performer. I trust you to get ooohs and aaahs from the AI-race spectators who don't know any better. I don't want someone who is primarily in showbiz within 10 fucking miles of my infrastructure though
- > the PR description is entirely Claude
You should be embarrassed to admit this, let alone do it. The lack of shame people have these days is gross.
- I knew it was possible :-)
https://webkit.org/blog/7846/concurrent-javascript-it-can-wo...
- I was SO excited when I first read this article, as I was at the time implementing shared-global multithreading in a fork of JS Interpreter [1][2] and it was thrilling to think that we might one day have true parallelism in a real JS engine, not just simulated concurrency in our educational toy.
Since then I've often wondered if anyone at Apple was still working on this, or if it was just one of those things (like proper tail call support in V8) that was destined never to see the light of day.
A year or so ago I tried tracking it down again (apparently I'd not bookmarked it at the time) but alas several search engines responded only with a sea of articles about web workers.
Finally, last week I put Gemini on the case and, despite it claiming that it didn't exist and that I must be conflating memories of some other related articles it did correctly identify you as the author, after which it was easy to find the link to the original article on your blog.
Since re-reading it I've been wondering if it might be possible to implement it with help from AI (not having written any C++ since before the turn of the century I don't think I'd be too successful doing it unassisted!), or whether JSC's internals might have drifted too far in the intervening years.
It's delightful that someone else has take a stab at it, and I look forward to seeing where this leads.
Thanks for all the work you did laying the groundwork that made it feasible to even contemplate, then contemplating all tricky details and writing the answers down in the form of such an inspiring article.
[1] https://github.com/NeilFraser/JS-Interpreter [2] https://github.com/google/CodeCity/blob/fa1bd2734b806559ffaf...
- In case anyone missed it, this PR is based on that:
> This is an implementation of the design Filip Pizlo published in 2017: "Concurrent JavaScript: It Can Work!".
- Years ago I did "multithreaded Javascript" by calling into Rhino (Javascript engine) from multiple threads. Granted, I converted Rhino from JVM to CLR, so it wasn't exactly a stable environment, but it did "work".
- I remember reading that article some years ago.
Boy, wasn't I surprised when I ran into this PR. I'm excited.
- That's excellent work and a great read, Filip!
- It’s certainly possible, but I worry that weird things can happen when doing something as “simple” as defining a property if another thread is messing with the prototype chain. Even thread safe property maps can’t entirely save you because operations that need to go up the prototype chain are not and cannot be atomic.
- My blog post explains how to make prototype chain operations work in the presence of threads
- This won’t work well without a few other things, like structs
- Structs aren’t necessary for my proposal to work well
- Yes, you did. And it's a good design. You even did the GC question justice.
My concern is more in the spirit of "Your scientists were so preoccupied with whether or not they could, they didn't stop to think if they should.". Of course JS being single threaded wasn't a hard constraint. Lift it, and people like you can use the parallelism to do great things.
The problem is that most developers are not you. Shared memory concurrency is foot-artillery (especially if truly parallel). Adding threads to the JS ecosystem is selling W48 nuclear artillery shells at the toy store.
JS's ostensible limitation to a single thread forced users to do what they should have been doing anyway: message-passing, thread-per-core architecture, and actor-ish stuff. People who don't know better reach for shared memory concurrency because it seems like a good way to solve problems, but it's actually a dangerous attractor in idea space. JS engine limitations were accidentally keeping people away from it. Now that they can hear the siren's song of a mutex, they'll run around on the hard problems of parallel programming.
Now, that's not a reason to avoid shipping such a system. It's just not something I would have chosen to implement for the masses.
- I don’t understand the thread phobia
Comparing it to nukes is a bit extreme, don’t you think?
- I don’t think it is extreme. Imagine this is added to WebKit. Now I have a new question to answer - can I use library X across multiple threads? How do I know it does not have a little cache inside which breaks if I call it from multiple threads?
Another issue is lack of memory model (sorry if ai missed it) which means memory updates will be published to threads differently on different architectures.
And then an obvious problem of mixing async with locks - never ends good.
- > Comparing it to nukes is a bit extreme, don’t you think?
Does Herb Sutter strike you as extreme?
https://herbsutter.com/2013/02/11/atomic-weapons-the-c-memor...
- This is consistent with the endless contempt people have had for JavaScript and those that use it.
- Yeah I don’t get that either
It’s a super successful language
- I think with ES6 and newer things really cleaned up and now we’re left with avoidable ugly parts, of which every language has.
Before when you didn’t even have strict equality checking, for example, you were forced to know about implicit type casting.
Getting on the same page with modules also helped a lot. Typescript directly in Node is great. Look mom, no build system!! I’m just hoping one day browsers will accept TS the same way.
- > I’m just hoping one day browsers will accept TS the same way.
Wouldn't that be a direct kill of JS?
- TS is JS just with stuff on top so it can’t really ever kill JS. The way Node does it is to just ignore the type notations in a TS file, making it valid JS. Does mean you can’t use things like enums but worth the price.
- When did JS not have strict equality?
- 1995-1999. Strict equality was introduced in ES3 which was first released in December 1999.
- The parent said 'before ES6', I suspect they were not thinking of 1999.
- You still need a compiler for TSX, though. There's also a tiny bit of non-erasable Typescript (enums).
- There’s a mode to pretend those features don’t exist and not allow them. Meaning it gets far simpler to just type elide rather than any actual compilation effort. I think this idea is getting more popular and it would be kinda nice if TS committed to not adding any more features like that.
- TS has committed to not adding any more features like that. Features only get added when they reach a certain threshold on the TC39 standardisation track.
- It's successful because it's been kept away from the kind of programmers who think the time spent to endlessly specify everything four times is nothing compared to the sadness of losing a byte or a cycle. These are the descendants of people who hundreds of years ago would have insisted that real work is in Latin. C++26 is available for them, or Node/React with hundreds of dependencies if they want JavaScript, or they can even compile and run whole operating systems into WASM now, or anything else. Just let JavaScript be the domain of people who do other things for fun.
- Worth noting that javascript has had workers, shared memory and atomics for years and that you can use them today. Look at this guy writing a lockless allocator: https://greenvitriol.com/posts/lockless-allocator
The only difference in this PR is that it makes threads light (workers are fat because they carry a whole v8 instance with them) and it makes shared memory default with light threads (now you need to pass a shared array buffer first).
Javascript is probably not your first language, I get it, but it has had "the siren song of a mutex" for years now. What really surprises me and I can't explain is why you went and took time to express such strong opinions on something that you obviously don't even know or use that well.
- js does not and has never had shared native objects between workers. there is a vast gulf between "here is a shared array buffer, feel free to interpret these bytes on another thread" and "your existing { ... obj } code just works but now is threaded".
shared array buffer is a decent primitive but nothing in the language uses it. if you want to make existing code that uses JS objects multi-threaded on top of shared array buffer, you might as well port it to Go -- it would be less work than rewriting it to use raw byte arrays.
- There's a difference between 1) having a shared-everything heap and 2) having a separate, obscure facility (which practically nobody uses) for building a special data-only portal to shared memory. #1 normalizes the mutex. #2 doesn't.
I have strong opinions on the superiority of #2 to #1 because I've dealt with endless bugs caused by people who think they can handle #1 and can't. Reasoning about complex memory order rules and thread interleaving is extremely difficult for both humans and AIs. That's why we abstract over raw threads with actors, STM, fork/join facilities, and (my favorite) structured cooperative concurrency. It's not a knock against anyone's skill to point out that EVERYONE gets concurrency wrong and we need guardrails on top.
That said, let's be honest: the JS ecosystem has a culture that'll make #1 worse than it usually is. There's a certain combination of insularity and lack of restraint I've observed in the JavaScript world that prompts its members to re-learn the hard way all the painful lessons in software history.
- #2 is very much used in high performance web apps, whenever you can't afford the overhead of message passing. I agree it's a specialized tool and normally you don't need it, but it's a misrepresentation to say "it's an obscure feature that almost nobody uses". If you do webGL, for example, you almost invariably end up using shared array buffers.
- Look, I’m not an AI hater, but AI is… not great at multi-threading code. And having it analyse multi-threaded code proves nothing because… it’s not good at multi-threaded code. This isn’t entirely shocking because I’m not good at it either and need to write in some very particular ways to have even a hope of being correct. But basically, unless it was written by a genuine expert, I wouldn’t want to even glance at this PR. And it wasn’t.
- I don't think AI is particularly worse at multi-threading code than humans are: humans are notoriously bad at it. I've had reasonably good success with telling Claude and Gemini to go into a codebase, insert clang -Wthread-safety annotations, fix any issues it finds, and refactor code that isn't amenable to the annotations to make it possible.
- But there are any number of humans who will tell you that humans are bad at multithreading the codes and all but the smallest codebases are headed for heisenbug deadlock city if you do things like they told you to in that Introduction to OOP with JavaTM book.
But is Claude going to tell you "No, dear user, this project is going to follow an excessively simple and sub-optimal locking regime because experience shows that it is easier to write code than it is to reason about its exponentially-growing complexity" ?
- The code needs to be not in the state of "no obvious bugs", but "obviously no bugs". Especially the programming language runtime. Otherwise there is no hope you can sustain any development whatsoever
- No language runtime is ever in a state of "obviously no bugs".
Good luck demanding that of anything of JSC's or LLVM's complexity
- On one hand, sure, the entire point of a programming language is to make complex ideas able to be expressed in simpler abstractions. On the other hand, we can damn well try.
- Damn well trying to enforce an "obviously no bugs" rule in a language runtime would mean zero progress in language runtimes.
We certainly wouldn't have gotten to where we are with runtime and compiler quality and performance if we had damn well tried to enforce such a rule
- IMO the very minimum requirement should be that you've demonstrated effort to reduce unnecessary complexity of the problem. Sure, some problems are complex enough that there might not exist an obvious solution, yet usually after a while once you're familiar with some topic the existing solutions do start to appear obvious. If they're not I'd argue we're doing something very very wrong
- Adding concurrency to JavaScript definitely falls in the "complex enough" category
So does basically any feature or optimization in a JS runtime
- I think it's also worth distinguishing _problem complexity_ and _solution complexity_. The problem might be really really hard (and it very obviously is in the case of adding multi-threading to JavaScript). But it does not mean that the solution has to be hard to understand. It doesn't mean that any average PHP developer (I can say that, I started with PHP) should be able to verify the correctness of the patch, but for a person who is well familiar with the area there shouldn't exist areas they can't understand.
Look at the description of your own Fil-C: it focuses on clarity of explanation of how it works, and it actually does make sense (and, hopefully, works well enough too). Compare that with the pull request sent here. I'll wait
- The solution to concurrency in JS is hard to understand and I would expect even hardened JSVM folks (me included) to be super confused by it
- I think you're underselling your own level of intelligence Fil. If even you would be confused by an implementation (and you're the author of the concept) what chances do you think this PR has to actually work correctly?
- Lots of tests
- Yes. People are losing the plot and embracing corruption with logic like this:
There will always be a few employees stealing. So why don't we just use this system that consistently and randomly introduces theft into every level of our cashflow. We can't expect perfection!
- Perhaps then it would be better to not use tools of this level of complexity.
- I think LLVM is a perfect example of what happens when it's too complicated: it's slow, it's bug-ridden when you stray away from the beaten path (e.g. Rust hits bugs in LLVM like this one https://www.reddit.com/r/rust/comments/l4roqk/a_fix_for_the_... ), and it's really hard to use and understand.
It's obviously not useless because of that, but it's a great example of what happens when you cannot fully control the implementation complexity
- So don't use compilers at all?
- Compilers aren't made equal either. E.g. compare Visual Studio C++.NET compiler and something like Go. And Go isn't that simple either to be fair
- how would you suggest we compile literally anything?
- Won’t happen unless the thing is implemented in lean4.
- Proving something is correct doesn't automatically make it obvious though. For it to be obvious it needs to either be intuitive or it needs to be (reasonably) simple
- This em-dash stricken PR is yet more evidence that the bun project has AI psychosis.
The most important feature for a language runtime is reliability. It's the foundation, it should be boring. I need to know that the foundation is stable so that I can control the reliability of whatever's built on top.
AIs hallucinating a multithreaded JSC is not boring, it's scary.
- >Scalability, measured (the honest section)
Ugh.
- The entire PR description is filled with LLMisms. I find this style so hard to read, it’s almost nauseating these days. My eyes start to glaze over and I stop reading pretty quickly after. I’m having to deal with this a lot at work these days unfortunately. I mean, did anyone even read or verify this output? When I read this type of stuff, I have the nagging suspicion that I am the proofreader and I have to do the verification myself. At that point, what are we even doing? I can generate Claude output myself…
I know I’m being overly dramatic but this sort of thing feels so wrong and inhuman(?) to me for some reason.
- Yes, that's the smoking gun!
- 151 commits, 1826 files changed and claude found 0 smoking guns? I call bullshit. It found 3 in one run-of-the-mill query the other day
- I can't stand Claude's "honesty". Anthropic should hire some writers and linguists to make the output a bit more bearable. It's mentally taxing to read this type of dull text for hours every day.
- I just can't do it. I barely skim Claude PR reviews and have no qualms asking someone to summarize in their own words if they've sent me two pages of Claude slop
- almost spit out my drink!
- It’s pretty incredible to me that a mammoth change like this is possible to prototype now using LLMs.
It makes me wonder how much of our software stack will become more malleable to big ideas and experiments in the future, like Filip’s idea here. Even if you don’t want to merge the code, it’s still an incredible existence proof that something like this could work.
- Bingo. Dozen LLM-prototypes and then a manmade final patch which is merged.
- Is there a human-authored description of the PR anywhere?
How are there not race conditions all over the place?
- Putting on my tinfoil hat. Did Anthropic even buy Bun because they actually use it or was it just an excuse to lob ridiculous PRs at things with at least a little bit of credibility behind them. Their way of trying to set a precedent for accepting AI code into bigger open source projects.
- The author has huge online following, and influence over developers. I don't doubt the author is genuinely interested in this, but the employer definitely is supporting this too.
- Ive said many times in my day-to-day convos around AI that Ive come to realize more and more that AI is a solo endeavor. Its very difficult to scale things to more people if you are trying to use AI for more than just speeding yourself up.
AI is the epitome of the saying "if you want to go fast, go alone". This PR and the rust rewrite are incredible in scale and ambition. I still think theres a middle ground though of traditional committee-driven design with AI-driven iteration and POCs.
- This is terrifying. Evidently based on prior art by Mr. Pizlo – indeed, where's the acknowledgement of that?? (edit: I missed it) – but I'm assuming that was never translated into code.
I love the idea of experimentation and innovation; I abhor the idea of it being dependent on Anthropic and their theft. I've never rooted for the Chinese labs more strongly than after seeing this.
- Back when Node was the new kid on the block, the single-threaded async model was justified by pointing out that the major challenge with multithreading was shared memory. It's one of the strong points of the language / environment, because you never have to worry that some callback will run on another thread.
Javascript shines when it's handling multiple concurrent IO operations, and concurrent operations can become very thread-like with async/await syntax. Multithreaded code in this context only helps with CPU-bound operations; but if I was doing something CPU-bound, I'd probably choose a different language.
One thing I wonder, does Bun (or Node) have a way to call into native code on another thread, but still keep single-threaded once back in JavaScript?
- yes, all of node.js is built on such operations. what do you think is happening when you `await fs.promises.readFile(name, 'utf8')`? it dispatches a libuv thread to read the file you want, and resolve the promise when the background thread has completed the operation.
- Except there is often no background thread but async IO.
- think of all the poor web devs trying to use multiple threads on top of asynchronous operations. wild.
- Standard contempt for web developers.
- I mean if they hadn't constantly reinvented the wheel by refusing to learn about existing technologies, and if they hadn't then effectively forced web dev garbage on the rest of the programming world via their sheer numbers, then they might not have earned such contempt. See React in the Windows start menu or Claude's CLI being written in React as two of the most egregious examples (but one of only many).
As I saw someone here on HN describe it a year or two ago, it's like mayflies debating politics.
- Worth noting it's not web devs pushing for React in the Windows start menu. It's PMs looking at the problem and concluding React is the least painful way to solve it (correctly or incorrectly, but I doubt they optimize for the same measurements you do).
Ink (the React renderer) in Claude code, on the other hand, makes a lot of sense for interactive CLIs where you want to componentize your menus and dialogs. Actually not using a component framework normally ends up in state / render chaos.
Re: mayflies debating politics: React has been there for 13 years, and while the interface has shifted a couple of times (object factories to classes to functions), the main idea has always been really simple and really stable: isolated declarative components that can optionally have state and side effects. Many other popular frameworks have come and gone in the meantime.
- > Scalability, measured (the honest section)
Barf
- Heh, are the other sections dishonest, then? Yuck.
- For what it's worth: this isn't a PR on mainline WebKit. The PR is on bun's own fork of WebKit (and JSC), which already has a bunch of their own changes.
- Did they rewrote WebKit in Rust or not yet?
- I'd actually love to see a relatively high-performance (i.e., including a decent JIT) runtime for a dynamic language that's written in Rust. There's a lot of implementations like Rust Python, the Boa JS engine, etc. that are purely interpreted – and fun! – but I haven't seen a proper, high-performance VM yet.
I considered writing such a JVM in Rust, following writing one in C (https://github.com/anematode/b-jvm) that could JIT WebAssembly code and run in the browser, but decided it would be too time-consuming.
Obviously such a VM would involve a lot of unsafe, but I'm wondering if you could establish some proper, compile-time-checked invariants that make things a lot safer, without the complicated sandboxing that modern JS runtimes use to make it harder for JIT bugs to escalate into full blown RCE.
- rust seems alergic to the un-safety required of "i dynamically built this executable code segment just now, please jump into it"
- wasmtime exists
- yes i love to use a language runtime within another language runtime for a sweet sweet 30% performance penalty
- Why the snark? wasmtime is a (pretty popular) Rust project which uses a JIT, demonstrating that it's not incompatible with Rust. Obviously a proper VM wouldn't depend on wasmtime, but implement its own JIT and paraphernalia.
- fair. i guess i used “rust” in collective noun sense for “rust the ecosystem and community”; from my armchair experience there’s a big contingent of that community that abhors unsafe and software that uses it, and it’s that community/ecosystem aspect that prohibits unsafe since of course the language and compiler support it just fine.
- One of the biggest things preventing software like SQL DB's from being written in TypeScript is the lack of proper threading.
I genuinely think you could write a competitively-performant multi-threaded DB in Bun + TS if you had shared-heap threads and fast atomics/locking primitives.
- "I genuinely think you could write a competitively-performant multi-threaded DB in Bun + TS if you had shared-heap threads and fast atomics/locking primitives."
Not likely. Databases that attain any significant use in the field end up getting optimized to the n'th degree because they're the bottleneck of the entire system of every system they get put into. Javascript runs on the "5-10x slower than C" language tier. Personally I think even picking Go, in the "2x slower than C" tier, is a huge mistake, though a few people seem to be doing OK with it. I don't think you can call it "competitive" when your C++ or Rust competition is consuming a factor of magnitude less resources.
WASM DBs, maybe, especially as it continues to mature. Not Javascript.
- Something compiled to WASM still gives a fair amount of control over memory layout, something that AFAIK is not possible in JS without building effectively a new embedded language on top of an array (Emscripten being an existence proof that you can do more or less anything that way).
One place where an interpreter + JIT language could be interesting is if it were sufficiently safe to allow user code into the query execution engine, such that the JIT could optimize it all together.
- Yeah I kinda agree about Go. CockroachDB didn't catch on nearly as much as it should, and I wonder how much it has to do with the fact that optimising code in Go (both in terms of memory usage and performance) is just much harder than C
- You have web workers, and for shared memory and synchronisation respectively SharedArrayBuffer and the Atomics namespace.
- Exactly. Nothing stops your writing a high-performance parallel database in TypeScript today. Given that runtimes and tooling are actually pretty good, I think TypeScript is actually a fine choice of language for the task.
The only thing you can't do with JS today is share a heap across threads. You have SharedArrayBuffer. You have atomics. You don't need a shared address space.
There's a high performance database called "PostgreSQL" you may have heard about. It doesn't use threads. It uses separate processes and shared memory: just like standard JavaScript, with its service workers and SharedArrayBuffer.
If not sharing an address space is good enough for PostgreSQL, it's good enough for your TypeScript database.
The problem with shared-everything, unmarked, preemptive-parallel concurrency is that 90% of the time it gets used by people who don't know they shouldn't.
- SharedArrayBuffer gives you a byte array, and asks you to re-implement the entire JavaScript universe on top of that. String -> use TextEncoder to copy in / out of a byte buffer. Object/class? Sure, devise your own protocol to serialize + copy instances in/out of a byte array. Even basic arithmetic operations on a TypedArray over a SharedArrayBuffer is slow AF in v8 compared to a "native" JS Array<number> for small-medium integers, because our current JIT compilers can jit the fuck out of regular arrays but struggle with TypedArray stuff. It's so sad.
- > Even basic arithmetic operations on a TypedArray over a SharedArrayBuffer is slow AF in v8 compared to a "native" JS Array<number> for small-medium integers, because our current JIT compilers can jit the fuck out of regular arrays but struggle with TypedArray stuff. It's so sad.
Yeah, that sucks, but at least it's just an implementation problem. Java's analogous ByteBuffer methods have been fast compiler intrinsics for a long time, so there's an existence proof of this stuff done right.
- This sounds pretty insane if you wrote any database code that needs to care about memory management at all
- Are you hoping to, like, run postgres in nodejs or something?
You can get parallelism with web workers and shove sqlite over there if you like, e.g. for running more intensive queries. Beyond that I kinda don't see much of a reason to use JS for databases, except maybe for isolation (e.g. via wasm).
- I honestly should print that comment and hang it on a wall.
> …competitively-performant… Care to explain competitively to what?
- …but why? JS/TS does not seem like the right tool for the job?
- It's probably what they know so not anything new should be learned.
- I'm curious to hear from people if anyone who uses Bun after this changed has noticed any day to day differences with the rust version over the zig version
- The latest version of Claude Code is the compiled with the Rust version of Bun, I've been using it and haven't noticed any regressions.
- Anslopic
- I am shocked by how good and comprehensive the bun docs & ecosystem is.
Its so well contained I never need to look outside its ecosystem for basic components. It's a true "Batteries Included" runtime.
- Last time I read the bun docs I spotted an off-by-one bug in sample code, so I opened a github issue. An AI bot responded, confirming the issue, and opened a PR to fix it - A simple "+ 1" added in the right place. Two other AI bots reviewed the PR, which went on for several rounds of "improvements". Last time I checked, neither the issue nor the PR received any human attention (actually I just checked again, and the PR has been closed by stalebot).
- > (actually I just checked again, and the PR has been closed by stalebot).
Can you provide the link?
- I, too, was curious to see it in practice.
Here is the ticket opened by @retr0id: https://github.com/oven-sh/bun/issues/28030
And here is the swarm of bots / LLMs / agents that open, review and bikeshed the PR before it's closed by the stalebot: https://github.com/oven-sh/bun/pull/28031
It's hilarious. But also a little sad.
- Yup, that's the one.
- That's pure comedy
- Ok, you didn’t lie, it’s extremely funny, the stalebot at the end is such a good punchline!
- Here's a trivial docs issue I opened, where I had a similar experience:
https://github.com/oven-sh/bun/issues/31233
The difference is that the PRs to fix that problem were already open when I created the issue. I was unaware of them (I only searched for duplicate issues, not PRs addressing the problem). The robobun comment implies there are 5 open PRs addressing it, but I could only find two. They still haven't been merged, a month later.
https://github.com/oven-sh/bun/pull/30677 <-- later rolled up into:
- Utter dysfunction. I ripped out bun from my projects after the vibe Rust rewrite, but seems like the problem has existed much longer...
- Bun is so good that can’t be used as server and only as local script runner.
https://discord.com/channels/876711213126520882/148058965798...
Leaks memory left and right. And the core team seems unable to fix it.
- Yet I rarely hear about it being used in production systems and replacing Node.js.
- From what I've heard there are two main use cases:
- People use bun as an all-in-one frontend web bundler. Personally, I just use esbuild (and webpack, if I'm working on a system using its module federation, like Jupyterlab). My understanding is bun has a machine-translated port of esbuild (ported to Zig, then to Rust) built into it.
- Claude Code runs on bun.
The second point has to be why Anthropic acquired them.
- Somehow claude-cli left open completely nerfs my laptop's battery life. Is this a bun feature?
- It famously is extremely memory leaky, with the core team having no idea how to fix it. With the new AI-automated unsafe Rust migration, this piece of slop may never actually become production-ready.
- tbh, that looks like AI psychosis caused by getting access to unlimited tokens
- Great, this will be the savior of software devs - as the last memory safety bugs are being patched, a whole new world of javascript multithreading issues to fix opens up.
- I like how the page is actually struggling to load due to the sheer amount of bot activity on the PR.
On a completely unrelated note, I wonder why Github is always down. Real mystery there.
- Eh, Firefox/Thunderbird had multi-threaded JS in SpiderMonkey in the late 90s.
Then it was removed it because it made garbage-collection a real mess (the JavaScript gc needs to walk through lots of C++ data, some of it may have specific requirements for destruction/finalization).
I hope it's better this time :)
- This has me thinking of Python's NoGIL movement.
- I would just like to point to a single issue that has major ramifications in using Bun:
- Don't have much to say on the topic but recalled this excerpt from the book Coders at Work in the chapter interviewing Douglas Crockford.
``` In my experience, the worst bugs are the real-time bugs, which have to do with interactions with multiple threads. My approach to those bugs is to avoid making them. So I don't like threads. I think threads are an atrocious programming model. They're an occasionally necessarily evil, but they're not necessary for most of the things we use threads for.
One of the things I like about the browser model is that we only get one thread. Some people complain about that—if you lock up that thread, then the browser's locked up. So you just don't do that. There are constantly calls for putting threads into JavaScript and so far we've resisted that. I'm really glad we have.
The event-based model, which is what we're using in the browser, works really well. The only place where it breaks down is if you have some process that takes too long. I really like the approach that Google has taken in Gears to solving that, where they have a separate process which is completely isolated that you can send a program to and it'll run there. When it's finished, it'll tell you the result and the result comes back as an event. That's a brilliant model. ```
- Soo... Essentially, still threads, but no shared state between threads, and they talk through this message interface?
- Threads which can’t share state are called processes.
- Fair-ish point, if a bit cheeky. But threads can be still threads, i.e. in the same address space, but without actually having shared state between them. And then they're still threads, not processes.
You could also have stuff like message ques going between them, the cost of passing data around is small then, you don't have do leave user space to put stuff in the mq's. But can you still call it "not having shared state"? I'd say yes, even though you do share memory and you do have the mutually accessible que. But I can see why you could argue otherwise.
- > Fair-ish point, if a bit cheeky. But threads can be still threads, i.e. in the same address space, but without actually having shared state between them. And then they're still threads, not processes.
If they don’t share state implicitly, then by all relevant features they are processes. That they share an address space is not really relevant except as an opportunity for optimisation. See BEAM.
Hell, older consumer OS used to not have memory isolation, even after multitasking was introduced.
- this is why operating systems have forbidden threads since 1999 and no one has ever used them since.
- > Shared-memory threads for JavaScriptCore. new Thread(fn) runs fn on another thread, in the same heap, with the same objects. No structured clone, no message passing, no SharedArrayBuffer-only escape hatch. You share an object by sharing the object.
If you can't even be bothered to write a non-slop PR description, it doesn't bode particularly well for the content of the PR itself...
- I previously gave this author and the bun rewrite the benefit of the doubt. But an obvious slop PR to the WebKit repository?
I'd tap out here too if I was a maintainer. Even if the change was perfect, if you could not be bothered to write the PR description, I am not going to waste my time with it.
Edit: My bad, the PR is to a fork, in that case it's not our business how the PR description is written.
- It’s a PR on their private fork, they’re not expecting to have this accepted upstream.
- This LLM PR description style is getting very tiresome. The obvious signs are the little lists (“not x, not y, not z”) and pompous declarations like this:
“The bring-up log at the bottom is honest about what broke and what it took.”
- I know a thing or two about VMs. Reading this post, I thought to myself "No way it was this easy. No performance hit in the single threaded case? No way".
I was right. Buried in the middle of the post is this tidbit:
> v1 collects synchronous and stop-the-world
Ah, there it is! I knew it!
Parallel garbage collection is a very hard problem. Years of experience and subtle implementation are required to get something like ZGC. A stop-the-world garbage collector will kill tail latency in many use-cases, especially for large programs. I'd say a good GC is the hardest part of a modern VM, even harder than a good JIT: not that a JIT is easy.
Show me multi-threaded JS with generational mark, sweep, compaction, etc. running in parallel with the mutator and I'll be impressed. (The smart thing would be to base it on the JVM or CLR. Doesn't count though.)
It's all so exhausting, this current programmer culture of doing the easy part of a system thing X and presenting your work, without qualifiers, as a complete and modern X.
Sure, sure, we can have memory safe C (just don't have any data races!). Sure, we can have an AI C compiler (just don't expect type checking). Sure, we can port SQLite to Rust (but don't expect it to be fast). Sure, you can one shot a Slack clone (just don't expect performance or security). Doing the easy part of a thing is not doing the thing! You can't trust a README's feature list these days.
To be fair, given that the README is obviously unedited LLM output, the authors might not have realized that their agents cheated and made threading easy by pessimizing the GC. The LLM certainly did though.
Now, maybe the JSC really is adaptable to a multi-threaded mutator world. If it is, great. But over and over, I've seen AI say "I will defer and charter $HARD_THING" and mean "I have no idea how to do $HARD_THING, so I'm creatively reinterpreting your request to make it easy". You have to be endlessly vigilant for LLMs subtly twisting your tasks into easy versions that might technically meet the requirements but they are less complete than you intend.
- I sometimes wonder if full GC is really worth it. For a lot of applications some compile time analysis + refcounting is close enough, and for some others arenas (per frame rendered, per request served, etc) are as fast as a GC to allocate and faster than malloc to free. Could we make the rest a compile error and save most people most of the time a lot of pain?
- GC is worth it. What you're proposing is a false economy.
In addition to lifetime management, GC gives you compaction, pointer compression, and fast bump-pointer allocation that doesn't depend on being able to represent your lifetimes as nested arenas.
Modern GC is excellent. Replacing it with manual allocation isn't better, even with guardrails: reference counting is expensive, atomic reference counting doubly so, and free() itself is very far from free.
Sure, you can restrict lifetime shapes, but when you do that, people switch to allocating out of arrays and using indices as pointers, so you're right back where you started with respect to lifetime management.
So what are you saving? You're just replacing the high-performance concurrent mark/sweep microsecond-pause GC someone has written and debugged for you for free with custom convoluted logic that'll probably leak and run slower besides. Why would anyone want this trade?
The elevation of manual memory management to standard performance practice is a generational mistake this industry is making.
- How modern is modern, and who's implemented it? In recent memory (last decade or so) I've had to work around the GC by doing exactly what you describe with arrays as well as off-heap storage to avoid memory footprint and pause issues across Java, Go, and Javascript. Writing something like say Objective C (with its refcounting, autorelease pools, etc) seemed pretty productive, had predictable behavior, etc. I follow GC development a bit, and often cite some of the stuff Gil Tene has written as an example of clear technical writing and thinking, but I'm not convinced GC is that universally good. Rust's approach has a high ergonomics cost but the Swift people seem to get by.
- In contrast, I don't know that much about VMs.
But if you're making a big fundamental change to a system, I do know that it shouldn't start with a single "+279,276 -4,272" PR. It starts with a small patch with the core of the change so that everyone can understand what it does and how it works. (I mean, ideally, a change like this starts with documentation, discussion, diagrams, surveys of existing implementations, etc, before you start writing code)
You don't cram everything into a single 270K line PR, even (especially) with an LLM, unless you specifically don't want anyone else to look too closely at what you did.
- Bun alert!
- Imagine somebody doing a drive-by on your repo and dropping a 270k loc PR expecting you to merge it. Bonus points if they can't even put in the 0.001% smidgen of effort to write why they think the PR is useful or necessary in their own words. Oh, but we don't have to imagine it, because there are people who actually do that!
- The PR is against bun's fork of WebKit, not upstream.
- Oh, my mistake, I thought they were doing the zig thing again.
- They didn't open a PR against zig either, the compiler concurrency work they did was also only ever in their own fork.
- Counting 62 em-dashes in the PR description alone, are people reading those walls of slop anymore?
- Course not. They have an LLM summarize it for them.
- No human has ever read or will ever read the PR description.
No human has read or will ever read any of the code, nor was any human thought involved in its creation.
Everything is performative now. As long as you just keep your eyes closed and believe it all works, that's all that matters.
- Does it not work? I'm watching for the explosion and following "told you so"s.
- To all the people saying "it's dangerous to add concurrency to javascript", javascript has already workers, shared array buffers and atomics. It's entirely possible today to start two or more workers, pass a shared array buffer via a message and then write concurrently on the same buffer forfeiting message passing and synchronizing only using atomics. You can even do lock less data structures, see for example https://greenvitriol.com/posts/lockless-allocator. That's what you do when you write high performance Web apps. This proposal only adds lightweight threads sharing memory by default, but it's by no means the first and only way to do low level concurrency with javascript.
- This is from PR: v1 collects synchronous and stop-the-world
Go build performant web app that has stop-the-world all the time.
- You bypass GC by allocating pools of array buffers at the cost of low-level memory management.
- So you add threads to allow a shared objects graph with a side effect of more frequent stop the world. Then you fight stop the world by resorting to low level memory management. But if you go level why not allocate a shared array buffer and share it across workers? Something you can do today without threads.
- I know a ton of people absolutely hate this level of "LLM code + LLM PR description + LLM PR review" but my boss would have an orgasm if I was able to use AI half as well in our org... :/
- Just stop caring about quality. It makes it 10x easier to produce slop with AI if you never bother to check
- I just wrote an internal report in my company.
My conclusion from the project I'm working on is that, as of this day, there is no way to have both this so-called 20x performance improvement _and_ any kind of quality. Or security if whoever is running the agent has any token in an .env anywhere on the same file system.
We'll see in which direction the CTO takes this. My bet is not on quality.
- The company I work for, the code Opus 4.8 is able to generate, is higher quality than what was left behind by 10+ years of contractors that have come and gone.
- I understand that some developers produce very poor code. Maybe in some companies it's the norm. Luckily for me, I've seldom worked alongside such developers.
In my company, the code Opus 4.8 is able to generate appears competent, but if you dig a bit, it contains way more timebombs than anything I've seen the team members develop.
- Time bombs and just 2-3x the amount of code for the same thing. I recently rewrote a Claude generated feature from 3000 lines to 800. I guess AI fans are just predicting that no one will have to read the code in the future or something like that.
- Yeah, I suspect the 2-3x amount of code, but I can't prove it yet. This will wait for the next report :)
- Software Engineering may have very well entered its own Eternal September.
- It is sad. This is a new reality. No one reads code, it is agents all the way down. It has been long enough now that I can safely say AI has not sped up project delivery nor improved quality when it did ship.
Is it the AI or the people using it? Idk
- Humans made the AI, and their goal is profit, so there’s no AI using people: it’s humans using people.
- It is sad. This is a new reality. No one reads machine code, it is compilers all the way down. It has been long enough now that I can safely say C has not sped up project delivery nor improved quality when it did ship.
- > Just stop caring about quality.
I'm not so sure this is true anymore. It may have been years ago but... can you honestly say "the Bun project was fully AI written, therefore the quality is poor"?
Any concrete examples/proof?
- [dead]
- Amazing. This is what the Typescript team should have done instead of rewriting to golang -- innovate the runtime.
- That doesn't help anyone using Node. I don't want to have to start using a new runtime because my compiler is slow. That's wild.
- You're already using a new runtime with tsgo -- it's golang at build time -- but still running Node in prod, so the same could work here. :-)
Agreed I would not want all Typescript users forced to use /this/ runtime, but if the TS team shipped tsc as "oh now it's uses a special fast JS runtime" (just like tsgo is a different runtime) I'd love to at least have the option of using the same special fast runtime in my own still-written-in-TS apps.
Seems I've either struck or a nerve, or miscommunicated, given the insta down votes.
- if there was a thingy that compiled JS to a 10mb native executable with shared heap multithreading, im sure we'd use it. however, no one has invented such a thing. until this pr.
- Right! That's why I think this is an exciting development.
I assume everyone is downvoting me for "liking LLM slop", but really I just like the competition that "this is possible!"
And would love a slop/non-slop/whatever version in Node/v8. Someday!
- same. ts with thread + struct would be a killer language.
i pray anthropic buys roblox to get pizlo to actually land this