Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Lock-free кольцевой буфер. / 15 сообщений из 15, страница 1 из 1
14.02.2020, 18:48
    #39926872
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
На просторах интернета встретилось несколько реализаций на Delphi. И даже на любимом sql.ru. Но все они показались мне замороченные и если честно очень длинные, хотя возможно и быстрые.
У меня же задача простая. Есть 1 поток писатель и 1 поток читатель. Буфер создается заранее и заполняется массивами TidBytes.
Если писатель быстрее читателя или наоборот, то ждем.
Так как я еще тот синхронизатор/оптимизатор, то подскажите свежим взглядом, где могут быть ошибки чтения/записи в буфер?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
TLockFreeQueue = class
    private
      FHead: Int64;
      FTail: Int64;
      FSize: int64;
      FItems: array of TPacket;
    public
      function PushObject(AData: TidBytes; ASize: integer): boolean;
      function PopObject(): TPacket;
      constructor Create(const ASize: integer);
      destructor Destroy(); override;
    end;

constructor TLockFreeQueue.Create(const ASize: integer);
var
  i: integer;
begin
  FHead:= 0; //заполняет писатель
  FTail:= 0; //заполняет читатель
  FSize:= ASize;
  SetLength(FItems, ASize);
  for i := Low(FItems) to High(FItems) do
  FItems[i]:= TPacket.Create(UDP_PACKET_SIZE);
end;

destructor TLockFreeQueue.Destroy;
var
  i: integer;
begin
  try
    for i := Low(FItems) to High(FItems) do
    FItems[i].Free;
    FItems:= nil;
  finally
    inherited;
  end;
end;

function TLockFreeQueue.PushObject(AData: TidBytes; ASize: integer): boolean;
var
  Next: integer;
begin

  Next:= TInterlocked.Read(FHead)+1;

  if Next >= FSize then Next:= 0;

  if Next = TInterlocked.Read(FTail) then
  begin
    Result:= False;
    Exit;
  end;

  CopyTIdBytes(AData, 0, FItems[FHead].PackUDP, 0, ASize);
  FItems[FHead].Size:= ASize;

  TInterlocked.Exchange(FHead, Next);
  Result:= True;
end;

function TLockFreeQueue.PopObject(): TPacket;
var
  Next: integer;
begin

  if (TInterlocked.Read(FHead) = TInterlocked.Read(FTail)) then begin
    Result := nil;
    Exit;
  end;

  Next:= TInterlocked.Read(FTail)+1;

  if Next >= FSize then
  Next:= 0;

  Result:= FItems[FTail];
  TInterlocked.Exchange(FTail, Next);
end;
...
Рейтинг: 0 / 0
14.02.2020, 18:58
    #39926877
X-Cite
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
Вашу проблему решает уже готовый

http://docwiki.embarcadero.com/Libraries/Rio/en/System.Generics.Collections.TThreadedQueue

при этом он решает еще и задачу несколько читают, несколько пишут.
...
Рейтинг: 0 / 0
14.02.2020, 19:18
    #39926890
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
все так. так и использую на текущий момент. Но скорости не хватает. В целом архитектура такая: Один писатель и куча читателей.
Для каждого читателя отдельная очередь с писателем. И такое чувство, что читатели через крит. секции притормаживают писателя, а мне это совсем не нравиться
...
Рейтинг: 0 / 0
14.02.2020, 19:26
    #39926893
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
X-Cite
Вашу проблему решает уже готовый
http://docwiki.embarcadero.com/Libraries/Rio/en/System.Generics.Collections.TThreadedQueue
при этом он решает еще и задачу несколько читают, несколько пишут.
Только там до Токио включительно, был баг в методе Grow
...
Рейтинг: 0 / 0
14.02.2020, 19:43
    #39926901
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
cptngrb
где могут быть ошибки чтения/записи в буфер?
При наличии более одного читателя или писателя ошибки гарантированы

TInterlocked.Exchange для одного читателя/писателя не имеет смысла, для нескольких смотри выше

TInterlocked.Read вообще бессмысленен.
...
Рейтинг: 0 / 0
14.02.2020, 19:43
    #39926902
X-Cite
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
cptngrb
все так. так и использую на текущий момент. Но скорости не хватает. В целом архитектура такая: Один писатель и куча читателей.
Для каждого читателя отдельная очередь с писателем. И такое чувство, что читатели через крит. секции притормаживают писателя, а мне это совсем не нравиться

Монитор написан так, что если вы бесконечно пишете и читаете то критическая секция никогда не сработает. Там первые вроде 50 циклов/тактов проверка на ожидание как раз фрилоковая, а потом чтобы не нагружать процессор уже блокировка.
...
Рейтинг: 0 / 0
14.02.2020, 19:51
    #39926904
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
X-Cite,бесконечно пишете и читаете то критическая секция никогда не сработает. В смысле? А как же синхронизация?
...
Рейтинг: 0 / 0
14.02.2020, 19:53
    #39926905
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
Вопрос не совсем по теме. А никто не знает какая пропускная способность сокета UDP?
...
Рейтинг: 0 / 0
14.02.2020, 19:56
    #39926907
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
cptngrbВ целом архитектура такая: Один писатель и куча читателей.
Для каждого читателя отдельная очередь с писателем. И такое чувство, что читатели через
крит. секции притормаживают писателя

Это для UDP? Какая-то вывернутая наизнанку архитектура. Обычно бывает наоборот: один поток
только и делает что читает из сокета, а все остальные в него пишут, даже не
синхронизируясь, ибо blocking mode.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
14.02.2020, 20:17
    #39926913
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
Dimitry Sibiryakov, мне нужно читать только. Я одним потоком считываю с сокета данные и передаю в другие, которые уже собирают из пакетов конфетку
...
Рейтинг: 0 / 0
14.02.2020, 20:18
    #39926914
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
просто я называю поток, который читает из сокета ПИСАТЕЛЕМ своего буфера
...
Рейтинг: 0 / 0
14.02.2020, 21:06
    #39926921
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
Тогда lock-free алгоритмы тебе не только не нужны, но и полностью противопоказаны,
поскольку приводят к процессорному голоданию producer-а.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
15.02.2020, 15:06
    #39927010
Bred eFeM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
cptngrb, Для каждого читателя отдельная очередь с писателем.для синхры достаточно одного boolean без interlockИ такое чувство, что читатели через крит. секции притормаживают писателяну,Если писатель быстрее читателя или наоборот, то ждем.и как ты ждёшь?
(если ждёшь, то это уже не Lock-free)



И такое чувствосделай чтобы это было не чувство, а реальные цифры



Я одним потоком считываю с сокета данные и передаю в другие, которые уже собирают из пакетов конфеткуЕсли цена передачи данных между потоками соизмерима со сбором конфетки, то можно ускориться в разы используя пул потоков считывателей из сокета (например, IOCP) внутри которых и будет обработка.
...
Рейтинг: 0 / 0
16.02.2020, 09:09
    #39927119
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
[quot Bred eFeM#22080498]и как ты ждёшь?
В первом посте вроде понятно. Кто быстрее тот и ждет.

IOCP надо попробовать
...
Рейтинг: 0 / 0
16.02.2020, 11:59
    #39927136
pvv.pas
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Lock-free кольцевой буфер.
cptngrb,

В комплекте black shark есть коллекция TQueueFIFO<T> для пары потоков отлично работает без использования системных средств синхронизации. Но я использовал только для асинхронной очереди, т.е. с возможностью потерь в случае переполнения. Синхронный режим возможно не будет работать, хотя опция есть. Посмотрел код, как по мне - доработать не проблема.
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Lock-free кольцевой буфер. / 15 сообщений из 15, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]