更快的KV vs字典与并发词典,仅在更新字典的值时才使用该字典

发布于 2025-02-12 09:15:58 字数 3352 浏览 0 评论 0原文

流股票的直播价格,每张股票都是关键(INT),其价值类型为struct(不是类) 字典< int,tick>。该字典用所有键初始化一次,并从WebSocket回调中随机更新(无新添加)值。从另一个线程中,该字典每20毫秒就不断迭代以获取最新值。字典的大小为5000键。因此,字典不是线程安全的,contrentDictionary的性能很少。那么,更快的KV速度更好吗?

如果我们不添加新值,只是从一个线程更新现有的键值并从另一个线程读取现有的键值,是否会安全? 在下面的代码块中,“点A”和“点B”将具有相同的值?

 /// <summary>
/// this struct from 3rdpary library
/// </summary>
public struct Tick
{
    public DateTime DateTime { get; set; }
    public uint InstrumentToken { get; set; }
    public decimal LastPrice { get; set; }
}

class TickDataProcessor
{
    private Dictionary<UInt32, Tick> AllStocksTickData { get; set; }
    private Dictionary<UInt32, Tick> AllPreviousStocksTickData { get; set; }


    private void Initialize()
    {
        AllPreviousStocksTickData = new Dictionary<uint, Tick>(capacity: 5000);
        AllPreviousStocksTickData = new Dictionary<uint, Tick>(capacity: 5000);

        // initialize dict with all empty values, after this no more additions
        UInt32 key = 1000001;
        for (int i = 0; i < 5000; i++)
        {
            AllStocksTickData[key] = new Tick();
            AllPreviousStocksTickData[key] = new Tick();
            key++;
        }
    }

    /// <summary>
    ///real time streaming of stock data from stock broker
    /// this method is call back of websocket, websocket callback comes every millisecond for random key
    /// it will update the value of that key.
    /// </summary>
    /// <param name="tickData"></param>
    public void OnNewTickData(Tick tickData)
    {
        AllStocksTickData[tickData.InstrumentToken] = tickData;
    }

    public void Start()
    {
        var ts = new ThreadStart(OneBackgroundMethodStockPriceAnalyzer);
        var backgroundThread = new Thread(ts);
        backgroundThread.Start();

        var ts2 = new ThreadStart(TwoBackgroundMethodStockPriceAnalyzer);
        var backgroundThread2 = new Thread(ts2);
        backgroundThread2.Start();
    }

    private void TwoBackgroundMethodStockPriceAnalyzer()
    {
        while (true)
        {
            foreach (var entry in AllStocksTickData)
            {
                // second thread
            }
        }
    }

  private  void OneBackgroundMethodStockPriceAnalyzer()
    {
        while (true)
        {
            foreach (var entry in AllStocksTickData)
            {
                var key = entry.Key;
                var tickData = entry.Value; // Point A
                /*
                 * process tickdata
                 *
                 */
                if (AllPreviousStocksTickData[key].LastPrice >= tickData.LastPrice)
                {
                    // calculate % of change
                    // other calculations...
                }

                AllPreviousStocksTickData[key] = entry.Value; // Point B
            }
            Thread.Sleep(20);
        }
    }
}

class Program

{
    public static void Main(string[] args)
    {
        var tickDataProcessor = new TickDataProcessor();
        tickDataProcessor.Start();
        Console.ReadLine();
    }
}

仅考虑高性能的字典值时,要使用哪一个。

更快的kv Quick-start start指南

Streaming live prices for stocks, each stock is key (int) and its value type is struct (not class)
Dictionary<int,Tick>. This dictionary is initialized once with all keys, and updating (no new additions) values every millisecond randomly from websocket callback. From another thread this dictionary is continuously iterating every 20 milliseconds for latest values. Size of the dictionary is 5000 keys. So dictionary are not thread safe, ConcurrentDictionary has little performance overhead. So is it better to go for Microsoft FASTER KV?

Will normal dictionary is thread safe if we don't add new values, just updating existing key value from one thread and reading from another thread is safe?
in the below code block "Point A" and "Point B" will have same value?

 /// <summary>
/// this struct from 3rdpary library
/// </summary>
public struct Tick
{
    public DateTime DateTime { get; set; }
    public uint InstrumentToken { get; set; }
    public decimal LastPrice { get; set; }
}

class TickDataProcessor
{
    private Dictionary<UInt32, Tick> AllStocksTickData { get; set; }
    private Dictionary<UInt32, Tick> AllPreviousStocksTickData { get; set; }


    private void Initialize()
    {
        AllPreviousStocksTickData = new Dictionary<uint, Tick>(capacity: 5000);
        AllPreviousStocksTickData = new Dictionary<uint, Tick>(capacity: 5000);

        // initialize dict with all empty values, after this no more additions
        UInt32 key = 1000001;
        for (int i = 0; i < 5000; i++)
        {
            AllStocksTickData[key] = new Tick();
            AllPreviousStocksTickData[key] = new Tick();
            key++;
        }
    }

    /// <summary>
    ///real time streaming of stock data from stock broker
    /// this method is call back of websocket, websocket callback comes every millisecond for random key
    /// it will update the value of that key.
    /// </summary>
    /// <param name="tickData"></param>
    public void OnNewTickData(Tick tickData)
    {
        AllStocksTickData[tickData.InstrumentToken] = tickData;
    }

    public void Start()
    {
        var ts = new ThreadStart(OneBackgroundMethodStockPriceAnalyzer);
        var backgroundThread = new Thread(ts);
        backgroundThread.Start();

        var ts2 = new ThreadStart(TwoBackgroundMethodStockPriceAnalyzer);
        var backgroundThread2 = new Thread(ts2);
        backgroundThread2.Start();
    }

    private void TwoBackgroundMethodStockPriceAnalyzer()
    {
        while (true)
        {
            foreach (var entry in AllStocksTickData)
            {
                // second thread
            }
        }
    }

  private  void OneBackgroundMethodStockPriceAnalyzer()
    {
        while (true)
        {
            foreach (var entry in AllStocksTickData)
            {
                var key = entry.Key;
                var tickData = entry.Value; // Point A
                /*
                 * process tickdata
                 *
                 */
                if (AllPreviousStocksTickData[key].LastPrice >= tickData.LastPrice)
                {
                    // calculate % of change
                    // other calculations...
                }

                AllPreviousStocksTickData[key] = entry.Value; // Point B
            }
            Thread.Sleep(20);
        }
    }
}

class Program

{
    public static void Main(string[] args)
    {
        var tickDataProcessor = new TickDataProcessor();
        tickDataProcessor.Start();
        Console.ReadLine();
    }
}

Which one to use when only updating value of dictionary considering high performance.

FASTER KV Quick-Start Guide

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烟凡古楼 2025-02-19 09:15:58

如果我们不添加新值,只需从一个线程更新现有的键值,然后从另一个线程读取现有的键值,则通常是安全的吗?

我将仅解决这个问题的这一部分。不,在多线程环境中使用普通字典&lt; int,十进制&gt;,其中固定键的数量并可以更新值,绝对不是线程安全。这是因为更新十进制不是原子操作,因此可以撕裂十进制值。您可以在此处找到有关此现象的实验证明:在C#中。

Will normal dictionary is thread safe if we don't add new values, just updating existing key value from one thread and reading from another thread is safe?

I'll address this part of the question only. No, using a normal Dictionary<int, decimal> in a multithreaded environment, where the number of keys is fixed and the values can be updated, is definitely not thread-safe. That's because updating a decimal is not an atomic operation, so a decimal value can be torn. You can find an experimental demonstration of this phenomenon here: Reproduce torn reads of decimal in C#.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文