Измерьте время выполнения метода с помощью атрибута (ядро .net) - PullRequest
0 голосов
/ 19 сентября 2018

Я заинтересован в измерении времени, которое требуется для выполнения определенных методов.

Я подумал, что было бы действительно удобно сделать это, используя пользовательский атрибут вместо засорения методов кодом для запуска / остановки секундомера.и отправка в логгер.Если бы я мог украсить метод, о котором идет речь, с помощью атрибута, это было бы очень удобно!

Я смог бы создать собственный атрибут, следуя этой статье: https://docs.microsoft.com/en-us/dotnet/standard/attributes/writing-custom-attributes

Примерно так:

public class MonitorExecutionTime : Attribute
{
    private Stopwatch measureExecution;

    // Start measuring on instantiation
    public MonitorExecutionTime()
    {
        measureExecution = new Stopwatch();
        measureExecution.Start();
    }

    // how do I hook into end invoke?
    public MethodHasEnded()
    {

        measureExecution.Stop();
        TimeSpan timeSpan = measureExecution.Elapsed;

        Console.WriteLine("Time: {0}h {1}m {2}s {3}ms", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds, timeSpan.Milliseconds);
    }
}

Но я не уверен, как «захватить» точки запуска существа и завершить его, чтобы запустить секундомер и остановить секундомер (чтобы измерить время и зарегистрировать его).

Кто-нибудь использовал этот подход в приложении ядра .net?Заранее спасибо за любые указатели!

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Атрибуты не вызываются во время выполнения.Но вы можете использовать библиотеку наподобие Fody для создания сборок - для автоматического добавления кода после компиляции сборки в метод, помеченный вашим пользовательским атрибутом.

Фактически уже есть реализация, аналогичнаяВы хотите достичь - Метод Таймер

Вот как это работает (скопировать / вставить из документации).Ваш код:

public class MyClass
{
    [Time]
    public void MyMethod()
    {
        //Some code u are curious how long it takes
        Console.WriteLine("Hello");
    }
}

То, что фактически скомпилировано в окончательную сборку

public class MyClass
{
    public void MyMethod()
    {
        var stopwatch = Stopwatch.StartNew();
        try
        {
            //Some code u are curious how long it takes
            Console.WriteLine("Hello");
        }
        finally
        {
            stopwatch.Stop();
            Trace.WriteLine("MyClass.MyMethod " + stopwatch.ElapsedMilliseconds + "ms");
        }
    }
}

Вы можете написать свой собственный код перехватчика, чтобы избежать использования Trace.WriteLine и вести запись так, как вы этого хотите.

0 голосов
/ 19 сентября 2018

@ igore-goyda - ваш пост отправил меня по пути к тому, что мне было нужно.Подводя итог, можно сказать, что есть два способа перехватить методы и выполнить некоторую пользовательскую обработку.Либо через прокси, либо с помощью перезаписчика IL.

Я нашел эту статью превосходной для объяснения: http://jeffbelback.me/posts/2015/06/01/principles-of-aop/

Я решил, что метод Proxy будет работать лучше для меня (мне не нравилось представление о том, что мой код был изменен после компиляции), и смог реализовать подходящее решение с использованием Autofac, следуя этой статье: https://nearsoft.com/blog/aspect-oriented-programming-aop-in-net-core-and-c-using-autofac-and-dynamicproxy/

Документация Autofac также помогла мне: https://autofaccn.readthedocs.io/en/latest/advanced/interceptors.html?highlight=proxy

0 голосов
/ 19 сентября 2018

Атрибуты в .NET не являются обертками, поэтому их нельзя использовать таким образом.Вы должны использовать упаковщик вызова метода, например:

public class Service : IService
{
    public void Exec() {
        Wrap("Method Exec", () => {
            // do something usefull
        });
    }

    private void Wrap(string message, Action action)
    {
        var watch = Stopwatch.StartNew();
        try
        {
            action();
        }
        finally
        {
            watch.Stop();
            Console.WriteLine($"{message} executed in {watch.ElapsedMilliseconds} ms");
        }
    }
}

Если вы хотите обернуть все методы класса или интерфейса, вам следует взглянуть на аспектно-ориентированное программирование, например, в этой статье: https://www.c -sharpcorner.com / статей / аспект-ориентированное программирование-в-с-острое использование-dispatchproxy /

...