Производительность ThreadLocal и использование параметров - PullRequest
5 голосов
/ 08 февраля 2012

В настоящее время я реализую среду выполнения (то есть набор функций) для языка формул. Некоторым формулам нужен контекст для передачи им, и я создал класс с именем EvaluationContext, который содержит все свойства, к которым мне нужен доступ во время выполнения.

Использование ThreadLocal<EvaluationContext> кажется хорошим вариантом сделать этот контекст доступным для функций времени выполнения. Другой вариант - передать контекст в качестве параметра нужным функциям.

Я предпочитаю использовать ThreadLocal, но мне было интересно, есть ли какое-либо снижение производительности по сравнению с передачей контекста оценки через параметры метода.

Ответы [ 5 ]

2 голосов
/ 16 ноября 2015

Продолжение costa s answer ;

Если вы попытаетесь N как 10000000,

int N = 10000000;

вы увидите, что нет большой разницы (около 107,4 до 103,4 секунды).

Если значение становится больше, разница становится меньше.

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

PS: В коде типы возврата int должны быть преобразованы вдолго.

2 голосов
/ 09 февраля 2012

Я создал программу ниже, и она быстрее использует параметры, а не поле ThreadLocal.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TestThreadLocal
{
  internal class Program
  {
    public class EvaluationContext
    {
      public int A { get; set; }
      public int B { get; set; }
    }

    public static class FormulasRunTime
    {
      public static ThreadLocal<EvaluationContext> Context = new ThreadLocal<EvaluationContext>();

      public static int SomeFunction()
      {
        EvaluationContext ctx = Context.Value;
        return ctx.A + ctx.B;
      }

      public static int SomeFunction(EvaluationContext context)
      {
        return context.A + context.B;
      }
    }



    private static void Main(string[] args)
    {

      Stopwatch stopwatch = Stopwatch.StartNew();
      int N = 10000;
      Task<int>[] tasks = new Task<int>[N];
      int sum = 0;
      for (int i = 0; i < N; i++)
      {
        int x = i;
        tasks[i] = Task.Factory.StartNew(() =>
                                                 {
                                                   //Console.WriteLine("Starting {0}, thread {1}", x, Thread.CurrentThread.ManagedThreadId);
                                                   FormulasRunTime.Context.Value = new EvaluationContext {A = 0, B = x};
                                                   return FormulasRunTime.SomeFunction();
                                                 });
        sum += i;
      }
      Task.WaitAll(tasks);

      Console.WriteLine("Using ThreadLocal: It took {0} millisecs and the sum is {1}", stopwatch.ElapsedMilliseconds, tasks.Sum(t => t.Result));
      Console.WriteLine(sum);
      stopwatch = Stopwatch.StartNew();

      for (int i = 0; i < N; i++)
      {
        int x = i;
        tasks[i] = Task.Factory.StartNew(() =>
        {
          return FormulasRunTime.SomeFunction(new EvaluationContext { A = 0, B = x });
        });

      }
      Task.WaitAll(tasks);

      Console.WriteLine("Using parameter: It took {0} millisecs and the sum is {1}", stopwatch.ElapsedMilliseconds, tasks.Sum(t => t.Result));
      Console.ReadKey();
    }
  }
}
1 голос
/ 09 февраля 2012

Я считаю дизайн ThreadLocal грязным, но креативным. Определенно будет быстрее использовать параметры, но производительность не должна быть вашей единственной заботой. Параметры будут намного понятнее для понимания. Я рекомендую вам пойти с параметрами.

0 голосов
/ 08 февраля 2012

Я думаю, вы обнаружите, что при непосредственном сравнении доступ к ThreadLocal <> занимает значительно больше времени, чем доступ к параметру, но в итоге это может не иметь существенного значения - все зависит от того, что еще вы делаешь.

0 голосов
/ 08 февраля 2012

Там не будет никакого влияния на производительность, но вы не сможете делать какие-либо параллельные вычисления в этом случае (что может быть весьма полезно, особенно в области формул). Если вы определенно не хотите этого делать, вы можете выбрать ThreadLocal.

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

...