.Net обработка данных за 5 ms железно
От: arkhivania  
Дата: 07.01.11 15:03
Оценка:
Всем привет и с Новым Годом
У меня такой вопрос к людям, которые хардкорно используют возможности .Net. Пишу программу с "очень богатым" пользовательским интерфейсом на WPF. Выбрал WPF так как понимаю, что "очень богатый" интерфейс со всеми пожеланиями потенциальных пользователей в конкретном случае на нем реализовать гораздо проще. Написал программу уже на пятую часть, но столкнулся с интересной проблемой. Дело в том что мое .Net приложение очень тесно работает с драйвером железки, которая в потоке драйвера дергает у меня один метод, который должен в течение 5 ms (а на самом деле желательно быстрее) заполнить небольшой буффер (в несколько сот байтов) значениями. Надо сказать, что при формировании этих значений в буфере у меня участвуют несколько десятков managed классов и вызывается для каждого буфера по несколько сот методов, как managed написанных на .Net так и unmanaged написанных на C++. Я отлично понимал, что во время обработки данных, не стоит пользоваться всем, что может привести к выделению дополнительной памяти, и всё, что как-то может зависнуть на операциях с операционной системой. Поэтому у меня все методы, которые условно участвуют в обработке реального времени не используют оператор new, не используют linq (который создает объекты IEnumerable в куче), там где уж совсем нельзя использовал stackalloc (хотя в результате и без него обошелся), в общем обошел (вроде) все ситуации, но... В общем-то программа расчитана на то, что во время работы с этой железкой, пользователь не сидит сложа руки, он их (руки) использует по всем направлениям, тыкает, то туда, то сюда. А так как интерфейс написан полностью на WPF, то там происходят весьма интересные создания и умирания объектов, контроль за которыми на себя взял WPF. Так вот с чем я столкнулся: оказалось, что мои действия в пользовательском интерфейсе приводят к работе сборщика мусора, который блокирует мои самые важные вычисления буффера. Я прочитал про настройки сборщика мусора, нашел чудо режимы gcServer, LowLatency. В общем-то на мой субъективный взгляд LowLatency почти рещил проблему, но не до конца (а жаль).
На настоящий момент, я почти отчаялся, решил, что зря я так расдухорился и такие важные вычисления оставил на долю управляемого кода, и морально подготовился к тому, что движок (а это месяца два аккуратного проектирования) придется переносить на C++ (который я люблю использовать для математики, но не для сложных связей объектов). Может у кого-нибудь возникнут мега-гениальные идеи как:

1) понять что приводит к временным затыкам в течение 5 мс (к сожалению профайлеры мне говорят только статистику по нескольким тысячам вызовов, а тут видимо в какой-то момент хитрый во время работы с пользовательским интерфейсом происходит сбой по времени)
2) если есть возможность для конкретного потока приостановить работу GC, чтобы он не начинал свою чистку во время вычислений

ну и может есть методы, которые мне покажут, в какой момент внутри потока драйвера произошла задержка больше 5 ms.

Спасибо!
Re: .Net обработка данных за 5 ms железно
От: rasp_file Украина  
Дата: 07.01.11 15:22
Оценка: +1
Здравствуйте, arkhivania, Вы писали:

Риторический вопрос. А зачем было выбирать .NET для "приложения, которое очень тесно работает с драйвером железки" (realtime походу) и поиметь все уже описаные проблемы написания такого приложения.
Хотя бы

The moment when the garbage is actually collected can be unpredictable, resulting in stalls scattered throughout a session. Unpredictable stalls can be unacceptable in real-time environments such as device drivers, in transaction processing,

например.
... << RSDN@Home 1.2.0 alpha 4 rev. 1481>>
Re: .Net обработка данных за 5 ms железно
От: Sinix  
Дата: 07.01.11 15:27
Оценка: 4 (3)
Здравствуйте, arkhivania, Вы писали:

Победите gc — вам ещё бороться с прерываниями/с планировщиком.

Есть ли возможность лениво заполнять данные, или как-то кэшировать их?
Пробовали ли RuntimeHelpers.PrepareConstrainedRegions()? Также см
Guidelines for Using Low Latency

Wrap the low latency code in constrained execution regions (for more information, see Constrained Execution Regions).


Наконец, разнесите работу с драйвером и UI в разные процессы.
Re[2]: .Net обработка данных за 5 ms железно
От: arkhivania  
Дата: 07.01.11 15:47
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, arkhivania, Вы писали:


S>Победите gc — вам ещё бороться с прерываниями/с планировщиком.


S>Есть ли возможность лениво заполнять данные, или как-то кэшировать их?

S>Пробовали ли RuntimeHelpers.PrepareConstrainedRegions()? Также см
S>Guidelines for Using Low Latency
S>

S>Wrap the low latency code in constrained execution regions (for more information, see Constrained Execution Regions).


S>Наконец, разнесите работу с драйвером и UI в разные процессы.


Спасибо, не заметил про constrained execution regions.

Попробую.
Re: .Net обработка данных за 5 ms железно
От: Kerbadun  
Дата: 07.01.11 15:55
Оценка: 2 (1) +1
Здравствуйте, arkhivania, Вы писали:

О, опять тема реального времени под виндой.

A>Я отлично понимал, что во время обработки данных, не стоит пользоваться всем, что может привести к выделению дополнительной памяти, и всё, что как-то может зависнуть на операциях с операционной системой. Поэтому у меня все методы, которые условно участвуют в обработке реального времени не используют оператор new, не используют linq (который создает объекты IEnumerable в куче), там где уж совсем нельзя использовал stackalloc (хотя в результате и без него обошелся), в общем обошел (вроде) все ситуации, но...


По-моему, вы зря раньше времени начали городить огород. Как видите, это все еще и не помогло, скорее всего, оно вообще особо не влияет.

Собственно, что делать, не знаю. Могу только порекомендовать известную статью про многопоточность под Windows XP.

Когда он умрет, его мозг заспиртуют в стакане
Re: .Net обработка данных за 5 ms железно
От: Visor2004  
Дата: 07.01.11 16:59
Оценка: +1
Здравствуйте, arkhivania, Вы писали:

разнесите логику формирования своих буферов и UI в разные процессы, пусть буфера формирует какая-нить служба, с которой при необходимости соединяется UI и пользователь меняет состояние системы через него. Пользователь явно не будет успевать давить на кнопки с частотой 5мс, поэтому буфера вам надо генерировать исходя из какого-то внутреннего состояния, которое в реальности не меняется каждые 5 мс.
Ну а вообще, если по правильному делать такое, то вам надо смотреть QNX или VxWorks для реализации службы с такими требованиями к работе. Для связи UI и службы можно будет использовать SOAP, в .NET есть реализации для связи по этому протоколу.
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re[2]: .Net обработка данных за 5 ms железно
От: Sinix  
Дата: 07.01.11 17:36
Оценка:
Здравствуйте, Visor2004, Вы писали:

Всё правильно, только для связи между службой и приложением лучше использовать named pipes напрямую, или обернуть в WCF.
Re[3]: .Net обработка данных за 5 ms железно
От: Visor2004  
Дата: 07.01.11 17:40
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Visor2004, Вы писали:


S>Всё правильно, только для связи между службой и приложением лучше использовать named pipes напрямую, или обернуть в WCF.


Тут уже все равно в принципе, что автор будет использовать, всяко оно будет работать быстрее чем пользователь. Просто SOAP более универсально с точки зрения платформы, я уверен, что для преложенных систем можно будет найти библиотеки, которые умеют с SOAP работать, а как оно работает с виндовыми каналами
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re[2]: .Net обработка данных за 5 ms железно
От: xobotik Россия  
Дата: 07.01.11 18:30
Оценка:
Здравствуйте, Kerbadun, Вы писали:

K>Собственно, что делать, не знаю. Могу только порекомендовать известную статью про многопоточность под Windows XP.


Классная статья =) Спасибо=)
С уважением!
Re[2]: .Net обработка данных за 5 ms железно
От: arkhivania  
Дата: 07.01.11 18:37
Оценка:
Здравствуйте, Visor2004, Вы писали:

V>Здравствуйте, arkhivania, Вы писали:


V>разнесите логику формирования своих буферов и UI в разные процессы, пусть буфера формирует какая-нить служба, с которой при необходимости соединяется UI и пользователь меняет состояние системы через него. Пользователь явно не будет успевать давить на кнопки с частотой 5мс, поэтому буфера вам надо генерировать исходя из какого-то внутреннего состояния, которое в реальности не меняется каждые 5 мс.

V>Ну а вообще, если по правильному делать такое, то вам надо смотреть QNX или VxWorks для реализации службы с такими требованиями к работе. Для связи UI и службы можно будет использовать SOAP, в .NET есть реализации для связи по этому протоколу.

В общем-то всё верно, но тут такая в общем-то смешная задача, что есть причины по которой это должен быть один процесс. У меня теперь такой вопрос:
ведь .Net приложение не суспендирует все потоки процесса во время сборки мусора, то есть если я на C-шном уровне сделаю поток и в нем всё посчитаю без управляемого кода, всё будет ок?
Re: .Net обработка данных за 5 ms железно
От: _FRED_ Черногория
Дата: 07.01.11 20:03
Оценка:
Здравствуйте, arkhivania, Вы писали:

A>У меня такой вопрос к людям, которые хардкорно используют возможности .Net.…


A>1) понять что приводит к временным затыкам в течение 5 мс (к сожалению профайлеры мне говорят только статистику по нескольким тысячам вызовов, а тут видимо в какой-то момент хитрый во время работы с пользовательским интерфейсом происходит сбой по времени)




Не то вы понимаете. Почитайте Рихтера или статьи на этом сайте
Автор(ы): Чистяков Влад (VladD2)
Дата: 14.06.2006
Уже много сказано слов о том, что такое GC, чем он хорош и как лучше его применять. Но, наверно, очень многим хочется знать, как устроен конкретный GC. Данная статья открывает некоторые подробности устройчтва GC в .NET Framework.
, что бы разобраться с тем, как в дотнет выделяется память. Коротко говоря — это очень быстрая операция. Из-за неё переживать не стоит (если вы создаёте множество небольших по размерам объектов).

Отказ от линка может быть оправдан, но не из-за "создает объекты IEnumerable в куче" а из-за того, что его АПИ построен на вызове делегатов, который, относительно прямых вызовов, дорог.

Так же, из того, что вы описали, весьма существенно время на переключение между managed/unmanaged вызовами. Если возможно, попробуйте свормировать интерфейс неуправляемых вызовов таким образом, что бы пришлось как можно реже переключаться.

A>На настоящий момент, я почти отчаялся, решил, что зря я так расдухорился и такие важные вычисления оставил на долю управляемого кода, и морально подготовился к тому, что движок (а это месяца два аккуратного проектирования) придется переносить на C++ (который я люблю использовать для математики, но не для сложных связей объектов). Может у кого-нибудь возникнут мега-гениальные идеи как:


A>ну и может есть методы, которые мне покажут, в какой момент внутри потока драйвера произошла задержка больше 5 ms.


Есть: терпение и профилирование.
Help will always be given at Hogwarts to those who ask for it.
Re[3]: .Net обработка данных за 5 ms железно
От: Visor2004  
Дата: 08.01.11 00:10
Оценка:
Здравствуйте, arkhivania, Вы писали:
A>ведь .Net приложение не суспендирует все потоки процесса во время сборки мусора,


A>то есть если я на C-шном уровне сделаю поток и в нем всё посчитаю без управляемого кода, всё будет ок?


сделайте прототип и посмотрите. Теоретически, сборщик мусора ничего о потоках не знает, он просто ищет части графа объектов, от которых нет путей к pinned объектам и удаляет найденные. Как конкретно поступает среда исполнения при выполнении сборки мусора я не знаю, но мне кажется, что она просто перебирает все потоки, порожденные текущим процессом и останавливает их. Хотя я никогда сам не проверял и могу ошибаться тут.
Помните!!! ваш говнокод кому-то предстоит разгребать.
Re[2]: .Net обработка данных за 5 ms железно
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 08.01.11 04:59
Оценка:
Здравствуйте, Kerbadun, Вы писали:

K>Собственно, что делать, не знаю. Могу только порекомендовать известную статью про многопоточность под Windows XP.


Эта статья безнадёжно устарела. Сейчас одноядерные процессоры поискать надо — почти все имеют 2 ядра или больше...
[КУ] оккупировала армия.
Re: .Net обработка данных за 5 ms железно
От: Pavel Dvorkin Россия  
Дата: 08.01.11 09:10
Оценка: +4
Здравствуйте, arkhivania, Вы писали:

За 5 мсек железно ничего гарантировать нельзя в Windows — хоть с дотнетом, хоть без него. Windows не есть система реального времени.
With best regards
Pavel Dvorkin
Re[2]: .Net обработка данных за 5 ms железно
От: arkhivania  
Дата: 08.01.11 12:05
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, arkhivania, Вы писали:


PD>За 5 мсек железно ничего гарантировать нельзя в Windows — хоть с дотнетом, хоть без него. Windows не есть система реального времени.


Да мне хотя бы деревянно Sample приложение нативное от драйвера железки работает вполне железно, если не прыгать особенно между процессами и не заводить в комп в сонный режим.

Всё-таки у меня вопрос: будет ли сборщик мусора останавливать все потоки приложения, или только те, что используют управляемый код?
Re[2]: .Net обработка данных за 5 ms железно
От: arkhivania  
Дата: 08.01.11 12:10
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Не то вы понимаете. Почитайте Рихтера или статьи на этом сайте
Автор(ы): Чистяков Влад (VladD2)
Дата: 14.06.2006
Уже много сказано слов о том, что такое GC, чем он хорош и как лучше его применять. Но, наверно, очень многим хочется знать, как устроен конкретный GC. Данная статья открывает некоторые подробности устройчтва GC в .NET Framework.
, что бы разобраться с тем, как в дотнет выделяется память. Коротко говоря — это очень быстрая операция. Из-за неё переживать не стоит (если вы создаёте множество небольших по размерам объектов).


Я хорошо читал эту статью и достаточно хорошо представляю, как работает куча и сборщик мусора. Поэтому попытался минимально нагружать работу сборщика.

_FR>Отказ от линка может быть оправдан, но не из-за "создает объекты IEnumerable в куче" а из-за того, что его АПИ построен на вызове делегатов, который, относительно прямых вызовов, дорог.


Но создание новых IEnumerable в профайлере заметно увеличил во времени время сборки мусора, когда я от них избавился, время сборки мусора заметно уменьшилось.

_FR>Так же, из того, что вы описали, весьма существенно время на переключение между managed/unmanaged вызовами. Если возможно, попробуйте свормировать интерфейс неуправляемых вызовов таким образом, что бы пришлось как можно реже переключаться.


Это действительно очень жалко, но я всё-равно смирился с тем что надо писать обсчет в потоке драйвера на чистом С без управляемого кода.

A>>На настоящий момент, я почти отчаялся, решил, что зря я так расдухорился и такие важные вычисления оставил на долю управляемого кода, и морально подготовился к тому, что движок (а это месяца два аккуратного проектирования) придется переносить на C++ (который я люблю использовать для математики, но не для сложных связей объектов). Может у кого-нибудь возникнут мега-гениальные идеи как:


A>>ну и может есть методы, которые мне покажут, в какой момент внутри потока драйвера произошла задержка больше 5 ms.


_FR>Есть: терпение и профилирование.


терпение есть и профилирование тоже есть. профайлер мне показывает, что внутри моего критического вызова происходила сборка мусора 4 раза, все вместе по времени 30 ms, значит в 5 ms я и не уложился.

Всё-таки у меня вопрос: будет ли сборщик мусора останавливать все потоки приложения, или только те, что используют управляемый код?
Re[3]: .Net обработка данных за 5 ms железно
От: Pavel Dvorkin Россия  
Дата: 08.01.11 14:02
Оценка:
Здравствуйте, arkhivania, Вы писали:


A>Всё-таки у меня вопрос: будет ли сборщик мусора останавливать все потоки приложения, или только те, что используют управляемый код?


Здесь есть лучше меня знающие этот вопрос, им и слово. Если бы я писал этот сборщик — остановил бы все потоки. Неуправляемому коду до GC дела нет, но вот вызовы из неуправляемого кода в управляемый вроде как возможны.
With best regards
Pavel Dvorkin
Re[3]: .Net обработка данных за 5 ms железно
От: Kerbadun  
Дата: 08.01.11 14:39
Оценка:
Здравствуйте, koandrew, Вы писали:

K>Эта статья безнадёжно устарела. Сейчас одноядерные процессоры поискать надо — почти все имеют 2 ядра или больше...


Я не про ядра, я про то, как работает планировщик потоков под виндой, и какая на самом деле латентность.

Когда он умрет, его мозг заспиртуют в стакане
Re[3]: .Net обработка данных за 5 ms железно
От: BulatZiganshin  
Дата: 09.01.11 18:54
Оценка:
Здравствуйте, arkhivania, Вы писали:

A>В общем-то всё верно, но тут такая в общем-то смешная задача, что есть причины по которой это должен быть один процесс.


вот и спросите здесь как решить эту проблему. а попытки подстроиться под недокументированные тонкости работы рантайма — неблагодарное занятие
Люди, я люблю вас! Будьте бдительны!!!
Re: .Net обработка данных за 5 ms железно
От: arkhivania  
Дата: 10.01.11 14:10
Оценка:
Здравствуйте, arkhivania, Вы писали:

Ура. GC не тормозит системные потоки, тормозит только управляемые потоки.

http://stackoverflow.com/questions/1870381/net-garbage-collection-and-native-threads
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.