HN user

grogers

989 karma
Posts2
Comments432
View on HN

Today is my last day at my current employer. After some time off, I'm considering several different options. I have enough saved that retirement is probably doable, although last time I took extended time off I got bored much quicker than I expected. I'm also considering retraining for a different field but that seems kinda daunting, and no certain bet either. I was thinking of doing some open source contributions to test the waters on whether I really want to give up software dev or not. I might do part time work just for something to do and for decent health care. Luckily working in tech has been very lucrative, so there are plenty of options on the table.

Have you tried dafny, which seems roughly comparable for your purposes? I heard some buzz about it a little while ago but I haven't been following this space closely.

If you are ten nested functions deep in sync code and want to call an async function you could always choose to block the thread to do it, which stops the async color from propagating up the stack. That's kind of a terrible way to do it, but it's sort of the analog of ignoring errors when that innermost function becomes fallible.

So I don't buy that async colors are fundamentally different.

They all smear the purchases and sales from index changes, but I don't think they publish on what timescale. Most funds try to minimize tracking error. There are funds that take this to a different level. When a stock is added to the big indexes, it tends to do poorly over the next year, and on the flip side when a stock is removed it tends to perform well. Dimensional funds have automatic rules to take advantage of this type of thing. There are other companies that have funds of this style, but overall they are much less widely used than the big index funds from vanguard, blackrock, state street, etc.

Well they also shadowed production traffic and fixed some bugs that were causing mismatching results. Not saying that stuff can't still slip through, but it's a good way to evaluate it against real data in a way you can't from just test cases alone

In this incarnation, the only one who "wants" red to win is the first column. Every other column will choose whatever color it wants to win, subject to the rules of the game.

It's a 2 step process:

1. Prepare - Collect a majority of rows such that each of them promises not to accept any color sent by columns to the left of the proposing column. Any colors which were already accepted are sent in reply, along with the column they were accepted in (if different colors were accepted, only the rightmost column for a given row matters). The color to be propagated by the proposer is that with the rightmost column number (or if none were accepted by that particular majority, anything may be selected)

2. Accept - for every row, set the color to the one chosen in step one for the proposing column, subject to the promises made in step 1.

In this case, it's not shown well in the diagram, but by having a majority of rows promise for column 2, column 1 would already have a broken majority. Even if column 4 wanted red, since it received some already accepted colors, it has to choose from one of them based on the rightmost column (blue in this case)

The final diagram is a bit confusing, so it's worth pointing out one additional thing. It appears that R5 could vote green in column 2 and have green be agreed by a majority, even though in column 4, we are committing to blue as the value. However, as part of allowing blue to be selected in column 3, R5 must have already promised NOT to accept green in column 2. A more complete final diagram would show X's in all the appropriate cells.

Well it is hedged with the word "fancy". I think a charitable reading is to understand the problem domain. If N is always small then trying to minimize the big-O is just showing off and likely counterproductive in many ways. If N is large, it might be a requirement.

Most people don't need FFT algorithm for multiplying large numbers, Karatsuba's algorithm is fine. But in some domains the difference does matter.

Personally I usually see the opposite effect - people first reach for a too-naive approach and implement some O(n^2) algorithm where it wouldn't have even been more complex to implement something O(n) or O(n log n). And n is almost always small so it works fine, until it blows up spectacularly.

Even treating the process as read only after forking is potentially fraught. What if a background thread is mutating some data structure? When it forks the data structure might be internally inconsistent because the work to finish the mutation might not be completed. Imagine there are locks held by various threads when it dies, trying to lock those in the child might deadlock or even worse. There's tons of these types of gotchas.

It's not your main point, but I can't help but point out that artificial diamonds ARE diamonds. Cubic zirconia is a different mineral. Usually the distinction is "natural" vs "lab grown" diamonds.

When computers have super-human level intelligence, we might be making similar distinctions. Intelligence IS intelligence, whether it's from a machine or an organism. LLMs might not get us there but something machine will eventually.

You must implement a move constructor or a move assignment operator in order for std::move to do anything

Bit of a nitpick, but there are sometimes other functions with overloads for rvalue references to move the contents out - think something like std::optional's `value() &&`. And you don't necessarily need to implement those move constructor/assignment functions yourself, typically the compiler generated functions are what you want (i.e. the rule of 5 or 0)

so clearly an LLM that does math well only does so by ignoring the majority of the space it is trained on

There are probably good reasons why LLMs are not the "ultimate solution", but this argument seems wrong. Humans have to ignore the majority of their "training dataset" in tons of situations, and we seem to do it just fine.

An often underlooked aspect of SSDs for databases is write endurance. With the wrong workload random writes can burn through your drive in months instead of years. This is the hidden gem of LSM over b-tree - low write amplification, not just better write performance. Maybe doesn't really matter on AWS since you can just pitch your instance once you've trashed the SSDs

LLM only fairly recently underwent a step change from "maybe someday" to actually useful now. That opened many new doors that people didn't even think were possible. Getting incrementally better at something they are already pretty good at isn't that impressive. But getting drastically better at something they are currently bad at, will drive new models and new research.

Yeah, -O3 generally performs well in small benchmarks because of aggressive loop unrolling and inlining. But in large programs that face icache pressure, it can end up being slower. Sometimes -Os is even better for the same reason, but -O2 is usually a better default.

Of course it depends on the situation. But I don't see how you could think that in this case, crashing is better than stale config.

Crashing on a config update is usually only done if it could cause data corruption if the configs aren't in sync. That's obviously not the case here since the updates (although distributed in real time) are not coupled between hosts. Such systems usually are replicated state machines where config is totally ordered relative to other commands. Example: database schema and write operations (even here the way many databases are operated they don't strongly couple the two).

Instead of crashing when applying the new config, it's more common to simply ignore the new config if it cannot be applied. You keep running in the last known good state. Operators then get alerts about the failures and can diagnose and resolve the underlying issue.

That's not always foolproof, e.g. a freshly (re)started process doesn't have any prior state it can fall back to, so it just hard crashes. But restarts are going to be rate limited anyways, so even then there is time to mitigate the issue before it becomes a large scale outage

It sounds like part of the problem was how the application reacted to the reverted fail over. They had to restart their service to get writes to be accepted, implying some sort of broken caching behavior where it kept trying to send queries to the wrong primary.

It's at least possible that this sort of aborted failover happens a fair amount, but if there's no downtime then users just try again and it succeeds, so they never bother complaining to AWS. Unless AWS is specifically monitoring for it, they might be blind to it happening.

Autocommit mode is pretty handy for ad-hoc queries at least. You wouldn't want to have to remember to close the transaction since keeping a transaction open is often really bad for the DB

Use after free is number 8 and 9 on the lists respectively... Not like it's way down the list. And most of the things the things above it (other than out of bounds writes/reads which you addressed in another comment) are not something I would consider a programming language can directly affect (e.g. SQL injection, CSRF)

Real world systems often have to deviate from the "pure" version used to run formal methods on. This could be how long you keep transaction logs for, or how long rows are tombstoned for, etc. The longer the time period, the costlier it usually is, in total storage cost and sometimes performance too. So you have to compromise with where you set the time period for.

Let's imagine that the process usually takes 1 minute and the tombstones are kept for 1 day. It would take something ridiculous to make the thing that usually takes 1 minute take longer than a day - not worth even considering. But sometimes there are a confluence of events that make such a thing possible... For example, maybe the top of rack switch died. The server stays running, it just can't succeed any upstream calls. Maybe it is continuously retrying while the network is down (or just slowly timing out on individual requests and skipping to the next one to try it). When the network comes back up, those calls start succeeding but now it's so much staler than you ever even thought was possible or planned for. That's just one scenario, probably not exactly what happened to AWS.

I'm not familiar with tokio, but I am familiar with folly coro in C++ which is similiar-ish. You cannot co_await a folly::coro::Task by reference, you must move it. It seems like that prevents this bug. So maybe select! is the low level API and a higher level (i.e. safer) abstraction can be built on top?