Есть ли лучшая реализация потокобезопасной LinkedList - PullRequest
0 голосов
/ 25 июня 2019

Я использую LinkedList и переключаюсь между хранением данных, получаемых через обновления, выполнением вычислений и удалением старых обновлений.Чтобы выполнить это, я должен заблокировать раздел чтения и выборки, но это идет с ударом производительности.Поскольку я постоянно добавляю и удаляю узлы, я думал, что LinkedList - лучшая структура данных для этой задачи (насколько я понимаю, использование списка для этого повлечет за собой множество действий по копированию списка). Насколько я знаю, нет поточно-ориентированногореализация LinkedList.Я запускаю этот код на большом объеме данных, и для его завершения требуются часы.Есть ли способ, которым я мог бы ускорить его?

edit: я добавляю узлы в конец списка и удаляю из его начала

  private readonly ConcurrentQueue<Update> _UpdatesQueue = new   ConcurrentQueue<Update>();
  private volatile bool _AddingUpdates = false;
  public void InsertUpdate(Update update)
        {
            _UpdatesQueue.Enqueue(update);
            if (_AddingUpdates)
            {
                return;
            }

            lock (_updateQueueLock)
            {
                if (_AddingUpdates)
                {
                    return;
                }
                _AddingUpdates = true;
            }
            Task.Factory.StartNew(() =>
            {
                lock (_updateQueueLock)
                {
                    Update lastupdate = null;
                    while (_UpdatesQueue.TryDequeue(out update))
                    {
                        updateWindow.AddLast(update);
                    }
                }
            }).ContinueWith(x =>
            {
                _AddingUpdates = false;
            });
        }

        private volatile bool _Sampling = false;
        private readonly ConcurrentQueue<Tuple<Timestamp, Action<float>>> _RequestsQueue = new ConcurrentQueue<Tuple<Timestamp, Action<float>>>();

        public void GetFeatureAtTime(Timestamp time, Action<float> valueCallback)
        {
            _RequestsQueue.Enqueue(new Tuple<Timestamp, Action<float>>(time, valueCallback));
            if (_Sampling)
            {
                return;
            }

            lock (_updateQueueLock)
            {
                if (_Sampling)
                {
                    return;
                }
                _Sampling = true;
            }
            Task.Factory.StartNew(() =>
            {
                lock (_updateQueueLock)
                {
                    Timestamp lastTime = null;
                    while (_RequestsQueue.TryPeek(out var request))
                    {
                        GetFeatureAtTimeInternal(request.Item1, request.Item2, out var haveEnoughData);
                        if (haveEnoughData)
                        {
                            _RequestsQueue.TryDequeue(out _);
                        }
                        else
                        {
                            break;
                        }
                    }
                }

            }).ContinueWith(x => _Sampling = false);
        }

Из того, что яЕсли смотреть на инструмент Concurrency Visualizer в VS, то 76% процессорного времени уходит на синхронизацию.Кроме того, выборка иногда может быть длительным действием по сравнению со вставкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...