There are (at least) three ways to find bugs:
- Someone using the program may notice it behaving in an undesired way. This could be a feature they want, or a defect (i.e., bug).
- While looking at the code directly, a defect could be spotted either as a difference between advertised behavior (from a comment or documentation or from other sections of the same code) for that code and what it actually does, or possibly an accidental misuse, such as an array subscript out of bounds. This could be done by mechanized means (such as compiler checks) or by human eye.
- External programs (frequently called fuzzers) can attack the code in random ways and attempt to make it misbehave by random chance.
Likely you don't see many kernel bugs because they are fixed quickly, when found, not because there are not many.
A feature request is distinguished from a bug in that it usually involves adding new code for new behaviors, where bugs are mistakes in existing code. The optimizations could be either bug fixes or new features.
As a new kernel developer, probably optimizations are very difficult.
Your best bet (as already suggested) might be to find a device that is not currently supported or not well supported and try writing a driver for it.
But just reading through existing kernel code without finding a need to make changes may in itself be a good way to get into kernel development. Following discussions on optimization and understanding how new optimizations work would be equally valuable.