Нужна помощь профессионального программиста - страница 64

 
prostotrader #:

Наторговал за 2 недели :) на Т1


Мои поздравления! Это акция - фьюч? скальп... жесткий....? )

мотивируете к торгам!!!

спс Вам!

может статью об этом подходе написать? и как им пользоваться и чем лучше торговать? )

 

Добрый день!

Если кто-то знает как сделать, то подскажите пожалуйста.

Суть проблемы:

Во время работы моего ПО происходит переключения между тредами (TID).

Если в тредах (у меня 4 соединения и 4 БД) приема данных блок данных маленький, то заявка обрабатывается

практически без задержек.

2026-08-14 14:36:44.902460;cgate.user;; ---> DEBUG: Заявка 1963883665931640159 удаляется...;TID 19312
2026-08-14 14:36:44.902493;cgate.user;; ---> DEBUG: Delete order send...;TID 19180

2026-08-14 14:36:44.902545;P2ReplStorage;;Change revs (C);strm 0x36D3650;TID 26224
2026-08-14 14:36:44.902547;P2ReplStorage;;      tbl 0;revs 543789274-543789278(5);strm 0x36D3650;TID 26224
2026-08-14 14:36:44.907131;p2repl-cli;;<DATA;strm 0x36CDDA0;TID 4232
2026-08-14 14:36:44.907181;P2ReplStorage;;Change revs (C);strm 0x36CDDA0;TID 4232
2026-08-14 14:36:44.907183;P2ReplStorage;;      tbl 0;revs 67787695-67787700(6);strm 0x36CDDA0;TID 4232

2026-08-14 14:36:44.909545;cgate.user;; ---> DEBUG: Callback Remove order 1963883665931640159 done;TID 20352

2026-08-14 14:36:44.909688;p2repl-cli;;<DATA;strm 0x36CC340;TID 24872
2026-08-14 14:36:44.909722;cgate.user;; ---> DEBUG: FORTS_TRADE_REPL orders_log resived.;TID 24872
2026-08-14 14:36:44.909725;P2ReplStorage;;Change revs (C);strm 0x36CC340;TID 24872
2026-08-14 14:36:44.909726;P2ReplStorage;;      tbl 0;revs 338155323579-338155404251(1);strm 0x36CC340;TID 24872

2026-08-14 14:36:44.909793;cgate.user;; ---> DEBUG: Notyfication FORTS_TRADE_REPL orders_log done.;TID 6404
2026-08-14 14:36:44.909821;cgate.user;; ---> DEBUG: Call CheckOrderTransactions...;TID 20352
2026-08-14 14:36:44.909840;cgate.user;; ---> DEBUG: OrderSelect done.;TID 20352
2026-08-14 14:36:44.909847;cgate.user;; ---> DEBUG: Заявка на продажу 1963883665931640159 удалена.;TID 20352

Время обработки чуть более 7 мс

Но если блок входящих данных большой, то происходят огромные задержки в обработке заявки

2026-08-14 14:37:33.494291;cgate.user;; ---> DEBUG: Заявка на продажу BOC устанавливается...;TID 19312
2026-08-14 14:37:33.494316;cgate.user;; ---> DEBUG: Add order send...;TID 19180
2026-08-14 14:37:33.499789;cgate.user;; ---> DEBUG: Callback Get ticket 1963883665931644406 done;TID 20352

2026-08-14 14:37:33.501644;p2repl-cli;;<DATA;strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.502058;P2ReplStorage;;Change revs (C);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.502060;P2ReplStorage;;      tbl 0;revs 67914076-67914235(160);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.505281;p2repl-cli;;<DATA;strm 0x36D3650;TID 26224
2026-08-14 14:37:33.505512;P2ReplStorage;;Change revs (C);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.505514;P2ReplStorage;;      tbl 0;revs 543847600-543847632(33);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.511152;p2repl-cli;;<DATA;strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.511286;P2ReplStorage;;Change revs (C);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.511288;P2ReplStorage;;      tbl 0;revs 67914236-67914305(70);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.515912;p2repl-cli;;<DATA;strm 0x36D3650;TID 26224
2026-08-14 14:37:33.516339;P2ReplStorage;;Change revs (C);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.516343;P2ReplStorage;;      tbl 0;revs 543847633-543847666(34);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.523069;p2repl-cli;;<DATA;strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.523420;P2ReplStorage;;Change revs (C);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.523422;P2ReplStorage;;      tbl 0;revs 67914306-67914427(122);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.526502;p2repl-cli;;<DATA;strm 0x36D3650;TID 26224
2026-08-14 14:37:33.526544;p2repl-cli;;<DATA;strm 0x36CC340;TID 24872

2026-08-14 14:37:33.526574;cgate.user;; ---> DEBUG: FORTS_TRADE_REPL orders_log resived.;TID 24872

2026-08-14 14:37:33.526729;P2ReplStorage;;Change revs (C);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.526731;P2ReplStorage;;      tbl 0;revs 543847667-543847687(21);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.533099;p2repl-cli;;<DATA;strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.533614;P2ReplStorage;;Change revs (C);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.533615;P2ReplStorage;;      tbl 0;revs 67914428-67914625(198);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.537189;p2repl-cli;;<DATA;strm 0x36D3650;TID 26224
2026-08-14 14:37:33.537553;P2ReplStorage;;Change revs (C);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.537555;P2ReplStorage;;      tbl 0;revs 543847688-543847724(37);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.542912;p2repl-cli;;<DATA;strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.543164;P2ReplStorage;;Change revs (C);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.543165;P2ReplStorage;;      tbl 0;revs 67914626-67914710(85);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.547157;p2repl-cli;;<DATA;strm 0x36D3650;TID 26224
2026-08-14 14:37:33.547717;P2ReplStorage;;Change revs (C);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.547719;P2ReplStorage;;      tbl 0;revs 543847725-543847788(64);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.553701;p2repl-cli;;<DATA;strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.553835;P2ReplStorage;;Change revs (C);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.553837;P2ReplStorage;;      tbl 0;revs 67914711-67914747(37);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.557084;p2repl-cli;;<DATA;strm 0x36D3650;TID 26224
2026-08-14 14:37:33.557472;P2ReplStorage;;Change revs (C);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.557475;P2ReplStorage;;      tbl 0;revs 543847789-543847828(40);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.563782;p2repl-cli;;<DATA;strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.564051;P2ReplStorage;;Change revs (C);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.564055;P2ReplStorage;;      tbl 0;revs 67914748-67914824(77);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.565692;p2repl-cli;;<DATA;strm 0x36D3650;TID 26224
2026-08-14 14:37:33.565798;P2ReplStorage;;Change revs (C);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.565799;P2ReplStorage;;      tbl 0;revs 543847829-543847840(12);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.574476;p2repl-cli;;<DATA;strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.574599;P2ReplStorage;;Change revs (C);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.574602;P2ReplStorage;;      tbl 0;revs 67914825-67914857(33);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.577402;p2repl-cli;;<DATA;strm 0x36D3650;TID 26224
2026-08-14 14:37:33.577701;P2ReplStorage;;Change revs (C);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.577703;P2ReplStorage;;      tbl 0;revs 543847841-543847870(30);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.578428;P2ReplStorage;;Change revs (C);strm 0x36CC340;TID 24872
2026-08-14 14:37:33.578432;P2ReplStorage;;      tbl 0;revs 338155630543-338155632198(1);strm 0x36CC340;TID 24872

2026-08-14 14:37:33.578468;cgate.user;; ---> DEBUG: Notyfication FORTS_TRADE_REPL orders_log done.;TID 6404
2026-08-14 14:37:33.578473;cgate.user;; ---> DEBUG: Call CheckOrderTransactions...;TID 20352

2026-08-14 14:37:33.585216;p2repl-cli;;<DATA;strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.585419;P2ReplStorage;;Change revs (C);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.585421;P2ReplStorage;;      tbl 0;revs 67914858-67914923(66);strm 0x36CDDA0;TID 4232
2026-08-14 14:37:33.586797;p2repl-cli;;<DATA;strm 0x36D3650;TID 26224
2026-08-14 14:37:33.587024;P2ReplStorage;;Change revs (C);strm 0x36D3650;TID 26224
2026-08-14 14:37:33.587026;P2ReplStorage;;      tbl 0;revs 543847871-543847891(21);strm 0x36D3650;TID 26224

2026-08-14 14:37:33.594388;cgate.user;; ---> DEBUG: OrderSelect done.;TID 20352
2026-08-14 14:37:33.594425;cgate.user;; ---> DEBUG: Заявка на продажу 1963883665931644406 активна.;TID 20352

Время обработки более 100 мс !!!!!!

Задание приоритета тредам не помогает!!!

Что-нибудь можно сделать?

 
prostotrader #:

Добрый день!

Если кто-то знает как сделать, то подскажите пожалуйста.

Суть проблемы:

Во время работы моего ПО происходит переключения между тредами (TID).

Если в тредах (у меня 4 соединения и 4 БД) приема данных блок данных маленький, то заявка обрабатывается

практически без задержек.

Время обработки чуть более 7 мс

Но если блок входящих данных большой, то происходят огромные задержки в обработке заявки

Время обработки более 100 мс !!!!!!

Задание приоритета тредам не помогает!!!

Что-нибудь можно сделать?

в Linux я-бы советовал смотреть системные настройки планировщика IO и аллокатор памяти приложения.  И обратить внимание на парсер данных, по возможности поменять на SAX, резкий рост потребления чего-либо часто от манипуляция с DOM (когда в памяти строится временная динамическая структура - она когда маленькая всё быстро, а с ростом начинается катастрофа)

 
Maxim Kuznetsov #:

в Linux я-бы советовал смотреть системные настройки планировщика IO и аллокатор памяти приложения.  И обратить внимание на парсер данных, по возможности поменять на SAX, резкий рост потребления чего-либо часто от манипуляция с DOM (когда в памяти строится временная динамическая структура - она когда маленькая всё быстро, а с ростом начинается катастрофа)

Это W10
 
prostotrader #:
Это W10

я потому специально и отметил что совет о планировщике это про Linux. Что-такое может быть и в Win10.

чтобы совсем не упороться в системные дебри, лучше потратить день-два и написать тесты. Вот тут вот AI может помочь - тесты он генерит прилично. Самое очевидное это проверить парсер - как он себя ведёт на разных объёмах и вложенности данных.

 
prostotrader #:

Добрый день!

Если кто-то знает как сделать, то подскажите пожалуйста.

Суть проблемы:

Во время работы моего ПО происходит переключения между тредами (TID).


вот тут друг посоветовал начать с этого ) 

Судя по логам, дело не в приоритетах потоков, а в последовательной (упорядоченной) обработке сообщений внутри самого CGate.

Смотрите на сам лог: колбэк CheckOrderTransactions / OrderSelect (TID 20352) срабатывает только после того, как приходит уведомление FORTS_TRADE_REPL orders_log resived (TID 24872). А это уведомление, в свою очередь, приходит только после того, как два других потока (TID 4232 и TID 26224) закончат применять свои пачки ревизий — в "быстром" случае там единицы записей, а в "медленном" — по 30–200 записей за раз, и обработка каждой такой пачки занимает несколько мс, которые суммируются.

Похоже, что несколько p2repl-потоков (видимо, тяжёлый поток типа FORTS_FUTINFO / стакан / справочники и лёгкий, но критичный по задержке FORTS_TRADE_REPL) сидят на одном и том же соединении/маршрутизаторе CGate, и сообщения по ним разбираются строго по очереди в порядке прихода. Если перед orders_log в очереди оказалась пачка обновлений тяжёлого потока — она вся обработается первой, и только потом дойдёт очередь до заявки. Именно поэтому приоритет ОС-потоков не помогает: узкое место не в планировании CPU, а во внутренней последовательной обработке/блокировке очереди сообщений в самой библиотеке.

Что стоит попробовать:

— Развести потоки по разным соединениям CGate: FORTS_TRADE_REPL (свои заявки/сделки) — на отдельное лёгкое соединение, а тяжёлые потоки (стакан, справочники, futinfo и т.п.) — на другое соединение (можно даже в отдельном процессе). Это стандартный обход именно этой проблемы, который применяют в торговых системах на Plaza2/CGate — держать канал заявок изолированным от канала рыночных данных.

— Проверить, что именно "сидит" на том же соединении, что и orders_log — судя по счётчикам ревизий (десятки-сотни за раз), это явно что-то с большим потоком обновлений.

— Если разнести соединения нельзя, посмотреть в документации/строке подключения CGate, нет ли параметров буферизации/приоритезации потоков на уровне роутера (иногда это regulate через scheme /буфер размеры) — но это не факт, что поможет так же радикально, как разделение соединений.

— Заодно проверить, не делает ли CheckOrderTransactions / OrderSelect полный проход по локальной реплике таблицы — если это так, и она защищена тем же мьютексом, что и P2ReplStorage , это дополнительный источник задержки поверх очереди сообщений. Лучше вести состояние заявок инкрементально по приходящим колбэкам, а не дёргать выборку из таблицы синхронно.

Стоит сначала быстро проверить гипотезу: вынести только FORTS_TRADE_REPL на отдельное соединение и посмотреть, уйдёт ли задержка — это не такая большая переделка, но подтвердит или опровергнёт причину.

точечно проинструментировать код:

— замерить время между соседними "p2repl-cli <DATA" (это происходит целиком внутри CGate, до его кода — если тут набегает основная задержка, то дело в очереди/диспетчере библиотеки, и тогда решение — разнести FORTS_TRADE_REPL и "тяжёлые" потоки по разным соединениям, как я писал выше);

— отдельно замерить время, которое тратит именно его обработчик "Change revs" → запись в БД (если тут время растёт непропорционально размеру пачки — это как раз случай Максима, и лечится переходом на построчную/потоковую запись вместо "накопить и записать одним блоком").

Это буквально день работы — добавить пару QueryPerformanceCounter/std::chrono замеров в оба места и сделать 10–20 заявок под нагрузкой и без. Дальше по цифрам будет видно, куда копать: в конфигурацию соединений CGate или в свой код работы с БД.

 
Roman Shiredchenko #:

вот тут друг посоветовал начать с этого ) 

Судя по логам, дело не в приоритетах потоков, а в последовательной (упорядоченной) обработке сообщений внутри самого CGate.

Смотрите на сам лог: колбэк CheckOrderTransactions / OrderSelect (TID 20352) срабатывает только после того, как приходит уведомление FORTS_TRADE_REPL orders_log resived (TID 24872). А это уведомление, в свою очередь, приходит только после того, как два других потока (TID 4232 и TID 26224) закончат применять свои пачки ревизий — в "быстром" случае там единицы записей, а в "медленном" — по 30–200 записей за раз, и обработка каждой такой пачки занимает несколько мс, которые суммируются.

Похоже, что несколько p2repl-потоков (видимо, тяжёлый поток типа FORTS_FUTINFO / стакан / справочники и лёгкий, но критичный по задержке FORTS_TRADE_REPL) сидят на одном и том же соединении/маршрутизаторе CGate, и сообщения по ним разбираются строго по очереди в порядке прихода. Если перед orders_log в очереди оказалась пачка обновлений тяжёлого потока — она вся обработается первой, и только потом дойдёт очередь до заявки. Именно поэтому приоритет ОС-потоков не помогает: узкое место не в планировании CPU, а во внутренней последовательной обработке/блокировке очереди сообщений в самой библиотеке.

Что стоит попробовать:

— Развести потоки по разным соединениям CGate: FORTS_TRADE_REPL (свои заявки/сделки) — на отдельное лёгкое соединение, а тяжёлые потоки (стакан, справочники, futinfo и т.п.) — на другое соединение (можно даже в отдельном процессе). Это стандартный обход именно этой проблемы, который применяют в торговых системах на Plaza2/CGate — держать канал заявок изолированным от канала рыночных данных.

— Проверить, что именно "сидит" на том же соединении, что и orders_log — судя по счётчикам ревизий (десятки-сотни за раз), это явно что-то с большим потоком обновлений.

— Если разнести соединения нельзя, посмотреть в документации/строке подключения CGate, нет ли параметров буферизации/приоритезации потоков на уровне роутера (иногда это regulate через scheme /буфер размеры) — но это не факт, что поможет так же радикально, как разделение соединений.

— Заодно проверить, не делает ли CheckOrderTransactions / OrderSelect полный проход по локальной реплике таблицы — если это так, и она защищена тем же мьютексом, что и P2ReplStorage , это дополнительный источник задержки поверх очереди сообщений. Лучше вести состояние заявок инкрементально по приходящим колбэкам, а не дёргать выборку из таблицы синхронно.

Стоит сначала быстро проверить гипотезу: вынести только FORTS_TRADE_REPL на отдельное соединение и посмотреть, уйдёт ли задержка — это не такая большая переделка, но подтвердит или опровергнёт причину.

точечно проинструментировать код:

— замерить время между соседними "p2repl-cli <DATA" (это происходит целиком внутри CGate, до его кода — если тут набегает основная задержка, то дело в очереди/диспетчере библиотеки, и тогда решение — разнести FORTS_TRADE_REPL и "тяжёлые" потоки по разным соединениям, как я писал выше);

— отдельно замерить время, которое тратит именно его обработчик "Change revs" → запись в БД (если тут время растёт непропорционально размеру пачки — это как раз случай Максима, и лечится переходом на построчную/потоковую запись вместо "накопить и записать одним блоком").

Это буквально день работы — добавить пару QueryPerformanceCounter/std::chrono замеров в оба места и сделать 10–20 заявок под нагрузкой и без. Дальше по цифрам будет видно, куда копать: в конфигурацию соединений CGate или в свой код работы с БД.

Дело не в разделении потоков, а в планировщике виндоус.

Начавший работать тред останавливается и начинает работать другой. 

После получения нотификации от БД (данные по ордерам обработаны)

2026-08-14 14:37:33.578468;cgate.user;; ---> DEBUG: Notyfication FORTS_TRADE_REPL orders_log done.;TID 6404
2026-08-14 14:37:33.578473;cgate.user;; ---> DEBUG: Call CheckOrderTransactions...;TID 20352

, начинает работать тред  

TID 20352

А когда начинают приходить новые данные (в другом) треде, то планировщик останавливает работающий тред и передает управление тредам приема данных.

Нужно как-то заставить, что бы тред 20352 доработал до конца.

Добавлено

На прием данных от Плазы 2 работают 4 независимых треда, каждый имеет свою БД, разделение потоков специально было сделано, чтобы стаканы и тики не мешали друг-другу, ровно как и ордера, сделки, позиции... 

Например  тред  TExpCallBacks = class(TThread) отвечает за 

procedure TExpCallBacks.Execute;
var
  Res: DWORD;
begin
  while not Terminated do
  begin
    Res:= WaitForMultipleObjects(7, @fEvents, False, INFINITE);
    case Res of
      WAIT_OBJECT_0    : OrderCallBack();                                       // Order call back
      WAIT_OBJECT_0 + 1: ProcessOrders();                                       // Check orders
      WAIT_OBJECT_0 + 2: ProcessTimeCb();
      WAIT_OBJECT_0 + 3: fExpert.RefSysID:= fExpert.GetRefSysID(fExpert.RefSysID);
      WAIT_OBJECT_0 + 4: fExpert.ClrSysID:= fExpert.GetClrSysID(fExpert.ClrSysID);
      WAIT_OBJECT_0 + 5: ProcessSession();
      WAIT_OBJECT_0 + 6: break;
      WAIT_FAILED: fExpert.SendMess('Внутреняя ошибка TExpCallBacks!');
    end;
  end;
end;

Нотификация как раз "дергает" эвенту

 WAIT_OBJECT_0 + 1: ProcessOrders(); 
но планировщик тормозит функцию ProcessOrders() и передает управление тредам приема данных!
 
prostotrader #:

но планировщик тормозит функцию ProcessOrders() и передает управление тредам приема данных!

А если привязать принудительно в планировщике всё к одному ядру, или наоборот каждый модуль к своему? Повысить приоритет?
 
Aleksey Vyazmikin #:
А если привязать принудительно в планировщике всё к одному ядру, или наоборот каждый модуль к своему? Повысить приоритет?

У меня 8 ядер, разносил по физическим ядрам - не помогло!

Архитектура Коннектора очень сложная

Сейчас одновременно работают 5 тредов 4 наполняют БД, а 1 транзакции и коллбэки. 

Но проблема может еще заключаться в том, что каждый робот (Expert-DLL) - имеет внутри 3 треда

  TExpert = class;    // Ahead declaration

// --- Orders manager ---
  TOrdersManager = class

//--- Market data ---
  TExpMarket = class(TThread)


//--- Trade class --
  TExpTrade = class(TThread)


//--- CallBacks class ---
  TExpCallBacks = class(TThread)

Каждый тред работает в режиме ожидания, ждет управляющие эвенты, что бы не вешать процессор.

А, сейчас в бою 120 советников.


Добавлено

Еще нужно учитывать GUI сплошные очереди и треды :)

TTask = class
    protected
      FSync: boolean;
    public
      constructor Create();
      destructor Destroy(); override;
      procedure Run(); virtual;
  end;

//--- GUI task ---
  TGuiTask = class(TTask)
    public
      constructor Create();
      destructor Destroy(); override;
  end;

//--- Queue thread ---
  TCGQueue = class(TThread)
 
prostotrader #:

У меня 8 ядер, разносил по физическим ядрам - не помогло!

Так а уровень приоритета пробовали менять для разных модулей?
Другой вариант - писать данные от сети в буфер, а только потом в БД, может сетевые запросы имеют высокий приоритет, да ещё операции с БД.
А так - сложно судить, тут действительно надо примитивный код для моделирования ситуации создать и искать причину с привлечением LLM (если специалиста нет).