Live data from Hacker News

New Grad vs. Senior Dev

ericlippert.com

111–120 of 392 posts

Re: New Grad vs. Senior Dev

#112

Earlier quoted context omitted.

Every good cs course has a section on cache aware algorithms. And i call bullshit that constant factor is not mentioned too

It wasn’t taught to me. And, in my previous job I interviewed many dozen fresh grads. One of my questions was “How much slower is it to sum integers in a trivial linked list vs. a trivial array?” 90% answered “Umm... I don’t know. 2x?” When asked why, they all said “1 op to sum the int +1 op to traverse the pointer.” It was amazingly consistent.

O dear.... Am I happy that I never studied computer 'science'..... On the other hand, there must be smart computer science students and/or smart places of education where actual learning about processor caches and the like takes place.....

Re: New Grad vs. Senior Dev

#113
I understand this as phenomenon as the new grad and the senior developer are optimizing for different things. The new grad is focused solely on the asymptotic complexity of the code. It doesn't matter how slow or how complicated it is in practice, they are solely focused on using the fastest data structure asymptotically.

The senior developer optimizes a different set of criteria:

  1) How hard is it to understand the code and make sure it's correct.
  2) How fast the algorithm in practice.
There are several different reasons why the performance of the algorithm in practice is different than the performance in theory. The most obvious reason is big-O notation does not capture lots of details that matter in practice. An L1 cache read and a disk IOP are both treated the same in theory.

A second reason is the implementation of a complex algorithm is more likely to be incorrect. In some cases this leads to bugs which you can find with good testing. In other cases, it leads to a performance degradation that you'll only find if you run a profiler.

I one time saw a case where a function for finding the right shard for a given id was too slow. The code needed to find from a list of id ranges, which one a given id fell into. The implementation would sort the id ranges once ahead of time and then run a binary search of the ranges to find the right shard for the id. One engineer took a look at this, realized that we were doing the shard lookups sequentially, and decided to perform the shard lookups in parallel. This made the code faster, but we still would have needed to double the size of our servers in order to provide enough additional CPU to make the code fast enough.

Another engineer hooked the code up into a profiler and made a surprising discovery. It turns out the implementation of the function was subtlety incorrect and it was sorting the id ranges on every call. This happened because the code sorted the id ranges inside of a Scala mapValues function. It turns out that mapValues does not actually map a function over the values of a hash table. It instead returns an object that when you look up a key, it will look up the value in the original hash table, then apply the function[0]. This results in the function being called on every read.

The solution was to replace mapValues with map. This dramatically improved the performance of the system and basically brought the CPU usage of the system down to zero. Notably, it would have been impossible to discover this issue without either knowing the difference between map and mapValues, or by using a profiler.

[0] https://blog.bruchez.name/2013/02/mapmap-vs-mapmapvalues.htm...

Re: New Grad vs. Senior Dev

#114
In real life, you will always start with simple working implementation and go with it. Then if things are slow, you profile your code with a good profiler while running for some kind of real life scenario and spot the slow parts (also keep in mind that profiling may affect the program's behaviour). After that you may want to consider alternatives with less asymptotic complexity iff that's the part causing slowness.

Once I was asked to look for one project to see that if there is any room for improvement to speed up the program. After I profiled the program with the test data, I saw that program was severely affected by a "size" method call on a lock-free concurrent list. Since the data structure is lock free, size method is not a constant time operation and calling it in a large list takes too much time. It was just there to print some kind of statistics, I changed the code so that it is called only necessary not every time some operation occurs. This immediately made program 2-3 times faster.

There were also some parts I changed with some algorithms with less algorithmic complexith to make it faster. Overall, I made the program 6x faster. So sometimes you need to use fancy algorithms, sometimes you just need to change one line of code after profiling.

Re: New Grad vs. Senior Dev

#115

Earlier quoted context omitted.

I regularly see people make this mistake and don't grasp it after correction. You could make a hash table with a constant time lookup, but the hash takes 1 hour. Big oh only tells you how it scales, not it's performance (runtime).

It's not even that. You could have a normal hash table with a decent hashing function, and you'll still get beaten by a flat array for small n (hundreds, low thousands), because the array is contiguous in memory - so operations like search or moving stuff around after addition make extremely good use of CPU's cache.

> by a flat array for small n (hundreds, low thousands)

Some of us are working in, say, Python. A flat array can outperform at small n, yes, but people overestimate where the tradeoff point is. It's at

  # A list of [0, 1, 2, 3, 4]
  In [10]: linear = list(range(5))                                                                                                                    

  # A hash set, same thing.
  In [11]: hashing = set(range(5))                                                                                                                    

  # 44ns / linear search
  In [12]: %timeit 3 in linear                                                                                                                        
  44.2 ns ± 0.412 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

  # 25ns / hash search!
  In [13]: %timeit 3 in hashing                                                                                                                       
  25 ns ± 0.6 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
The hash set outperforms the linear search by nearly 2x, on a list of size 5! (The performance is similar for other common types that end up in hashes, like strings.)

"It's Python!", you say. "Too much chasing of pointers to PyObjects destroy the cache!" And yes, they do; but many people are working in high-level languages like Python or Ruby.

But, for those that aren't, if we repeat the above exercise in Rust, yes the tradeoff will move up, but only to ~60 items, not hundreds or low thousands:

  test tests::bench_hash_int       ... bench:          14 ns/iter (+/- 1)
  test tests::bench_linear_int     ... bench:          19 ns/iter (+/- 3)
If you're thinking that somehow accessing the middle item each time bestows an unfair advantage to the hash table, randomizing the desired item doesn't help, either:

  test tests::bench_rng_hash_int   ... bench:          19 ns/iter (+/- 2)
  test tests::bench_rng_linear_int ... bench:          24 ns/iter (+/- 2)
And looking for an item not in the list is definitely not favorable to the linear search. (It's the worst case.)

In my experience, it's almost always easiest to pay mild attention to big O concerns, and just use the appropriate data structure for the problem at hand. Cache effects mattering is either rare (you're writing a RESTful microserving to push cat pictures, a cache isn't going to matter once we hit this mobile devices 20 second network latency!) or highly context dependent (your line of work is always low-level, and these crop up more often, and you're consequently on the lookout for it; I don't think this applies to most of us, however).

The code used, in case you wish to find fault with it: https://github.com/thanatos/hash-vs-linear

Re: New Grad vs. Senior Dev

#116
I have no CS degree or STEM degree.

Recently I worked on the same type of project as someone with 10 yrs of experience & a CS degree from Stanford.

A few months later, I created a project, and had a manager with a CS degree. However, when I left, that manager was unable to pickup where I left off, and he ended up leaving soon after.

I have less years of experience, but to me, what matters more is the time within that experience which was put into a relevant business model, product built, or past projects. I.e. a Senior Dev with a CS degree, vs. a New Grad with a Business Background & SWE Experience. It's apples to oranges in many cases.

Also, I'd echo another comment here:

>"daxfohl 1 hour ago [-]

> As a senior dev, I wish that I could say I always knew more than my interns, and that all the code that's there is because it was carefully planned to be that way.

>But more often than not, I don't, and it's not. "

Re: New Grad vs. Senior Dev

#117

Earlier quoted context omitted.

The New Grad had knowledge. The Senior Dev had Understanding. Understanding > Knowledge It's that simple.

Being pedantic here, but knowledge is equivalent to understanding (information being knowledge without understanding). Wisdom is the word you were looking for (knowledge being wisdom without experience): The New Grad had knowledge. The Senior Dev had Wisdom. Wisdom > Knowledge.

I see it differently. Knowledge =/= understanding. There are plenty of ppl who know a lot but have little understanding.

Put another way, knowledge is the nodes. Understanding is grasping the connections. Understanding is the higher power. Understanding is where the magic happens.

Wisdom? Wisdom is next level understanding. It's the maturity of developing connection within the connections.

Re: New Grad vs. Senior Dev

#118

Earlier quoted context omitted.

I regularly see people make this mistake and don't grasp it after correction. You could make a hash table with a constant time lookup, but the hash takes 1 hour. Big oh only tells you how it scales, not it's performance (runtime).

It's not even that. You could have a normal hash table with a decent hashing function, and you'll still get beaten by a flat array for small n (hundreds, low thousands), because the array is contiguous in memory - so operations like search or moving stuff around after addition make extremely good use of CPU's cache.

I was using an extreme example to illustrate. I definitely agree.

Re: New Grad vs. Senior Dev

#119
Shockingly,

    InStr(, "docum") = 0
I'm a dev with some grey hair who feels it would have been useful for all that fantastic domain knowledge from Paterson to get documented in a code comment.

I'd love to hear if either of them ever went back and did that?

Re: New Grad vs. Senior Dev

#120

I dislike the mentality that one must "struggle" to be patient with new devs and that it's "more than they deserve." Is it really so hard to help other people learn, and to accept that the only advantage you have on them is starting earlier?

I take your point, but let's be fair. My attitude was "this code is bad and I'm going to demonstrate my skill by improving it" when it should have been "please teach me what design and implementation concerns went into the choice of algorithm here". I was lucky to get a gentle and thoughtful correction for my presumptions.

Kudos to you first for recognizing your own error and second for openly admitting it.

I think there many things to consider here. For new developers, I'd encourage you to look for those "old guys" who really know their stuff. There's a lot of unmined gold you can discover there if you find the right ones. I think us older developers would do well to imitate the patience and kindness of Tim Paterson more often. I guess what I'm saying is both sides could do with a huge dose of humility. I know at times I've been the youthful dev out to one-up the "old guys", and I've been the senior dev thinking "these kids today" to myself when dealing with those with a lot less experience. And both of those are bad.

Also, there are many times when a young guy fresh out of college spots a problem, finds a great solution, and makes things ten times better by just doing it! If you're in the business for a long time, it can become too easy to be cynical, and lose your enthusiasm.

I think the best thing we can do is try to let the good stuff from both sides rub off on each other.

Post reply on HN