Есть швейцарский армейский нож, который, по какой-то странной причине, не все знают, может быть, потому, что он слишком прост (и тоже уродлив). Запустите его под GDB и просто приостановите его несколько раз, например, 10. Каждый раз изучайте стек вызовов.
Если 50% времени приходится на ввод / вывод, 50% +/- выборок будут показывать его в вводе / выводе, и каждая строка кода в стеке вызовов будет показывать часть цепочки, почему это делает ввод / вывод. То же самое для сна или любого другого блокирующего вызова. Если время не заблокировано, как будто вы сортируете пузырьки огромного массива, это тоже покажет, и почему. Если вы проводите время в какой-то системной библиотеке, в которой вы просто не знаете (или не заботитесь) о том, заблокирована она или нет, сделайте то же самое.
Если это занимает больше времени, потому что какой-то другой процесс использует часть процессорного времени, это не имеет значения, потому что это не сильно меняет то, как ваш код тратит свое время в процентах. Вы по-прежнему узнаете, сколько IO, или сна, или хруста вы делаете, в процентном соотношении и почему именно.
Если вы хотите что-то более красивое, хотя и не очень эффективное, попробуйте Zoom .