Я пытаюсь максимально точно измерить время выполнения некоторых битов кода на нескольких потоках, учитывая переключение контекста и время простоя потоков. Приложение реализовано на C # (VS 2008). Пример:
public void ThreadFunc ()
{
// Some code here
// Critical block #1 begins here
long lTimestamp1 = Stopwatch.GetTimestamp ();
CallComplex3rdPartyFunc (); // A
long lTimestamp2 = Stopwatch.GetTimestamp ();
// Critical block #1 ends here
// Some code here
// Critical block #2 begins here
long lTimestamp3 = Stopwatch.GetTimestamp ();
CallOtherComplex3rdPartyFunc (); // B
long lTimestamp4 = Stopwatch.GetTimestamp ();
// Critical block #2 ends here
// Save timestamps for future analysis.
}
public int Main ( string[] sArgs )
{
// Some code here
int nCount = SomeFunc ();
for ( int i = 0; i < nCount; i++ )
{
Thread oThread = new Thread ( ThreadFunc );
oThread.Start ();
}
// Some code here
return ( 0 );
}
Я бы хотел измерить время выполнения двух вышеупомянутых критических блоков кода как можно точнее. Два вызова, помеченные как A и B , представляют собой потенциально длинные вызовы функций, выполнение которых может занять несколько секунд, но в некоторых случаях они могут завершиться за несколько миллисекунд.
Я запускаю приведенный выше код на нескольких потоках - где-то от 1 до 200 потоков, в зависимости от ввода пользователя. Компьютеры с этим кодом имеют 2-16 ядер - пользователи используют меньшее количество потоков на более слабых машинах.
Проблема в том, что A и B являются потенциально длинными функциями, поэтому весьма вероятно, что по крайней мере один переключатель контекста произойдет во время их выполнения - возможно, более одного. Таким образом, код получает lTimestamp1, затем начинает выполняться другой поток (и текущий поток ожидает). В конце концов текущий поток получает обратно управление и получает lTimestamp2.
Это означает, что длительность между lTimestamp1 и lTimestamp2 включает время, когда поток фактически не выполнялся - он ожидал повторного планирования, пока выполнялись другие потоки. Однако количество тиков в любом случае увеличивается, поэтому продолжительность теперь действительно
Время блока кода = A + B + некоторое время, проведенное в других потоках
пока я хочу, чтобы оно было только
Время блока кода = A + B
Это особенно проблема с большим количеством потоков, так как все они получат шанс на запуск, поэтому вышеупомянутые временные интервалы будут выше, пока все остальные потоки запускаются, прежде чем рассматриваемый поток получит еще один шанс на запуск.
Итак, мой вопрос: возможно ли каким-то образом рассчитать время, когда поток не работает, и затем соответствующим образом отрегулировать вышеуказанные значения времени? Я хотел бы исключить (вычесть) этот 3-й член целиком или хотя бы как можно больше его. Код выполняется миллионы раз, поэтому окончательные значения времени рассчитываются по множеству выборок, а затем усредняются.
Я не ищу продукты для профилирования и т. Д. - приложение должно синхронизировать эти отмеченные части как можно точнее. Функции A и B являются сторонними функциями, я не могу их изменить. Я также осведомлен о возможных колебаниях при измерении времени с точностью до наносекунды и возможных издержках внутри этих сторонних функций, но мне все еще нужно сделать это измерение.
Любой совет будет принят с благодарностью - ассемблерный код C ++ или x86 также будет работать.
Редактировать: кажется невозможным реализовать это. Идея Скотта ниже (с использованием GetThreadTimes) хороша, но, к сожалению, GetThreadTimes () является ошибочным API и почти никогда не возвращает правильные данные. Спасибо за все ответы!