HNHacker News
TopNewBestAskShowJobs

branko_d

2,241 karma · joined May 2, 2017

submissionscomments
branko_d··on Things you can do with a debugger but not with print debugging
Yes, but to a lesser extent.
branko_d··on Things you can do with a debugger but not with print debugging
Assuming you meant C's printf, why would you subject yourself to the pain of recompilation every time you need to look at a different part of code? Isn't the debugger easier than adding printf and then recompiling?
branko_d··on Things you can do with a debugger but not with print debugging
Well, if you have a race condition, the debugger is likely to change the timing and alter the race, possibly hiding it altogether. Race conditions is where print is often more useful than the debugger.
branko_d··on The worst possible antitrust outcome
Can Elon Musk confiscate your property, limit your freedom of movement, or outright kill you?

There were times in history where having a lot of money was correlated to having all those powers. There are places in this world where that’s still the case.

branko_d··on What Is Complexity in Chess?
> ...between the current position and winning. (Because chess is entirely deterministic, that distance always exists. We are (currently) unable to measure it in most cases, but we can be sure it does exist.)

Can we?

Just because it's deterministic doesn't mean it always leads to a win - there may be strategies that always lead to a draw, we may just not know about them. Tic-tac-toe is deterministic and we know it always leads to a draw if played correctly - we know about it because it's a much simpler game (much smaller tree of possibilities).

branko_d··on John Carmack's arguments against building a custom XR OS at Meta
In my experience, coding is much faster when doing it this way.

Yes, you can produce a small amount of code faster if you don’t “waste” your time on documentation, but that becomes counterproductive as soon as you can no longer keep the entire codebase in your head.

branko_d··on Colleges see significant drop in international students as fall semester begins
Is a foreign student who finishes the university and then stays in America an American?
branko_d··on Like Intel before it, AMD blames motherboard makers for burnt-out CPUs
Most other brands had very similar problems (including my trusty Nokia at the time). You can still attenuate antennae on modern phones if you hold it just right. It's just a matter of physics.

Here is what Nokia N97 does when you "hold it wrong":

https://www.youtube.com/watch?v=shR4jITiG48

branko_d··on A visual introduction to big O notation
> In many cases it's guaranteed to be small or small-ish.

And in many cases it's assumed to be small, but not guaranteed. That's where the trouble lies.

A classic example is Windows using a quadratic algorithm for arranging desktop icons that caused severe performance issues when users had many icons on their desktop.

https://github.com/microsoft/Windows-Dev-Performance/issues/...

branko_d··on A visual introduction to big O notation
Even if it's slower for the vast majority of cases, but there are rare cases where the computer would otherwise freeze, that's still a win.
branko_d··on A visual introduction to big O notation
There is a lot of value in explaining the gist of something, even if it's not entirely accurate. In my experience, the cases where even that is impossible are very rare, at least when it comes to practical computer programming.
branko_d··on Go is still not good
You could also have the number of code UNITS, which is the route C# took.
branko_d··on Vibe Coding Is the Worst Idea of 2025 [video]
The problem is not that the experts have dismissed vibe coding without even trying it.

The problem is that the experts have tried it and found that vibe coding doesn't actually work at scale that they need.

Will it ever? Perhaps, but I'd argue a near-AGI level of intelligence would need to be achieved first. When that happens, we have bigger problems (and/or opportunities?) than a few programmers losing their jobs.

branko_d··on Good system design
> Note that “uniform service layer” doesn’t necessarily mean “networked service layer”, this can be in-process if you can prevent people from bypassing your querying functions and going directly to the DB.

You can take it one step further and implement the “uniform service layer” in the database itself - using stored procedures and views.

This has downsides, like strong coupling with the specific DBMS, and difficulty of development in a comparatively primitive SQL dialect, but protects the database from “naughty” clients and can have tremendous performance advantages in some cases.

branko_d··on Good system design
> Indexes work like nested dictionaries

If the author meant “dictionary” in a sense of a hash map, that’s not quite correct. In relational databases, indexes are usually B-trees, which are ordered, unlike hash maps. A B-tree can help with range-searches, ORDER BY and even merge joins, not just equality-searches.

branko_d··on 1910: The year the modern world lost its mind
On the other hand, dinosaurs may have survived if they had a space program! :)
branko_d··on PHP compile time generics: yay or nay?
And as a consequence, C# can pack the value types directly in the generic data structure, instead of holding references to heap-allocated objects.

This is very important both for cache locality and for minimizing garbage collector pressure.

branko_d··on US to rewrite its past national climate reports
Don't Look Up!
branko_d··on Writing a storage engine for Postgres: An in-memory table access method (2023)
Probably because of the "D" in ACID transactions, so the transaction log cannot be meaningfully write-cached.

OTOH, writing to tables/indexes is already done "out of order" and aggressively cached in the buffer pool, and flushed to permanent storage only occasionally (and relatively rarely, e.g. SQL Server does it approximately once a minute).

branko_d··on The time is right for a DOM templating API
I would love to see Web platform become more similar to JVM or .NET CLR - just a bytecode JIT with access to rich layout/rendering engine. Then build whatever you want on top of it.
branko_d··on Wrong ways to use the databases, when the pendulum swung too far
> looping through cursors, making business logic decisions, calculating things, etc.

Interesting. Can you share more details about the "non-data" processing that was done? Were they doing heavy mathematical calculations and such?

> change in business logic that would normally only need to update application code, now invalidates the stored procedure's cached execution plan

As for plan cache invalidation - the most extreme case I saw was on the order of 5-10s. Basically, it depends on the size of that one stored procedure - not on all other stored procedures that may call it or be called by it. What was the actual time that they got?

branko_d··on Wrong ways to use the databases, when the pendulum swung too far
I never quite understood these kinds of arguments, event though they seem to be repeated a lot:

> 1. Many critical APIs call would spend most of its CPU time inside the finite database servers. New APIs, or updating existing APIs meant you were hogging the DB/CPU time from every one else.

It's not that easy for a stored procedure to spend CPU on anything other than data processing. If you are going to do that data processing, then it's going to cost this amount of CPU regardless of whether it is initiate internally (through a stored procedure) or externally (by the client submitting queries). Furthermore, a frequently-used stored procedure's plan is likely already cached, so it doesn't have to be re-parsed and re-planned on each call. On the other hand, when the client submits the text of the query, that text has to at least be hashed, so it can be compared to the hashes in the query plan cache (even if the plan is already in the cache). So if anything, client-submitted queries will consume at least as much CPU as stored procedures, if not more.

> 2. API latency was at the mercy of the Query Planner. Any slight change in data statistics or business logic would cause the a different Query Plan to be picked, which drastically changed the execution time, and usually caused timeouts. A hash join suddenly became a full table scan across billions of rows without any warning.

This is also true for client-submitted queries. Basically the same techniques are useful for both stored procedures an client-submitted queries: query hints and plan guides, and above all: sound indexing. That being said, this is a big problem in practice and, I think, a fundamental problem in the design of SQL as "declarative" language where you are not supposed to concern yourself with the physical access path, even though it could make a big difference in performance. Fortunately SQL Server has mitigations for this problem (hints and plan guides), but not all DBMSes do (PostgreSQL still doesn't support hints natively, if I'm not mistaken).

branko_d··on Why does the U.S. always run a trade deficit?
> why doesn't it happen with the chinese supply chain

There are already "dark factories" that don't require light or heating because they are fully automated and don't require human presence.

Guess where they are? China.

branko_d··on The world could run on older hardware if software optimization was a priority
> The hardware is dirt cheap. Programmers aren't cheap.

That may be fine if you can actually improve the user experience by throwing hardware at the problem. But in many (most?) situations, you can't.

Most of the user-facing software is still single-threaded (and will likely remain so for a long time). The difference in single-threaded performance between CPUs in wide usage is maybe 5x (and less than 2x for desktop), while the difference between well optimized and poorly optimized software can be orders of magnitude easily (milliseconds vs seconds).

And if you are bottlenecked by network latency, then the CPU might not even matter.

branko_d··on The world could run on older hardware if software optimization was a priority
Often, this is presented as a tradeoff between the cost of development and the cost of hardware. However, there is a third leg of that stool: the cost of end-user experience.

When you have a system which is sluggish to use because your skimped on development, it is often the case that you cannot make it much faster no matter how expensive is the hardware you throw at it. Either there is a single-threaded critical path, so you hit the limit of what one CPU can do (and adding more does not help), or you hit the laws of physics, such as with network latency which is ultimately bound by the speed of light.

And even when the situation could be improved by throwing more hardware at it, this is often done only to the extent to make the user experience "acceptable", but not "great".

In either case, the user experience suffers and each individual user is less productive. And since there are (usually) orders of magnitude more users than developers, the total damage done can be much greater than the increased cost of performance-focused development. But the cost of development is "concentrated" while the cost of user experience is "distributed", so it's more difficult to measure or incentivize for.

The cost of poor user experience is a real cost, is larger than most people seem to think and is non-linear. This was observed in the experiments done by IBM, Google, Amazon and others decades ago. For example, take a look at:

The Economic Value of Rapid Response Time https://jlelliotton.blogspot.com/p/the-economic-value-of-rap...

He and Richard P. Kelisky, Director of Computing Systems for IBM's Research Division, wrote about their observations in 1979, "...each second of system response degradation leads to a similar degradation added to the user's time for the following [command]. This phenomenon seems to be related to an individual's attention span. The traditional model of a person thinking after each system response appears to be inaccurate. Instead, people seem to have a sequence of actions in mind, contained in a short-term mental memory buffer. Increases in SRT [system response time] seem to disrupt the thought processes, and this may result in having to rethink the sequence of actions to be continued."

branko_d··on Docs like code in basic terms
The above was copy-pasted from the article.
branko_d··on Docs like code in basic terms
Summary:

1. Write some docs in a text editor.

2. Using git, send your new docs to GitHub.

3. Follow some steps on GitHub to finish adding your new docs to the site.

4. A process runs which takes your changes, builds everything into a website (using the static site generator), and deploys it to a server.

branko_d··on Bloat is still software's biggest vulnerability (2024)
I remember, at the turn of the century (was is 2001?) when Microsoft was touting "weak coupling" achievable through "web services" and demoing the support for SOAP in Visual Studio.

To me, that was the strangest idea - how could you "decouple" one service from another if it needs to know what to call, and what information to pass and in what format? Distributing the computing - for performance, or redundancy or security or organizational reasons - that I can understand - but "weak coupling" just never made sense to me.

branko_d··on Legendary Bose Magic Carpet Suspension Is Finally Going Global
https://en.wikipedia.org/wiki/Moose_test

"It is noteworthy that the previous record holder (set in 1999) was the Citroën Xantia 3.0i V6 Activa, an unassuming family car with a unique active roll bar system.[15]"

branko_d··on Programming languages should have a tree traversal primitive
In C#, you can implement an iterator method with the signature like this:

    public static IEnumerable<TNode> DepthFirstTraverse<TNode>(
        TNode root,
        Func<TNode, IEnumerable<TNode>> children
    )
You can then just ‘foreach’ over it.

This doesn’t require the whole tree to be in-memory. Optimal implementation would recurse via programmer-controlled stack (instead of language-controlled) to avoid nested iterators.

Here is a TypeScript version:

    function* traverseDepthFirst<T>(
        root: T,
        children: (parent: T) => Iterable<T>
    )
A similar approach should be possible in any language which supports iterators/generators.
← PreviousPage 3 of 13Next →