logoalt Hacker News

sigbottletoday at 4:51 PM1 replyview on HN

> Understanding algorithmic complexity (in particular, avoiding rework in loops), is useful in any language, and is sage advice.

I recently fixed a treesitter perf issue (for myself) in neovim by just dfsing down the parse tree instead of what most textobject plugins do, which is:

-> walk the entire tree for all subtrees that match this metadata

-> now you have a list of matching subtrees, iterate through said subtree nodes, and see which ones are "close" to your cursor.

But in neovim, when I type "daf", I usually just want to delete the function right under my cursor. So you can just implement the same algorithm by just... dfsing down the parse tree (which has line numbers embedded per nodes) and detecting the matches yourself.

In school, when I did competitive programming and TCS, these gains often came from super clever invariants that you would just sit there for hours, days, weeks, just mulling it over. Then suddenly realize how to do it more cleverly and the entire problem falls away (and a bunch of smart people praise you for being smart :D). This was not one of them - it was just, "go bypass the API and do it faster, but possibly less maintainably".

In industry, it's often trying to manage the tradeoff between readability, maintainability, etc. I'm very much happy to just use some dumb n^2 pattern for n <= 10 in some loop that I don't really care much about, rather than start pulling out some clever state manipulation that could lead to pretty "menial" issues such as:

- accidental mutable variables and duplicating / reusing them later in the code

- when I look back in a week, "What the hell am I doing here?"

- or just tricky logic in general

I only noticed the treesitter textobject issue because I genuinely started working with 1MB autogen C files at work. So... yeah...

I could go and bug the maintainers to expose a "query over text range* API (they only have query, and node text range separately, I believe. At least of the minimal research I have done; I haven't kept up to date with it). But now that ties into considerations far beyond myself - does this expose state in a way that isn't intuitive? Are we adding composable primitives or just ad hoc adding features into the library to make it faster because of the tighter coupling? etc. etc.

I used to think of all of that as just kind of "bs accidentals" and "why shouldn't we just be able to write the best algorithms possible". As a maintainer of some systems now... nah, the architectural design is sometimes more fun!

I may not have these super clever flashes of insight anymore but I feel like my horizons have broadened (though part of it is because GPT Pro started 1 shotting my favorite competitive programming problems circa late 2025 D: )


Replies

liampullestoday at 6:11 PM

You are not wrong. There are of course tradeoffs here. There are various things that can improve web service performance, but if we are talking about the performance of a web service in comparison to other more general concerns, like maintainability, then I agree trying to make small performance wins falls pretty low on the list.

After all, even if one has some slow and beastly, unoptimized Spring Boot container that chews through RAM, its not that expenseive (in the grand scheme of things) to just replicate more instances of it.