Общая функция для проверки производительности любого делегата

При тестировании относительной производительности различных реализаций метода я переписываю функции, подобные этой.

private static long Measure(
    int iterations,
    Func func,
    string someParameter)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    for (var i = 0; i < iterations; i++)
    {
        func(someParameter);
    }

    stopwatch.Stop();
    return stopwatch.ElapsedTicks;
}

Вместо того, чтобы переписывать эту функцию для каждой тестируемой особенности метода, можно ли будет написать универсальную реализацию для тестирования производительности в любом случае? Нечто подобное

    private static long Measure(
    int iterations,
    Delegate func,
    params object[] parameters)
{
    ...
}

или же

    private static long Measure(
    int iterations,
    TDelegate func,
    params object[] parameters)
{
    if (!typeof(TDelegate).IsSubclassOf(typeof(Delegate)))
    {
        throw new ArgumentException("Not a delegate", "func");
    }

    ...
}

Если бы я мог сделать это, имело бы смыслCompile Expression перед выполнением итераций?

Ответы на вопрос(2)

в:

var p1 = ..
var p2 = ..
var p3 = ..
var p4 = ..
var p5 = ..
Measure(1000, (x) => MyTestFunc(p1, p2, p3, p4, p5), str);
 Jodrell20 нояб. 2012 г., 19:24
Теперь я понимаю, что вы говорите
 Jodrell21 нояб. 2012 г., 11:43
Недостатком здесь является то, что функция lamda для создания вызова становится частью теста. Однако я не вижу способа преодолеть это с помощью какой-либо альтернативы.
 mellamokb20 нояб. 2012 г., 19:21
Предполагая тип возвращаемого значенияMyTestFunc являетсяstring, а такжеx являетсяstring, затем(x) => MyTestFunc(p1, p2, p3, p4, p5) имеет типFunc, Хотя, в этом случае, ни входstring параметр, ни возвращаемое значение фактически нигде не используются - онипросто там, чтобы удовлетворить тип параметра дляMeasure, Если вы неони не нужны, тогда просто используйтеAction как предложено @juharr.
 Jodrell20 нояб. 2012 г., 19:20
Итак, какой тип является вторым параметром?Measure
 mellamokb21 нояб. 2012 г., 15:37
@Джодрелл: Да. Однако, как и в случае с любым временем тестирования, вы тестируете относительную производительность. Если вы тестируете метод 1 против метода 2, используя один и тот же жгут, вы сможете точно определить, какой метод "Быстрее", Если вы действительно пытаетесь рассчитать 100 000 итераций метода, который каждый раз занимает несколько миллисекунд (где lamdba может оказать заметное влияние на время), я бы быстрее проверил,вновь становиться жертвой опасности преждевременной оптимизации.
Решение Вопроса

и вы можете установить параметры в лямбду.

private static long Measure(int iterations, Action action)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    for (var i = 0; i < iterations; i++)
    {
        action();
    }

    stopwatch.Stop();
    return stopwatch.ElapsedTicks;
}

Тогда вы называете это как

Measure(100, () => MyMethod(arg1,arg2,...));
 Jodrell21 нояб. 2012 г., 11:44
Недостатком здесь является то, что функция lamda для создания вызова становится частью теста. Однако я не вижу способа преодолеть это с помощью какой-либо альтернативы. Там всегда будет элемент сантехники.
 Jodrell20 нояб. 2012 г., 19:25
Спасибо, ваш ответ помог мне понять.
 L.B20 нояб. 2012 г., 19:25
+1 Для устранения проблем JIT я бы позвонилaction(); один раз, прежде чем запустить таймер.

Ваш ответ на вопрос