Оптимизировать код без блокировки передачи индекса фондового рынка в другие потоки
Я рассчитываю индекс фондового рынка, который меняется настолько часто, что я решил выделить ему отдельное "ядро" (одно из 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 или что-то еще.