A "bottleneck" is a point at which performance is hindered. It's named the bottleneck because the neck of a bottle is the thinnest part which allows the least amount of fluid to pass.
For example if you have a super fast 3GHz processor but really slow RAM that can only be accessed at 100MHz, that RAM is the bottleneck because nothing can move faster than it. All other faster systems are stuck waiting for the RAM.
In C++ and programming in general, the bottleneck typically refers to the slowest area of code in a program. Particularly one where performance is an issue.
Profiling is the process of finding bottlenecks within code. Profiling measures the amount of memory used by a particular function, and time taken to execute that function. This is the case for all invoked functions. Profiling occurs during run-time.
First, you would profile your code, then, you would locate any functions that take too long to execute, or use too much memory. When you've found one, you would go back to your code and fix it.
A bottleneck relates to profiling. On a single threaded program, a function that takes way too long to execute means that the main thread would have to wait; not a good thing. By profiling, you can seek those bottlenecks and fix them, or at least attempt to.