Hacker Timesnew | past | comments | ask | show | jobs | submit | mrkeen's commentslogin

I ran into this as well. If an Event has a name, you can instantly grep across a giant monolith (or a big folder of microservice repos) and find every file that is concerned with that event.

If you pull it out into a constant, you're back to opening up projects one-by-one to 'find usages'


grepability is underrated. This is one of the reasons I dislike passing functions into interfaces - it makes it harder to follow the call chain when the functions are constantly renamed.

Luckily there are often solutions that just come down to which arbitrary labels that you assign. e.g. compare these two blocks

    do_thing = do_thing_one_way if condition else do_thing_other_way
    process(data, do_thing=do_thing)
versus

    thing_processor = do_thing_one_way if condition else do_thing_other_way
    process(data, thing_processor=thing_processor)
The first is much more greppable - search for "\bdo_thing" all over the code base. The second requires realizing that the processor function renames the internal function to "thing_processor".

This is what your choices are with regard to communicating to the compiler and other developers.

Use a regular class to signal that you may or may not have a value.

Wrap it in an optional to signal that you may or may not have a value.

See the problem?



These are called messaging bills if one never caucuses to get it passed.

Yes, I too dislike Sanders because others don't vote for his bills.

> because others don't vote for his bills

Not how politics works! He puts zero effort into making them passable, or pushing to get them included into omnibuses. He’s there to placate and sell books. If what you want is an influencer in the Senate, he’s your guy.


> He puts zero effort into making them passable

You mean watering them down so they’re next to useless and full of carved out exceptions for paying “friends”?


isn't a method used by smaller groups with less popular ideas to try to shift the overton window in their favor? if that's the case with Sanders then his goal wouldn't be to make his bills passable, it would be to shift the conversation to something like "hey maybe a sovereign wealth fund isn't a bad idea"

> but we strongly believe that Verse will become a more powerful and capable way to create game logic.

I haven't tried Unreal Engine yet, but I might, just to get a taste of a Simon Peyton Jones language


I didn't believe the optimal algorithm is linear time, so I checked the source:

  a simple register allocation algorithm can achieve most ot the performance of the more complex algorithms: linear-scan register allocation, developed by Poletto and Sarkar
"Most of the performance" is not optimal. Were you referring to a different source?

The big caveat in what I was saying is that it is only the pure graph coloring portion that has an optimal linear time algorithm.

Take code in static single assignment form, or another form where it is values that are tracked with live ranges. For a single basic block the interference graph of the live ranges is an interval graph. As the live ranges are just intervals from the instruction that produces the value to the last instruction that consumes the value.

It is annoying but totally doable to follow this into graph theory and see that interval graphs, are a subset of chordal graphs, and these graphs have an algorithm that colors the graph optimally in linear time.

Poke a little more and it turns out that algorithm is the same algorithm as linear-scan register allocation.

Add multiple basic blocks and it is trickier to see, but there are proofs in the academic literature that the interference graph remains an interval graph. Something about phi functions not counting.

Which is what I meant when I said a linear time algorithm.

Compare that to the O(N^2) heuristic from the paper register allocation by graph coloring.

The big change is going from a linear time optimal algorithm to a quadratic time heuristic and proclaiming the quadratic time heuristic is better. (What???)

In practice there are a lot of complications that are not accounted for by graph coloring. Instructions and function calls that take fixed registers. Spilling registers when you need more values alive then there are registers. Deliberately keeping a non-minimal number of values in registers to increase instruction level parallelism.

To the best of my knowledge all of those problems are very tractable if you start with a linear scan register allocator, as the code can be changed without requiring the register allocation to restart.

Code based on computing the interference graph has to reconpute the interference graph and restart whenever the code has to be changed. Making it much worse time wise. If for no other reason than computing the interference graph is O(N^2).

So yes more complications but only because the model described is overly simplified.


There is a wonderful paper "Register Allocation: What Does the NP-Completeness Proof of Chaitin et al. Really Prove?" (2006) by Bouchez, Darte, and Rastello [0]. I'll just quote the abstract in full because there is really nothing much I could add to it:

    Register allocation is one of the most studied problem in compilation. It is
    considered as an NP-complete problem since Chaitin, in 1981, showed that
    assigning temporary variables to k machine registers amounts to color, with
    k colors, the interference graph associated to variables and that this graph
    can be arbitrary, thereby proving the NP-completeness of the problem. However,
    this original proof does not really show where the complexity comes from.
    Recently, the re-discovery that interference graphs of SSA programs can be
    colored in polynomial time raised the question: Can we exploit SSA to perform
    register allocation in polynomial time, without contradicting Chaitin's NP-
    completeness result? To address such a question, we revisit Chaitin's proof
    to better identity the interactions between spilling (load/store insertion),
    coalescing/splitting (moves between registers), critical edges (a property of
    the control-flow graph), and coloring (assignment to registers). In particular,
    we show when it is easy to decide if temporary variables can be assigned to
    k registers or if some spilling is necessary. The real complexity comes from
    critical edges, spilling, and coalescing, which are addressed in our other
    reports.
[0] https://hal-lara.archives-ouvertes.fr/hal-02102286v1/documen...

It is worth noting that register coalescing gets a lot of attention in interference graph coloring allocators because they typically have a pre-pass that inserts copies everywhere (because adding copies or spills later is so hard). So instead of worrying about where to insert copies and spills, those allocators worry about what to coalesce instead.

In my own compiler (where I don't add copies in a prepass) I have not yet found a case where any coalescing would be beneficial.


> In fact, I barely talk about my choices around eating meat — because hearing people spout off about their morality is most of the time annoying and exhausting.

Congrats on writing an AI think-piece about how tiring it is that people only write AI think-pieces.



A couple more that don't seem to be represented there. No mention of cause and effect, or the order in which different nodes perceive things happening? Anyway here's three which I think might be more relevant to designing and building software:

* Your system is not a distributed system

Multiple users connect, disconnect, and use your system at the same time, some of the code is running on your servers, some of it's in your partners' servers, some of it's in your storage layer, and some of it's running on your users' computers

* Your DB's ACID transactions are sufficient for distributed thinking

An ACID transaction lets you addUser() to your storage, either succeeding completely or failing completely, with no observable intermediate state. It does not let both your frontend and your storage layer addUser(), same with both your storage and your partner's storage.

* Your DB's transactions are ACID

Your DB vendors cannot build databases that are acceptably fast while running ACID. Therefore isolation is relaxed and transactions can commit through each other. Even if the DB itself was ACID, your ORM and/or programming style is likely breaking ACID independently of the DB configuration.


Another one from my experience:

* Hardware is cheap.

So many services and daemons are running on your system and most of them believe that they have all the hardware for themselves, while the opposite is true. Designing to capitalize whole hardware while they are other processes which are fighting to do the same never ends well.

OTOH, being a good citizen on a crowded system makes life for everyone better. Both maintenance and performance-wise.


> No mention of cause and effect, or the order in which different nodes perceive things happening?

8. The network is homogeneous

Often misconstrued as a recapitulation of “there is one administrator”

A homogenous system, such as a single node Java application, for instance usually provides very clear semantics for this.


* You will have logs

Always gets me


While they're at it, they should kick out the French, the Germans, the Italians, and any other immigrants refusing to speak Swiss.

> refusing to speak Swiss

I know this is tongue in cheek. But one of the hallmarks of a nation of immigrants is the enforced tolerance of speaking multiple national languages. Lots of people who only speak on throws off that balance.


> While they're at it, they should kick out the French, the Germans, the Italians, and any other immigrants refusing to speak Swiss.

What's this Swiss language you speak of? I never heard of it. You must mean Romansh but that's only 0.5% of the population or so. You'd have to kick out 95.5% of the Swiss population too then?


That’s their point. Switzerland is a nation of immigrants. We don’t tend to be portrayed as such outside. And the SVP tends to forget this. (As does the GOP.)

Ah you're right. I did miss their sarcasm. Sometimes you can't tell online

https://en.wikipedia.org/wiki/Poe's_law


Are you Swiss? I thought you were American from previous interactions.

> Are you Swiss? I thought you were American from previous interactions

I’m more than one thing. (But only vote in two places.)


> To make things even worse, the community that has most thoroughly embraced them are compiler authors, who many programmers think of as being an impossibly skilled elite

The article's approach seems super ad-hoc, leaving you to have to think hard, do all the work, and make all the mistakes.

If you were to go down the other path, you might try dividing and conquering the problem. An arbitrary Pair<A,B> is trivially constructed from an arbitrary A and an arbitrary B. So if you can generate a string, and a number, you could generate a User full of number and string fields. If your generate function accepts a number describing how complex a string to make, then you can also choose how complicated to make your User. That's all shrinking needs to be. Repeatedly trying smaller Ns while the problem still happens (the problem being one of your unit tests - not an additional "interestingness" test you need to write.)

You'll probably way more likely to hit boundary cases by using the structure of the input and making interesting variations that way, rather than hoping you can permute the right bytes from the CLI.


For more than 20 years I've been doing automatic test input reduction as part of testing Common Lisp compilers. The reduction is on randomly generated inputs, but they are structured in such a way that reduction always gives a valid program that should (in the absence of compiler errors) not signal an error.

It's a tremendously economical way to test compilers. For a modest and finite investment in testing infrastructure I get an unlimited number of tests. Over the years I've run many billions of test inputs on various Common Lisp implementations, although I'm mostly focusing on sbcl these days. When a bug is found the input quickly reduces to a something small that usually immediately tells the developers where the problem is (usually but not always something introduced recently.)

I also have a testing harness that cobbles together usually erroneous Lisp code and sees if the compiler blows up (the sbcl compiler as designed must never throw an error condition even on erroneous input.) This exploits a corpus of public Common Lisp code, combining and mutating the code in various ways.


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

Search: