Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Наторговал за 2 недели :) на Т1
Мои поздравления! Это акция - фьюч? скальп... жесткий....? )
мотивируете к торгам!!!
спс Вам!
может статью об этом подходе написать? и как им пользоваться и чем лучше торговать? )
Добрый день!
Если кто-то знает как сделать, то подскажите пожалуйста.
Суть проблемы:
Во время работы моего ПО происходит переключения между тредами (TID).
Если в тредах (у меня 4 соединения и 4 БД) приема данных блок данных маленький, то заявка обрабатывается
практически без задержек.
Время обработки чуть более 7 мс
Но если блок входящих данных большой, то происходят огромные задержки в обработке заявки
Время обработки более 100 мс !!!!!!
Задание приоритета тредам не помогает!!!
Что-нибудь можно сделать?
Добрый день!
Если кто-то знает как сделать, то подскажите пожалуйста.
Суть проблемы:
Во время работы моего ПО происходит переключения между тредами (TID).
Если в тредах (у меня 4 соединения и 4 БД) приема данных блок данных маленький, то заявка обрабатывается
практически без задержек.
Время обработки чуть более 7 мс
Но если блок входящих данных большой, то происходят огромные задержки в обработке заявки
Время обработки более 100 мс !!!!!!
Задание приоритета тредам не помогает!!!
Что-нибудь можно сделать?
в Linux я-бы советовал смотреть системные настройки планировщика IO и аллокатор памяти приложения. И обратить внимание на парсер данных, по возможности поменять на SAX, резкий рост потребления чего-либо часто от манипуляция с DOM (когда в памяти строится временная динамическая структура - она когда маленькая всё быстро, а с ростом начинается катастрофа)
в Linux я-бы советовал смотреть системные настройки планировщика IO и аллокатор памяти приложения. И обратить внимание на парсер данных, по возможности поменять на SAX, резкий рост потребления чего-либо часто от манипуляция с DOM (когда в памяти строится временная динамическая структура - она когда маленькая всё быстро, а с ростом начинается катастрофа)
Это W10
я потому специально и отметил что совет о планировщике это про Linux. Что-такое может быть и в Win10.
чтобы совсем не упороться в системные дебри, лучше потратить день-два и написать тесты. Вот тут вот AI может помочь - тесты он генерит прилично. Самое очевидное это проверить парсер - как он себя ведёт на разных объёмах и вложенности данных.
Добрый день!
Если кто-то знает как сделать, то подскажите пожалуйста.
Суть проблемы:
Во время работы моего ПО происходит переключения между тредами (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 или в свой код работы с БД.
вот тут друг посоветовал начать с этого )
Судя по логам, дело не в приоритетах потоков, а в последовательной (упорядоченной) обработке сообщений внутри самого 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 или в свой код работы с БД.
Дело не в разделении потоков, а в планировщике виндоус.
Начавший работать тред останавливается и начинает работать другой.
После получения нотификации от БД (данные по ордерам обработаны)
, начинает работать тред
TID 20352А когда начинают приходить новые данные (в другом) треде, то планировщик останавливает работающий тред и передает управление тредам приема данных.
Нужно как-то заставить, что бы тред 20352 доработал до конца.
Добавлено
На прием данных от Плазы 2 работают 4 независимых треда, каждый имеет свою БД, разделение потоков специально было сделано, чтобы стаканы и тики не мешали друг-другу, ровно как и ордера, сделки, позиции...
Например тред TExpCallBacks = class(TThread) отвечает за
Нотификация как раз "дергает" эвенту
WAIT_OBJECT_0 + 1: ProcessOrders();но планировщик тормозит функцию ProcessOrders() и передает управление тредам приема данных!
А если привязать принудительно в планировщике всё к одному ядру, или наоборот каждый модуль к своему? Повысить приоритет?
У меня 8 ядер, разносил по физическим ядрам - не помогло!
Архитектура Коннектора очень сложная
Сейчас одновременно работают 5 тредов 4 наполняют БД, а 1 транзакции и коллбэки.
Но проблема может еще заключаться в том, что каждый робот (Expert-DLL) - имеет внутри 3 треда
Каждый тред работает в режиме ожидания, ждет управляющие эвенты, что бы не вешать процессор.
А, сейчас в бою 120 советников.
Добавлено
Еще нужно учитывать GUI сплошные очереди и треды :)
У меня 8 ядер, разносил по физическим ядрам - не помогло!
Другой вариант - писать данные от сети в буфер, а только потом в БД, может сетевые запросы имеют высокий приоритет, да ещё операции с БД.
А так - сложно судить, тут действительно надо примитивный код для моделирования ситуации создать и искать причину с привлечением LLM (если специалиста нет).