サーバー (2 * E5-2640 を実行) の別の「コア」(24 個の仮想利用可能なコアの 1 つ) を与えることにしたほど頻繁に変化する株式市場指数を計算していますとにかく、これまでのところ私は 5% しか持っていませんCPU 負荷が少ないので、多くの空き CPU パワーを利用できます。
株式市場の指数の変化に早急に対応する必要があるため、ロックフリー コードを使用することにしました。これは、私が実際に使用するものの例です。
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
です。
私は多くの空き CPU パワーを持っており、HFT ではマイクロ秒が重要であるため、このマイクロ秒が本当に必要です。
質問は簡単です。私の例に問題はありますか? 私はロックフリーのコードを書いたことがないので、ばかげた間違いをするかもしれません。プリミティブな変更 (int/double/decimal) は「アトミック」であると想定しているため、スピンロックは使用しません。したがって、2 番目のスレッドでは常に前の値または新しい値のいずれかを受け取りますが、他には何も受け取りません。
つまり、1 つのスレッドで int x を 100 から 555 に変更すると、2 番目のスレッドでは 100 または 555 になりますが、500 または 155 などにはなりません。