Recent submissions

Comment · 1 month ago
Nice to see more people getting nerdsniped by the sh code. ;-)

Yes, associative arrays work well. I think it should even be possible to use bash associative arrays. But at that point you're no longer doing classic sh - awk is basically halfway to Perl. (And pretty awesome.)

Comment · 1 month ago
The sort is on line numbers, as aozgaa said. Again, the paradigm here - and this is designed for a different time - is that your data most definitely does not fit in RAM, so you use sort(1) to sort on disk and run your software using only constant memory. (In modern software, databases can and do sort on disk, but few programs do.)

In detail, for input "foo bar FOO qux FOO foo", we convert to

[1 foo, 2 bar, 3 foo, 4 qux, 5 foo, 6 foo]

(with newlines instead of commas, obviously), then sort by word (then line number) to

[2 bar, 1 foo, 3 foo, 5 foo, 6 foo, 4 qux]

at which point the uniq invocation gives <count> <first_line> <word>, i.e.

[1 2 bar, 4 1 foo, 1 4 qux]

albeit with an ugly mix of tabs and spaces. One final sort by <first_line> gives us

[4 1 foo, 1 2 bar, 1 4 qux]

and then it's just a matter of formatting the output:

[foo 4, bar 1, qux 1]

The generally-useful point is that the classic shell utilities really do work pretty well if you're operating within their paradigm, which isn't "throw everything in a hash table". (That's the paradigm of later scripting languages.)

Comment · 1 month ago
The general point is true, but the shell pipeline gets a lot more elegant if you use the sort-and-accumulate paradigm that the classic shell utilities were written for (which uses O(1) memory, by sorting on disk). Using mostly the author's own code, and adding --count to uniq:

    tr < README.md --complement --squeeze-repeats '[:alpha:]' '\n' \
    | tr A-Z a-z \
    | nl \
    | sort --key=2,2 --key=1,1n \
    | uniq --skip-fields=1 --count \
    | sort --key=2,2n \
    | awk '{ print $3, $1 }'
(Where the final awk papers over the fact that we're mixing tabs and spaces here; obviously, awk is also good at doing the accumulation step, but uniq --count suffices here.)

(I originally posted the above as a comment on lobste.rs, on this same article.)

Comment · 4 months ago
In a way, but note that the government actors here have Opinions on the Chinese having capable models.
Comment · 9 months ago
Comment · 1 year ago
Thanks a lot for your response!
Comment · 1 year ago
(Hopping in here because the discussion is interesting... feel very free to ignore.)

Thanks for writing this up! It was a very interesting read about a part of networking that I don't get to seriously touch.

That said: I'm sure you guys have thought about this a lot and that I'm just missing something, but "why can't every proxy probe every [worker, not application]?" was exactly one of the questions I had while reading.

Having the workers being the source-of-truth about applications is a nicely resilient design, and bruteforcing the problem by having, say 10k proxies each retrieve the state of 10k workers every second... may not be obviously impossible? Somewhat similar to sending/serving 10k DNS requests/s/worker? That's not trivial, but maybe not _that_ hard? (You've been working on modern Linux servers a lot more than I, but I'm thinking of e.g. https://blog.cloudflare.com/how-to-receive-a-million-packets...)

I did notice the sentence about "saturating our uplinks", but... assuming 1KB=8Kb of compressed critical state per worker, you'd end up with a peak bandwidth demand of about 80 Mbps of data per worker / per proxy; that may not be obviously impossible? (One could reduce _average_ bandwidth a lot by having the proxies mostly send some kind of "send changes since <...>" or "send all data unless its hash is <...>" query.)

(Obviously, bruteforcing the routing table does not get you out of doing _something_ more clever than that to tell the proxies about new workers joining/leaving the pool, and probably a hundred other tasks that I'm missing; but, as you imply, not all tasks are equally timing-critical.)

The other question I had while reading was why you need one failure/replication domain (originally, one global; soon, one per-region); if you shard worker state over 100 gossip (SWIM Corrosion) instances, obviously your proxies do need to join every sharded instance to build the global routing table - but bugs in replication per se should only take down 1/100th of your fleet, which would hit fewer customers (and, depending on the exact bug, may mean that customers with some redundancy and/or autoscaling stay up.) This wouldn't have helped in your exact case - perfectly replicating something that takes down your proxies - but might make a crash-stop of your consensus-ish protocol more tolerable?

Both of the questions above might lead to a less convenient programming model, which be enough reason on its own to scupper it; an article isn't necessarily improved by discussing every possible alternative; and again, I'm sure you guys have thought about this a lot more than I did (and/or that I got a couple of things embarassingly wrong). But, well, if you happen to be willing to entertain my questions I would appreciate it!

Comment · 1 year ago
You're commenting on an article about people consuming less than $3/day; Americans on food stamps (SNAP appears to be about $4-6/day alone, not counting any other benefits) are a distraction, simply not part of the population that the article is discussing.
Comment · 1 year ago
Comment · 1 year ago
I really like this article. I do think it's useful to consider that the unit of isolation ("process") of the cloud era is a VM or container, and that the major clouds do have some sort of permissions model.
Comment · 1 year ago
Comment · 2 years ago
marktplaats.nl is the big "eBay-like" for the Netherlands.
Comment · 2 years ago
It's not ideal, but it's not a cryptographic risk.

Using an encoding that (like Protobuf) has multiple representations for a message may cause you problems if you switch implementations - sha256(encode(msg)) might yield different hashes on different implementations of encode().

But the main risk is an encoding that has multiple interpretations of a single encoding (e.g. sha256(encode("admin", "true")) == sha256(encode("admint", "rue"))), and Protobuf (can be unserialized, and thus) doesn't have that problem.

Comment · 2 years ago
I was also thinking of promise pipelining, but note that the article proposes communicating A -> {B, C} -> D, never directly communicating from A to D. Cap 'n Proto "level 3" nodes could send promises from B and C to D, but that still needs A to talk to D, i.e. A -> {B, C, D}; {B, C} -> D. Same latency / depth of dependency chain, but still more messages - right?

(In return, note that Cap 'n Proto's A -> D message makes it more obvious how A figures out whether the operation succeeded; I'm not quite sure how that works in the proposed diagram. I suppose the proposed system actually puts all messages in a system-wide database, which does solve the problem.)

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton