A looooooong time ago, in my first job, I wrote code for embedded systems. These systems used 8086 microprocessors, and had limited memory. We used the Intel C compiler. One system I built needed to access a 3-d array of structures. I built it just like the book told me: call malloc for the 3 dimensions, then allocate rows for the next dimension, then calloc for the end nodes.
It was pretty complicated (for me at the time), I had to do curve fitting, ANOVA process control and Chi-squared analysis. There were no libraries that did this for us; we had to write it all and fit it all onto the 8086.
The system ran like a dog. After a quick profiling, I discovered that one of the biggest problems was the allocator. To fix the problem I abandoned all the calls to malloc and did my own memory management of one large block of memory.
In another case on the same job, the customer was complaining about response time on their statistical process control system. The team before me had designed "software PLC" system where operators could use a boolean logic for combining signals and tripping switches. They wrote it in a simplified language, what we'd call a "domain specific language" today. as I recall it looked like
((A1 + B1) > 4) AND (C1 > C2) and so on.
The original design parsed and interpreted that string every time it was evaluated. On our measly processor, this consumed lots of time, and it meant that the process controller couldn't update as fast as the process was running.
I took a new look at it and decided that I could translate that logic into assembly code, at runtime. I parsed it once and then each time it ran, the app called into a dynamically generated function. Kind of like some viruses do today, I guess (but I don;t really know). The result was a 100-fold increase in performance, which made the customer and my boss really really happy.
The new code was not nearly as maintainable, being that I had built a custom compiler. But the performance advantage well outweighed the maintenance disadvantage.
More recently I was working on a system that needed to parse an XML fly, dynamically. Larger files would take considerably more time. This was very performance sensitive; too slow of a parse would cause the UI to become completely unusable.
These kinds of things come up all the time.
So.... sometimes you want maintainable, easy-to-write code. Sometimes you want code that runs quickly. The tradeoff is the engineering decision you need to make, on each project.