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

> Larry Ellison ... who owns it.

> who

Do not fall into the trap of anthropomorphizing Larry Ellison!

https://www.youtube.com/watch?v=-zRN7XLCRhc&t=2300s


Thanks, made my day

Another vital quality of good QA teams is that they often serve as one of the last/main repositories of tribal knowledge about how an org's entire software system actually behaves/works together. As businesses grow and products get more complex and teams get more siloed, this is really important.

> there's no "decades-running trap of trying to solve this".

I’m not as certain. The fact that we’ve gone from ASN.1 to COBRA/SOAP to protobuf to Cap’n’web and all the million other items I didn’t list says something. The fact that, even given a very popular alternative in that list, or super tightly integrated RPC like sending terms between BEAMs, basic questions like “should optionality/absence be encoded differently than unset default values?” and “how should we encode forward compatibility?” have so may different and unsatisfactory answers says something.

Not as an appeal to authority or a blanket endorsement, but I think Fowler put it best: https://martinfowler.com/articles/distributed-objects-micros...

It absolutely is a decades old set of problems that have never been solved to the satisfaction of most users.


> I’m not as certain. The fact that we’ve gone from ASN.1 to COBRA/SOAP to protobuf to Cap’n’web and all the million other items I didn’t list says something.

> It absolutely is a decades old set of problems that have never been solved to the satisfaction of most users.

ASN.1 wasn't in the same problem space with CORBA/DCOM, both CORBA and DCOM/OLE were heavily invested in a general-purpose non-domain-specific object model representation that would suppot arbitrary embeddings within an open-ended range of software. I suspect this is the unsolvable problem indeed, but I also believe that's not what you meant with your comment either, since all the known large-scale BEAM deployments (the comment I originally replied to implied BEAM deployments) operate within bounded domain spaces such as telecom and messaging, where distributed properties of the systems are known upfront: there are existing formats, protocols of exchange, and the finite number of valid interactions between entities/actors of the network, the embeddings are either non-existent or limited to a finite set of media such as static images, videos, maps, contacts etc. All of these can be encoded by a compile-time specification that gets published for all parties upfront.

> basic questions like “should optionality/absence be encoded differently than unset default values?”

However you like, any monoid would work here. I would argue that [a] and [] always win over (Option a) and especially over (Option [a]).

> and “how should we encode forward compatibility?”

If you'd like to learn if there's a spec-driven typed way of achieving that, you can start your research from this sample implementation atop json: https://github.com/typeable/schematic?tab=readme-ov-file#mig...


How would that be different from current municipal police forces?

The "under the control of the mayor" bit.

https://en.wikipedia.org/wiki/Patrolmen%27s_Benevolent_Assoc...

> Approximately 4,000 NYPD officers took part in a protest that included blocking traffic on the Brooklyn Bridge and jumping over police barricades in an attempt to rush City Hall.

https://en.wikipedia.org/wiki/History_of_the_San_Francisco_P...

> The ACLU obtained a court order prohibiting strikers from carrying their service revolvers. Again, the SFPD ignored the court order. On August 20, a bomb detonated at the Mayor's home with a sign reading "Don't Threaten Us" left on his lawn.

https://www.nytimes.com/2020/06/01/nyregion/chiara-de-blasio...

> Among the hundreds of protesters arrested over the four days of demonstrations in New York City over the killing of George Floyd in Minneapolis, only one was highlighted by name by a police union known for its hostility toward Mayor Bill de Blasio. The name of that protester? Chiara de Blasio, the mayor’s daughter.


Ah, Rudy Giuliani. I see he was always a creep.

“Under control of the mayor” would be different from many current municipal police forces.

I mean, they are militas so at the end of the day they will protect the people even if they are told not to..

Yes! And like … “out-compete” assumes a zero sum game. There are massive industries where the tools used to serve different market segments only barely overlap decades after the “game changing” tool was made available.

Like, screw the whole “artisanal small-batch software” argument—there are massive new systems being written in C every day despite decades of claims that it is an obsolete language doomed to be replaced by better alternatives. Those alternatives caught on in some segments and not in others. Electric cars caught on in some segments and not in others. Steel-and-concrete building construction caught on in some segments and not in others. It’ll be fine.


Bisect is one of those things where if you're on a certain kind of project, it's really useful, and if you're not on that kind of project you never need it.

If the contributor count is high enough (or you're otherwise in a role for which "contribution" is primarily adjusting others' code), or the behaviors that get reported in bugs are specific and testable, then bisect is invaluable.

If you're in a project where buggy behavior wasn't introduced so much as grew (e.g. the behavior evolved A -> B -> C -> D -> E over time and a bug is reported due to undesirable interactions between released/valuable features in A, C, and E), then bisecting to find "when did this start" won't tell you that much useful. If you often have to write bespoke test scripts to run in bisect (e.g. because "test for presence of bug" is a process that involves restarting/orchestrating lots of services and/or debugging by interacting with a GUI), then you have to balance the time spent writing those with the time it'd take for you to figure out the causal commit by hand. If you're in a project where you're personally familiar with roughly what was released when, or where the release process/community is well-connected, it's often better to promote practices like "ask in Slack/the mailing list whether anyone has made changes to ___ recently, whoever pipes up will help you debug" rather than "everyone should be really good at bisect". Those aren't mutually exclusive, but they both do take work to install in a community and thus have an opportunity cost.

This and many other perennial discussions about Git (including TFA) have a common cause: people assume that criticisms/recommendations for how to use Git as a release coordinator/member of a disconnected team of volunteers apply to people who use Git who are members of small, tightly-coupled teams of collaborators (e.g. working on closed-source software).


> If you're in a project where buggy behavior wasn't introduced so much as grew (e.g. the behavior evolved A -> B -> C -> D -> E over time and a bug is reported due to undesirable interactions between released/valuable features in A, C, and E), then bisecting to find "when did this start" won't tell you that much useful.

I actually think that is the most useful time to use bisect. Since this is a situation where the cause isn't immediately obvious, looking through code can make those issues harder to find.


I'm glad it works for you! I may not have described the situation super clearly: most bugs I triage are either very causally shallow (i.e. they line up exactly with a release or merge, or have an otherwise very well-known cause like "negative input in this form field causes ISE on submit"), or else they're causally well understood but not immediately solvable.

For example, take a made up messaging app. Let's call it ButtsApp. Three big ButtsApp releases releases happened in order that add the features: 1) "send messages"; 2) "oops/undo send"; and 3) "accounts can have multiple users operating on them simultaneously". All of these were deemed to be necessary features and released over successive months.

Most of the bugs that I've spent lots of time diagnosing in my career are of the interacting-known-features variety. In that example, it would be "user A logs in and sends a message, but user B logs in and can undo the sends of user A" or similar. I don't need bisect to tell me that the issue only became problematic when multi-user support was released, but that release isn't getting rolled back. The code triggering the bug is in the undo-send feature that was released months ago, and the offending/buggy action is from the original send-message feature.

Which commit is at fault? Some combination of "none of them" and "all of them". More importantly: is it useful to know commit specifics if we already know that the bug is caused by the interaction of a bunch of separately-released features? In many cases, the "ballistics" of where a bug was added to the codebase are less important.

Again, there are some projects where bisect is solid gold--projects where the bug triage/queue person is more of a traffic cop than a feature/area owner--but in a lot of other projects, bugs are usually some combination of trivially easy to root-cause and/or difficult to fix regardless of whether the causal commit is identified.


I think that’s primarily a Rust issue, not an LLVM issue. LLVM is at least competitive performance-wise in every case I’ve used it, and is usually the fastest option (given a specific linker behavior) outright. That’s especially true on larger code bases (e.g. chromium, or ZFS).

Rust is also substantially faster to compile than it was a few years ago, so I have some hope for improvements in that area as well.


> I don't care how elegantly my toaster was crafted as long as it toasts the bread and doesn't break.

A consumer or junior engineer cares whether the toaster toasts the bread and doesn’t break.

Someone who cares about their craft also cares about:

- If I turn the toaster on and leave, can it burn my house down, or just set off the smoke alarm?

- Can it toast more than sliced uniform-thickness bread?

- What if I stick a fork in the toaster? What happens if I drop it in the bathtub while on? Have I made the risks of doing that clear in such a way that my company cannot be sued into oblivion when someone inevitably electrocutes themselves?

- Does it work sideways?

- When it fills up with crumbs after a few months of use, is it obvious (without knowing that this needs to be done or reading the manual) that this should be addressed, and how?

- When should the toaster be replaced? After a certain amount of time? When a certain misbehavior starts happening?

Those aren’t contrived questions in service to a tortured metaphor. They’re things that I would expect every company selling toasters to have dedicated extensive expertise to answering.


My contention is:

> A consumer

is all that ultimately matters.

All those things you’re talking about may or may not matter some day, after years and a class action lawsuit that may or may not materialize or have any material impact on the bottom line of the company producing the toaster, by which time millions of units of subpar toasters that don’t work sideways will have sold.

The world is filled with junk. The majority of what fills the world is junk. There are parts of our society where junk isn’t well tolerated (jet engines, mri machines) but the majority of the world tolerates quite a lot of sloppiness in design and execution and the companies producing those products are happily profitable.


You really underestimate how much work goes into everything around you. You don't care because it just works: the stuff you use is by and large not crap, which makes the crappy stuff all the more noticable. Check out the housing code for your area: everything from the size of steps to the materials used for siding are in there. Or look at the FCC specifications for electrical devices that make sure you don't inadvertently jam radio frequencies in your local area, or the various codes which try very hard to stop you from burning your house down.

You're right that "there are parts of our society where junk isn't well tolerated", but the scope of those areas is far greater than you give credit for.


I'm long term traveling, mostly through the developing world, where something like 84% of humanity resides.

All around me, people's houses, the roads, the infrastructure, food cultivation and preparation, furniture, vehicles, it goes on and on, the tendency is towards loose approximation, loose standards. Things are constantly breaking, the quality is low, people are constantly being poisoned by the waste seeping into their water, air and soil, by the plastic they burn to cook their food, by the questionable chemicals in the completely unsafe industrial environments they work in to produce toxic products consumed by the masses.

There is no uniform size of steps. Yet the majority of humanity lives this way, and not just tolerates it but considers it a higher standard of living than we've had for the majority of human history.

I don't think people in the first world are a different species, so we will also adapt to whatever shitty environment we regress into as our standards fall. We'll realize that the majority of the areas we may consider sacrosanct are in fact quite negotiable in terms of quality when it comes down to our needs.

All this is to say that yeah, I think people will generally tolerate the quality of software going down just fine.


That's a sad way to think. I'd like to hope that humanity can improve itself, and that includes building products that are safer, more refined, more beautiful, more performant and more useful. I agree that there's a lot of crap out there, but I still want to believe and strive to make things that are excellent. I'm not ready to give up on that. And yes, I still get annoyed every time my crappy toaster doesn't work properly.

I hear this a lot, but I don’t really understand how this manifests in language complexity like the stuff in TFA in practice.

Like, I can understand how systems programming requiring programmers to think about questions like “how can I proceed if allocation fails? How does this code work in an embedded context with no heap?” is hard and irreducible.

But I can’t understand why a language’s choice to impose complex rules like C++ move constructor hell is an inevitable outcome of irreducible complexity in systems programming. Put another way: C is also a systems programming language that works for many people, and it doesn’t have any of these Byzantine rules (unless you build them yourself). That’s not to say C is better/preferable, but it swims in the same “official Big Gun systems language” pond as C++, which seems to indicate that revalue semantics as complex as C++’s are a choice, not an inevitability.


I wouldn't say issues like this are dues to irreducible complexity, but more symptomatic of long-lived languages that continually get extended but don't give up on backwards compatibility. It's basically the 2nd law of thermodynamics applied to programming languages that they will eventually die due to increased entropy.

Maybe if move semantics, and noexcept, had been designed into C++ from the beginning then the designers might have chosen to insist that move constructors be noexcept, but since these were added later there is code out there with move constructors that do throw exceptions...

Note by the way that the issue being described isn't strictly about std::move or move semantics in general, but more about the STL and containers like std::vector that have chosen to define behavior that makes noexcept move constructors necessary to be used when reallocating.


> But I can’t understand why a language’s choice to impose complex rules like C++ move constructor hell is an inevitable outcome of irreducible complexity in systems programming.

Programmer here for 30 years in C/C++. It is true that C++ has become a more complex language after rvalue references were introduced, but you have to understand the rationale behind C++: a language suitable for large scale systems programming with *ZERO OVERHEAD*.

The language complexity especially rvalue references was to reduce overhead. Pre-C++-11, there were many code patterns that involved constructing temporaries and destroying them immediately.

C is not suitable as a large scale programming language. Just look at the number of defects in the Linux kernel and their attempt at extending the language through custom compiler attributes to overcome the limitations of C.


> but you have to understand the rationale behind C++: a language suitable for large scale systems programming with ZERO OVERHEAD.

Is this the reason why C++ was created, or the last remaining niche that C++ is holding onto?

I remember the early 90's, and it very much seemed like C++ was being pushed as both a general-purpose language and the logical successor to C, insert Linus Torvalds rant here. On top of that, C++ made the decision to privilege a form of polymorphism that had pointer-chasing baked into its internal design, as well as having a good chunk of the standard library being considered a footgun best to avoid due to how much it blew up compile-times.

I think that C++ is a zero-overhead language now because a series of general purpose languages that came afterwards took the other niches away from it, plus the benefit of 30+ years worth of compiler optimizations that were originally largely aimed at the mountain of C code that was out there.

EDIT: Almost forgot about exceptions, the other enormous performance footgun that was an early pre-standard C++ feature.


C++ doesn't have zero overhead, though. The committee is unwilling to take ABI breaks and so have left performance on the table. For instance, unique_ptr<T> can't be passed in registers but T* can.

Zero overhead is a fiction the committee likes to tell themselves, but it's not true.


> I can’t understand why a language’s choice to impose complex rules like C++ move constructor hell is an inevitable outcome of irreducible complexity in systems programming

It's not about irreducible complexity in systems programming, it's about irreducible complexity in the creation of higher level abstractions.

You could certainly implement something functionally equivalent to std::vector<std::string> in C. What you couldn't do in C is implement std::vector<T> correctly and efficiently for any type T. That's where much of the complexity comes from.

The hard part is giving the compiler enough information so that it can automate a lot of what would have to be manually written in a language like C, and to produce a result that is both correct and efficient.


The difference is that in C one is supposed to do allocations and deallocations oneself. Then move semantics is just pointer assignment with, of course, the catch that one should make sure one does not do a double-free because ownership is implicit. In C++ ownership is indicated by types so one has to write more stuff to indicate the ownership.

> The difference is that in C one is supposed to do allocations and deallocations oneself

No, you should only use the heap if necessary.

The bigger issue in C is there is no concept of references, so if you want to modify memory, the only recourse is return-by-value or a pointer. Usually you see the latter, before return value optimization it was considered a waste of cycles to copy structs.

In the embedded world, its often the case you won't see a single malloc/free anywhere. Because sizes of inputs were often fixed and known at compile time for a particular configuration.


As you pointed out, the idea that a systems language requires some high level of complexity is just straight-up wrong, and demonstrably so (see, C).

The best programmers I know of have basically all abandoned C++ in favor of either languages they made, or just use plain C


What does processor but width have to do with the likelihood of allocation failures?

I think what he means is that on a 64-bit system you have a massive virtual address space (typically only 48-bit, but that's still 256TB), and since malloc allocates from virtual address space, not limited by physical memory, it is unlikely you will get a malloc failure (unless you are trying to allocate more than 256TB per process, maybe due to a memory leak).

That's not true as generally as you might expect.

Folks might be using mmap with MAP_POPULATE; they might have overcommit turned off; they might be operating in an rlimit/cgroup (like most container runtimes/orchestrators configure) that limits memory; they might be on a system which doesn't have virtual memory (plenty such systems exist in 64-bit architectures); they might be using calloc on an OS that zeros pessimistically/early; and so on.


> it is unlikely you will get a malloc failure

That assertion completely misses the point. The scenarios involving move constructors throwing exceptions involve objects being stuck in an inconsistent/zombie state. In fact, the whole point of a move constructors is to avoid having to allocate memory.


640K ought to be enough for anybody!

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

Search: