Каковы недостатки использования этого кода асинхронного ведения журнала? - PullRequest
2 голосов
/ 10 июля 2010

Ниже приведен код, который я только что написал.

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

Кажется, он работает, когда MyFirstMethod завершает работу, метод ведения журнала отключается в отдельном потоке, а MySecondMethod работает параллельно.Идея состоит в том, что методы в веб-приложении с высокой интенсивностью трафика (т. Е. В многопоточной среде) должны быть украшены аналогичным инструментарием.

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

using System;
using System.Threading.Tasks;
using NUnit.Framework;
using PostSharp.Aspects;

namespace Test
{
    [TestFixture]
    public class TestClass
    {        
        [Test]
        public void MyTest()
        {            
            MyFirstMethod();
            MySecondMethod();
        }

        [PerformanceInstrument]
        private void MyFirstMethod()
        {
            //do nothing
        }

        private void MySecondMethod()
        {
            for (int x = 0; x < 9999999; x++);
        }
    }

    [Serializable]
    public class PerformanceInstrument : MethodInterceptionAspect
    {                    
        public override void OnInvoke(MethodInterceptionArgs args)
        {            
            var startDtg = DateTime.Now;
            args.Proceed();
            var duration = DateTime.Now - startDtg;
            Task.Factory.StartNew(() => MyLogger.MyLoggingMethod(duration)); //invoke the logging method asynchronously
        }        
    }

    public static class MyLogger
    {
        public static void MyLoggingMethod(TimeSpan duration)
        {
            for (int x = 0; x < 9999999; x++);
            Console.WriteLine(duration);
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 03 августа 2010

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

Команда TPL написала об этом здесь.

http://blogs.msdn.com/b/pfxteam/archive/2010/02/08/9960003.aspx

Шаблон производитель / потребитель будет означать, что ваш метод MethodInterceptionAspect просто добавит запись в глобальную очередь (как предложил Бен), и тогда у вас будет одна (длительная) задача, которая обработает все записи. Таким образом, ваш метод пересечения становится:

ConcurrentQueue<TimeSpan> _queue;

public override void OnInvoke(MethodInterceptionArgs args)
{
    var startDtg = DateTime.Now;
    args.Proceed();
    var duration = DateTime.Now - startDtg;
    Task.Factory.StartNew(() => _queue.Add(duration)); 
}

Где-то еще вы обрабатываете очередь:

foreach (var d in _queue.GetConsumingEnumerable())
{
    Console.WriteLine(d);
}

В следующем посте показана аналогичная реализация, в которой несколько задач, созданных в цикле Parallel.For, добавляют изображения в коллекцию BlockingCollection, а одна задача обрабатывает изображения.

Библиотека параллельных задач WaitAny Design

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

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

2 голосов
/ 10 июля 2010

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

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

Это что-то вроде паттерна «Производитель / Потребитель», в котором код создает сообщения журнала, а потребитель отвечает за сброс этих сообщений на постоянный носитель.

...