Перейти к содержанию
    

Обработка потока данных - как реализуется концептуально?

Заголовок темы краткий, поясняю смысл вопроса на примере последовательного порта.

Из порта поступают байты, которые надо обработать. Для обработки используются т.н. фильтры - модули, получающие на вход поток байтов и содержащие список следующих фильтров, куда направляют поток данных со своего выхода. Например, есть фильтр, инвертирующий регистр символов и вырезающий из потока символы перевода строки: получил на входе "AbC\n", выдал на выход "aBc". К выходу этого фильтра подключены еще три фильтра, т.е. после того, как фильтр отработал, строку "aBc" он посылает поочередно на эти три фильтра, каждый из которых тоже может послать результат на следующие фильтры, те - на следующие и т.д.

То есть поток входящих байтов так или иначе проходит по дереву фильтров, и в конце получается N "конечных" точек, где данные уже реально используются (например, выводятся в консоль).

Логически все просто, но есть вопрос быстродействия: если каждый байт будет бродить по дереву, то для обработки следующего байта из порта придется ждать, пока все эти вложенные циклы передачи с выхода на вход (обход ветвей дерева) не закончится. С учетом того, что на самом деле поток обрабатывается не побайтово, а условными строками, т.е. блоками данных 1...X байт (где X в 64-битных системах практически не ограничено, пусть будет 0xFFFF), проблема имеет место быть. К тому же обработка данных внутри фильтра может быть не тривиальной, т.е. длительной.

Напрашивается такой вариант: фильтр, получив данные, копирует их себе в буфер, после чего "возвращает управление" предыдущему фильтру, а обработку и "рассылку данных" далее по своим подветкам дерева делает уже в своём потоке, не мешая работе других фильтров. Но тут тоже предвижу проблему: это ж сколько памяти надо будет под все эти потоки и промежуточные буферы? Как это все синхронизировать потом, при выводе в "конечных точках"?!

В общем, то ли я сам себе нагоняю мороза в труселя, то ли и вправду проблема есть, и её надо решать. Как вообще концептуально это следует делать? Пока думаю только в приложении к Windows, но теоретически есть задумка и на счет кроссплатформенности...

Да, пока мне приходит в голову максимум 2 параллельных ветки из цепочки последовательных фильтров для практического применения, но, разумеется, предсказать реально, какие потребности могут возникнуть со временем, я не могу, и поэтому обдумываю именно универсальное решение с наихудшим сценарием сильноразветвленного дерева.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Оставить всё как есть и просто добавить FIFO буфер по входу (между портом и фильтрами).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

FIFO уже на уровне драйвера порта сделано: оттуда уже приходит от 1 до 0xFFFF байтов.

9 минут назад, arhiv6 сказал:

Оставить всё как есть

Считаете, проблема "медленной обработки" за счет постоянного копирования туда-сюда данных, надумана?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сколько времени занимает

1. прием Х байтов ?

2. обработка Х байтов ?

Как только узнаете эти два числа, тогда и будете думать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, ARV сказал:

В общем, то ли я сам себе нагоняю мороза в труселя, то ли и вправду проблема есть

Со сферическими конями в вакууме всегда так.  :unknw:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, ARV said:

К выходу этого фильтра подключены еще три фильтра,

Неправильные слова приводят к неправильным мыслям. 
Надо отказаться от применения слова фильтр и поток.
Правильне было бы применять слова парсер, лексер и грамматика

 И не некий поток должен пихать данные в обработчик, а обработчик должен брать необходимые данные. 
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, x893 сказал:

Сколько времени занимает

1. прием Х байтов ?

2. обработка Х байтов ?

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

Только что, AlexandrY сказал:

Неправильные слова приводят к неправильным мыслям

Я описал проблему так, как я сам её понимаю. Я оперирую функциями: функция получила на входе данные (из порта), что-то сделала с ними и вызывает аналогичную функцию следующего "фильтра", передавая ей данные. Получается, именно следующему пихаются данные, а не следующий тянет их. Т.е. у меня поток данных течет по обработчикам, а не обработчики, высасывающие откуда-то данные. Возможно я не прав, но я не профессионал, и мне простительно :blush:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

46 minutes ago, ARV said:

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

Тогда нужно сделать последнее напряжение и решить, что будет с данными, если обработка ещё не закончилась, а новые данные уже готовы.
Два варианта есть
1. бросить обрабатывать старые и заняться новыми
2. бросить новые и до конца обработать старые.
 

А кто будет пихать или всасывать - не важно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

34 minutes ago, x893 said:

А кто будет пихать или всасывать - не важно.

Как это не важно, это принципиальное различие!
Пихать - это одна точка передачи данных.
Всасывать - много точек передачи данных. 
Улавливаете? 
Эт принципиально разные архитектурные решения.  :biggrin:
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 minutes ago, AlexandrY said:

Как это не важно, это принципиальное различие!
Пихать - это одна точка передачи данных.
Всасывать - много точек передачи данных. 
Улавливаете? 
Эт принципиально разные архитектурные решения.  :biggrin:
 

Пофиг как называть - всос/высос (I/O).
Пусть на на вопрос ответит сначала.
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, x893 сказал:

Два варианта есть

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, x893 said:

Пофиг как называть - всос/высос (I/O).
Пусть на на вопрос ответит сначала.
 

Мне видится архитектура как набор асинхронных тредов. Обмен между тредами делается обычно через очереди. 
И в каждой очереди выбор между потерей старых данных или потерей новых данных задается простым флагом.
Так что вопрос о том что теряется как раз вторичный. 
По идее более высокоуровневый тред решает как обходится с данными. Т.е. решение делается динамически.
То есть pull лучше push-а.  
 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пока нет уонкретного ответа, всё это рассуждения о сферическом коне в ваккуме.

Хоть 122 потока создавать, хоть 0.

 

3 hours ago, ARV said:

Я стремлюсь сделать

Зачем создавать тему, если нет ответов, а хрустальные шары на складе закончились.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 часа назад, x893 сказал:

Зачем создавать тему

Затем, что современные виндовсы совсем не те, что были раньше. Раньше подобный вопрос и не возникал бы вообще. А сейчас... Вот недавно я выяснил, что современные версии винды (семерка и новее) для DLL выделяют свою память данных (раньше данные выделялись в сегменте данных главного приложения), поэтому просто так взять, и передать указатель на данные DLL нельзя, надо с бубном плясать...

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Достаточно выбросить на помойку прошивку для игровых приставок и перейти на нормальную операционную систему.

Где есть нормальные IPC и т.д., и т.п.!

Да, задачу тоже надо пересмотреть: она явно может быть оптимизирована!

Изменено пользователем Eddy_Em

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...