That’s my impression too. I would expect more handcrafted code on embedded systems and you need more awareness of computational complexity and memory needs.
It's not as important as you would expect for a couple of reasons:
1. The size of the data is often much smaller - the savings from using an nlogn time algorithm vs a n^2 algorithm are much smaller when n=10 versus n=10000. There's a good chance that the constant time setup will dominate for those smaller datasets.
2. To a certain extent, embedded systems don't need to be as fast as possible - they just need to be "good enough" to meet their deadlines so that the rest of the system functions as expected. It'd be nice to be able to compute 1000 CRCs per millisecond instead of only 10, but if it already takes 1 millisecond to transmit the CRC over the serial bus, it's not going to make the system substantially better at its job.
So yes, there is a lot of handcrafted code, but quite often it's just implementing your standard naive brute-force algorithm with minimal code size, minimal memory overhead (preferably without dynamic allocation), and well-understood worst-case latency.
This. If I'm in embedded land, especially hard real time, I don't care how quick something is, as long as it complies with the real time requirements.
Programmers will endlessly prematurely optimize. I'd much prefer to see simple code that can be understood and optimized where needed, rather than squirrely code that runs fast but is unmaintainable.