Live data from Hacker News

Rob Pike’s Rules of Programming (1989)

users.ece.utexas.edu

311–320 of 332 posts

Re: Rob Pike’s Rules of Programming (1989)

#311

Earlier quoted context omitted.

No. It's really an issue of not being sure at first what needs to be flexible & data-driven vs handled in code. If make everything data driven, then it becomes this horrible mess where your input is basically a program and your actual code ends up being a terrible interpreter. I tend to just build things bottom-up, and start with a small bit of functionality, then when I have enough small bits, I bolt them together a…

I don't understand. Tdd gets you to working code (if on a subset of all your data) extremely fast. There are both bottom-up and top-down styles, neither of which is particularly wrong.

The TDD aspect is not really here nor there.

To provide a more concrete example, say I have a function that performs a transformation on a piece data. From what I currently know about the data, I can parse it using a regex. So I code up the function that accepts data, it runs the regex and provides the transformed result. Great.

Now as I'm continuing my work, I notice that some other data requires a similar, but not exactly the same transformation. It can be done with a slightly different regex. So rather than duplicating functionality, I modify the transform function above to take a regex as input along with the data. Everything works as expected.

I get further along in the project and I realize another piece of data needs a somewhat similar transformation, but this time it's just slightly too complicated for a stand-alone regex, it needs to be a function.

The "smart code" way to handle this would be to create another transformation function and call that instead. The "dumb code" way of handling this is to generalize the transformation function such that I can pass in some descriptor for the transformation, and have the transform function return the correct result.

That's the crux of the issue. I rarely have enough information at the time of writing to know just how generalized to make a function. If I created this hyper-generalized transformation at the beginning, but never needed anything beyond the original simple regex, I would have wasted a bunch of time creating code that's needlessly confusing.

TDD is perfectly applicable for development, and would help tremendously with the refactoring aspect, but what it doesn't help with is information that you don't yet know about.

Re: Rob Pike’s Rules of Programming (1989)

#312
post #309

Earlier quoted context omitted.

> It was a fully graphical 800x1024 (or 1024x1024) system running on 1982 processors. I've looked into in that. Blit was monochrome, had an 8Mhz processor, and a relatively large 256KB framebuffer which could but directly written to. There were only a handful commands, mostly concerned with copying (blitting) bitmaps around. Rob Pike only wrote the first version of the graphics routines - the slowest version, in C(!)…

Writeup of the blit terminal's operating system is here, it consists of a lot more than the bitblt primitive, with many whole-system performance concerns at play: http://a.papnet.eu/UNIX/bltj/06771910.pdf Suggest you read this before denigrating Rob Pike's bona fides. Not sure what axe you are trying to grind but it is ugly and unbecoming of a professional.

I'm not denigrating his bona fides, I'm questioning his credentials on performance-oriented computing. For all I know, if Rob Pike had been a performance freak, Blit might've never shipped. He may indeed have chosen all the right trade-offs.

Nevertheless, the advice he gives on performance is wrong, plain and simple, for the reason that I gave you: If you have overhead everywhere, there is no bottleneck that you can observe - your software is just slower than it needs to be across the board. If you write software without performance in mind from the very beginning, you can never get all of it back by optimizing later - without major rewrites that is.

How does one give wrong advice? By not having the required experience to give correct advice. I don't care if you're Rob Pike, Dennis Ritchie or Donald Knuth. If you're wrong, you're wrong.

Re: Rob Pike’s Rules of Programming (1989)

#313

Earlier quoted context omitted.

Yeah, linear probing helps hash-sets a lot on modern CPUs. Perhaps linear probing is a better example of how BigO analysis can go wrong on modern architectures. Inserting into a hashset with linear-probing is O(n) worst-case, while inserting into a linked list is always O(1) (best case, worst case, and average case). And yet, linear probing seems to work out best in practice (with a bit of rigging. The total_size > 2…

I don't think it is the same thing. Inserting into linked list assumes you have found the node to insert in. I don't remember exact details but in hash set with linear probing, the worst case happens quite rarely given the hash function is good one (which are quite sophisticated these days). It is O(1) amortized. The same applies for hash table with chaining too, that all of your keys may go to same bucket given a su…

I mean "Hash-set with Linked List" vs "Hash-set with linear probing". I realize I was getting lazy with my typing, so lemme try to be more clear this time.

Hash-set with Linked List is O(1) all cases.

Hash-set with linear-probing is O(n) worst-case insertion. But happens to be faster in practice with circa 2020-style CPUs (especially with Robin Hood insertion)

Assume the load-factor to be 90%+, so that we actually get a reasonable difference between the two strategies. We have a situation where O(n) is better than O(1).

Re: Rob Pike’s Rules of Programming (1989)

#314
post #251
post #180

Earlier quoted context omitted.

hehehhe I have actually put some data that do not change more often than once a week hardcoded in the code base and commited in source control... whenever a change needs to happen in the data the CI/CD runs and deploys a new version of the app. You don't wanna know how that was done before. It is like < 1 GB of JSON as well.

Please tell me you have git LFS configured to handle this.

Yup !

Re: Rob Pike’s Rules of Programming (1989)

#315

Earlier quoted context omitted.

> and also someone used a Set to check membership of single item. [1] Depending on where it was done (fast path or not), this could be just fine.

You don't know when something comes to hot path. if (std::set(itr.begin(), itr.end()).count(element)) { _____ } is it tempting for someone than something like std::find(itr.begin(), itr.end(), element) != itr.end()) ?? I don't know. That said, C++ STL quite undiscoverable.

>You don't know when something comes to hot path.

That's the point of the first advice though...

Re: Rob Pike’s Rules of Programming (1989)

#316
post #151

Earlier quoted context omitted.

Me too. I've seen a few systems that replaced their simple request requiring 10,000 queries "optimized" by requiring 10,000 cache lookups when they should have just added some joins. The bottleneck is the network latency, not the database. The worst I've seen is an nHibernate cache stored in a session variable, half the database was being serialized/deserialized on every http request. Fortunately that was a small dat…

Having worked with Hibernate recently on a smallish database (that isn't expected to grow too big), my take away is to minimize the network trips. If you have to check something for a list/set of things and all of that can be done from, say, two not so big tables, fetch the superset of records via a join with as much criteria pushed to predicates as efficiently possible and handle rest of the logic in application cod…

Not to cache simple trips to the database is pretty uncontroversial, the are more controversial cases elsewhere.

Say you consume a Restful API to hidrate order data in another system. Do you fetch orders as:

  /orders?ids=id-1,id-2,id-3
or separate calls to

  /orders/id-x
which can be cached and retrieved by id as a memoized function?

Well if you had to pick only one the second is probably better, but the best would be abstracting away order fetching in application code to always fetch single orders and behind the scenes looking up the cache for singles and pooling all the misses into a single request to the plural endpoint.

Re: Rob Pike’s Rules of Programming (1989)

#317

Earlier quoted context omitted.

> I just go with their suggestions. Why though? I am not going to go with suggestions if they make the code less readable for me!

I think the whole world would benefit if we’d make it so that code formatting happened separately from what was committed. Then everyone could have their local checkouts formatted the way they wanted and there would be nothing to argue about in terms of coding style.

After pre-commit linting, you get post-pull linting... If you kept the code in a RAM drive this might even be quick. 8)

Re: Rob Pike’s Rules of Programming (1989)

#318
post #273

Earlier quoted context omitted.

Doing any kind of style discussion in a code review means you’ve already failed. I personally get super annoyed when people keep pointing out style issues, but our CI tool can notify me of issues with my commit until the end of time without me getting frustrated with it.

> Doing any kind of style discussion in a code review means you’ve already failed This sort of baseless assertion has no bearing in reality. In a project that hasn't adopted any linting tools and automatic style checks, all it takes is a misconfigured editor to post a change request that fails to comply with style guides. These sorts of absolutes show a complete detachment from reality and absence of any practical ex…

> These sorts of absolutes show a complete detachment from reality and absence of any practical experience in the field.

But you are making these baseless assertions yourself?

Obviously you can have issues if you are not using automated linting (both in the editor and on CI). That’s part of the failure.

Re: Rob Pike’s Rules of Programming (1989)

#319
post #237
post #126

> Rule 1. You can't tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is. I wish people would follow this rule and just let stuff work. I recently encountered the most extreme version of this I've ever seen in my career: a design review where a guy proposed a Redis caching layer…

It is all about lack of knowledge because checking where the bottlenecks are is one thing. Knowing why they are there is another. A retailer app was very slow. The developers proposed a newer faster server with a newer Oracle version. Then I took a look at one of the slowest queries. Changed it so it could use the indexes in a better way and the query went from +20 to 0.7 seconds. The developers measured the query wa…

The developers didn't actually know where the problem is because they didn't root cause it. They knew it lay within a certain pretty large bounding box (a particular query), but didn't drill into it further, beyond checking that indices are used (eliminating some inadvertent unindexed search as being the root cause).

If you actually know where (or each one of the multiple wheres if several places collude), that is usually very close to knowing why; often the same.

They should have had the intuition that if a query takes 20 seconds, even in a testing scenario where the system is not bogged down, it must be churning through a lot of data all over the place. Then think: does the query actually need to be looking at a lot of data? Maybe it's wastefuly looking at more records than necessary. They didn't imagine what the machine might have to do to satisfy the query, just accepting it as a black box that the DB has optimized as well as it can be (so just throw hardware at it).

Post reply on HN