You need to profile your applications because you probably can’t intuit exactly where they are spending their CPU cycles or stashing their memory. Just like it takes a very socially savvy and clever counselor to figure out what people are really thinking, it takes a computer to understand a computer in the wild.
You may think, “Oh, but I understand the stack from top to bottom. I know what’s going on in there.” No you don’t. The spinning disk layer? The disk controller layer? The file system layer? The hypervisor? The guest OS? The driver? The API to the driver? Your code? Its dependencies on interrupts from devices you know nothing about? The unpredictability of the internet? The stupid GUI error your user is perpetuating behind your back? Your head cannot contain all these things.
Modern software is not analogous to gears turning together in a simple machine, but rather to a pinball bouncing around in a flashy arcade on the verge of tilt.
If you are smart and experienced, you’ll have a good guess where to look but even the best are frequently surprised. Profile your application. Use good tools to do it. If they don’t exist, then write a lot of stuff to the logs and add millisecond resolution to the entries. Look for gaps. Find the largest gap and start there, don’t just start anywhere.