Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Каков наиболее эффективный способ регистрации имени класса и метода?

Автор вопроса: CommunityОтветов: 6

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

Вот несколько, которые у меня были, но я беспокоюсь о производительности из-за отражения:

  • StackTrace/StackFrame (слишком много накладных расходов?)

  • MethodInfo.GetCurrentMethod() (все еще слишком медленный? И не очень чистый)

  • передать метод в качестве делегата (С# может сделать это неявно, и у меня есть доступ к MethodInfo, но не очень чистый)

Я ценю любые комментарии.

ОБНОВЛЕНИЕ:

Мне понравилась чистота StackFrame, поэтому я задал более конкретный вопрос здесь относительно производительности StackFrame и Я получил действительно хороший ответ, включая тесты производительности. Получается, что MethodInfo.GetCurrentMethod() является самым быстрым (занимает около 1 микросекунды на моем компьютере), а new StackFrame(1) может быть запрошен по запросу (занимает около 15-20 микросекунд на моем компьютере). Я выбросил метод как опцию делегата, так как это слишком беспорядочно, когда метод имеет несколько параметров.

ЗАКЛЮЧЕНИЕ:

Я рассмотрел все варианты, и лучше всего написать собственный подключаемый модуль для PostSharp, который вводит имя метода в виде строки в MSIL во время компиляции при применении к нему пользовательского атрибута, такого как [Trace]. На мой взгляд, это самый быстрый и ремонтопригодный вариант. Это даже позволяет гораздо больше вещей, таких как передача имен параметров и аргументов без какого-либо отражения, а также автоматический захват и регистрация исключений. Этот мой связанный вопрос для получения дополнительной информации.

  • могу я спросить, почему вы не хотите использовать log4net? nWorx 29.08.2009
  • Я не люблю слишком полагаться на другие компоненты. А также в случае с log4net это слишком сложно. 29.08.2009
  • Германн, в нашей отрасли этот синдром обычно называют не изобретенным здесь синдромом, и его лучше избегать. Вот ссылка на Википедию с дополнительной информацией об этом недуге: en.wikipedia.org/wiki/Not_Invented_Here Anderson Imes 01.09.2009
  • Я знаю об этом синдроме, но в моем случае для этого есть практические причины. Меня слишком много раз кусали, используя другие компоненты, и через некоторое время я понял, что они просто не отвечают всем требованиям. 01.09.2009
  • Кстати, у Джоэла Спольски есть отличная статья в защиту синдрома "не здесь изобретено": joelonsoftware.com/articles/ туман0000000007.html 01.09.2009
  • Компания Джоэла Спольски также изобрела собственный язык программирования. Я не уверен, что это хороший пример. Вам действительно следует подумать об использовании письменной библиотеки. Ведение журнала - это решаемая проблема, и я думаю, что изобретать велосипед - это, вероятно, не лучшее использование вашего времени. Просто мои 2 цента... примите это за то, что оно стоит. Anderson Imes 01.09.2009

loggingreflection

Ответы

Ответ 1 · рейтинг 3 · STW

Проще говоря, самый быстрый способ - сделать это статически во время компиляции:

public void DoSomething()
{
    TraceCall("DoSomething");
}

public void TraceCall(string methodName)
{
    if (!tracingEnabled) { return; }
    // Log the call
}

Тогда вопрос по сути такой же, как и ваш предыдущий вопрос; как лучше всего это сделать в ремонтопригодном и точном фасте? Варианты времени выполнения, которые мы обсуждали ранее, оказывают относительно серьезное влияние на производительность, но компромисс заключается в том, что их можно легко реализовать.

Как упоминалось в предыдущей теме, это начинает склоняться к аспектно-ориентированному программированию; PostSharp - одна из таких библиотек, которая может помочь найти баланс между статически скомпилированной производительностью и простым обслуживанием.

Ответ 2 · рейтинг 5 · Sergey Baranchenkov

Самый быстрый способ сделать это во время компиляции, это правда, но самый удобный способ сделать это в .NET - использовать CallerMemberName, CallerFilePath и другие атрибуты службы компилятора, представленные в .NET 4.5:

public void TraceMethodCall([CallerMemberName]string methodName)
{
}

Ответ 3 · рейтинг 2 · Mark Seemann

Когда вы уже находитесь внутри метода (или если вы перехватываете метод), я не думаю, что вы можете добиться большего успеха, чем MethodInfo.GetCurrentMethod, который не слишком быстр, если вы хотите оставаться типобезопасным.

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

В зависимости от нагрузки на ваше приложение, это может помочь или не помочь.

Ответ 4 · Stu Mackellar

Лучший способ сделать это - во время компиляции: C++ традиционно использовал символы препроцессора ____FILE____ и ____LINE____ в макросах для этого. К сожалению, в настоящее время компилятор C# не предлагает макросы или эквиваленты ____FILE____ и ____LINE____.

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

Ответ 5 · Gael Fraiteur

Я думаю, что Log4PostSharp отлично справится с этой задачей.

Ответ 6 · Steve Severance

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы