Оптимизировать код без блокировки передачи индекса фондового рынка в другие потоки

Я рассчитываю индекс фондового рынка, который меняется настолько часто, что я решил выделить ему отдельное "ядро" (одно из 24 виртуальных доступных ядер) моего сервера (работающее 2 * E5-2640), так или иначе, пока у меня есть только 5% нагрузки на процессор, поэтому у меня много свободной мощности процессора.

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

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace TestBlockingCollection2
{
    class Program
    {

        static void Main(string[] args)
        {
            Stopwatch sw = Stopwatch.StartNew();
            int i = 0;

            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    Console.WriteLine("Adding " + (i + 1));
                    sw = Stopwatch.StartNew();
                    i++;
                    Thread.Sleep(1000);
                }
            }, TaskCreationOptions.LongRunning);

            Task.Factory.StartNew(() =>
                                      {
                int prevI = 0;
                while (true)
                {
                    if (prevI < i)
                    {
                        sw.Stop();
                        long microseconds = sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L));
                        Console.WriteLine("Received " + i + ". Spent " + microseconds + " microseconds.");
                        prevI = i;
                    }
                }
            }, TaskCreationOptions.LongRunning);

            while (true)
            {
                Thread.Sleep(1000);
            }
        }
    }
}

Выход:

C:\bin\testBlockingCollection2>TestBlockingCollection2.exe
Adding 1
Received 1. Spent 1 microseconds.
Adding 2
Received 2. Spent 5 microseconds.
Adding 3
Received 3. Spent 2 microseconds.
Adding 4
Received 4. Spent 2 microseconds.
Adding 5
Received 5. Spent 2 microseconds.
Adding 6
Received 6. Spent 4 microseconds.
Adding 7
Received 7. Spent 2 microseconds.
Adding 8
Received 8. Spent 2 microseconds.
Adding 9
Received 9. Spent 5 microseconds.
Adding 10
Received 10. Spent 2 microseconds.
Adding 11
Received 11. Spent 2 microseconds.
Adding 12
Received 12. Spent 2 microseconds.
Adding 13
Received 13. Spent 2 microseconds.
Adding 14
Received 14. Spent 2 microseconds.
Adding 15
Received 15. Spent 2 microseconds.
Adding 16
Received 16. Spent 3 microseconds.
Adding 17
Received 17. Spent 5 microseconds.
Adding 18
Received 18. Spent 2 microseconds.
Adding 19
Received 19. Spent 2 microseconds.

Имея в среднем 2 микросекунды, довольно удивительно по сравнению с 18 микросекундами, которые я использую BlockingCollection что может быть лучше для асинхронного выполнения метода, чем BlockingCollection?

И я действительно хочу эти микросекунды, так как у меня много свободной мощности процессора, а в HFT важны микросекунды.

Так что вопрос прост - видите ли вы какие-либо проблемы с моим примером? Я никогда не писал код без блокировок, поэтому думаю, что могу делать глупые ошибки. Я не использую спин-блокировки, так как я предполагаю, что примитивное изменение (int / double / decimal) является "атомарным", и поэтому во втором потоке я всегда получаю либо предыдущее, либо новое значение, но больше ничего.

Т.е. если в одном потоке я меняю int x со 100 на 555, во втором потоке у меня будет либо 100, либо 555, но никогда не будет 500, 155 или что-то еще.

0 ответов

Другие вопросы по тегам