По сути, если инструмент профилирования недоступен, вы подражаете тому, что сделал бы профилировщик. Вы вставляете счетчики в функции, которые вы считаете интересными, и подсчитываете, сколько раз и, возможно, с каким размером / видом аргументов они вызываются.
Если у вас есть доступ к каким-либо таймерам на вашей платформе, вы можете запустить / остановить их в начале / конце указанных функций, чтобы также получить информацию о времени выполнения, если это неясно из кода. Это даст вам максимальную выгоду в сложном коде, так как обычно будет слишком много функций, чтобы приспособить их все. Вместо этого вы можете получить время, потраченное на определенные разделы кода, выделив каждому из них таймер.
Эти два метода в тандеме могут сформировать итеративный подход, в котором вы найдете широкий фрагмент кода, который потребляет большую часть ваших циклов, используя таймеры, а затем применяете отдельные функции с более высокой степенью детализации, чтобы отточить проблему.