Yahoo's hadoop has a variety of issues. I'd rather not say company names, but this comes from working at a company that had hadoop in production by 2007 and last I heard was running 10+pb datastores with 10k+ hadoop cores.

Yahoo's hadoop writes all output (from mappers and reducers) to local disks which are typically spinning rust. This is an anti-pattern: you run multiple mappers per box, typically 1.1-1.3 per core, and you have multiple jobs running simultaneously. You then perform a disk based merge sort, and then every reducer must connect to every mapper to get the data associated with its keys. The second you get a hot disk, whole jobs get choked because of the api invariants: all mappers complete before you can finish (or perhaps start) sort, all sorts complete before reducers, all reducers finish before the next mapper pass. Further, avoiding having every reducer have to have high throughput network to every mapper is key; the hadoop design makes it difficult to optimize over network topology like higher within-rack bandwidth.

There are far better designs implemented: never write to local disk from the mappers, instead writing to a global dfs then performing the sort in the dfs. I worked for a company that took hadoop 0.17 and made it roughly 10x more performant (and not on toy datasets: on petabyte scale datasets) with roughly 10 engineer-years with this design.

I think it's also fair to say that the quality of engineers on hadoop, particularly when they worked at yahoo, was... subpar. There was a ton of low hanging fruit.

Also, yahoo's workload wasn't, or so I've heard, highly cpu bound. They where using hadoop at least in part just for hdfs capacity. So if you aren't cpu constrained, a lot of optimizations don't matter. Better companies have to run at say 95%+ cpu or their cfo won't authorize more boxes.

You can also go after things like optimizing your compressors / decompressors, which are probably by far the hottest bits of code. Get icc, break out vtune, hire a really good optimizing dev to go after even small gains, etc.

Finally, the hdfs design is pretty shitty, on two fronts: the namenode gets slow (choking everyone), and the disk-based format is missing lots of things to enable optimizations like certain types of append, or indexing. Indexing is incredibly powerful for things like join, enabling a map-side join instead of having to read all your data once, sort by join keys, then reread in your reducers.

Another problem with hdfs design is capacity adding; hdfs has shitty rebalancing tools. The typical problem is this: hot data is new data. So if you add capacity to hdfs, your old capacity is say 80% full and your new capacity is 0% full so where does all new data go? To the new capacity. Which is quickly 100% saturated and choking your jobs. Properly rebalancing a dfs is a hard problem on it's own. Further, hdfs' use of triple replication (well, you can actually set the replication level) instead of better algorithms like erasure encoding does no favors to performance as well.

edit: by the way, never writing to local disk and instead going from mappers straight to dfs then performing a rough/fine grained sort in the dfs is a lot like google's design. You do trade network i/o for disk i/o, but that's often easier to scale and, as mentioned, easier to optimize over your network topology. Finally, you can do multi-pass sorts partially locally by running sorters on your disk nodes.