Я специально, хоть и под спойлером, объяснил, что без GIST гарантировать отсутствие пересечения диапазонов было бы проблематично. Возможно, для каких-то задач и допустимо ограничивать конкурентный доступ к БД блокировками, рискуя получить deadlock, но уж точно не для всех.
Не имею ничего против NoSQL баз данных. Сам использую CH, Redis (ValKey), Cassandra.
Давай сравню наглядно твой подход с PostgreSQL (на основе твоих тестов) и альтернативный
Если сравнивать, то для этого нужно сначала реализовать то, что с чего начиналась статья и задача. А именно, обеспечить гарантированное отсутствие пересечений диапазонов при конкурентной модификации данных разными процессами с соблюдением принципов ACID. Без этого говорить о производительности выборки, по меньшей мере, преждевременно.
Как раз размер кольцевого буфера DMA задаётся и за его пределы он не выйдет. Но на этом его ответственность заканчивается. Как на МК, так и на десктопах и серверах.
Вся ответственность за пропущенные данные лежит на программисте. Можете потерять данные - значит учитывайте это в протоколе, чтобы можно было их запросить заново.
Даже обычные роутеры или коммутаторы могут терять данные при большой загрузке. Но ни к чему катастрофическому это не приводит. Просто упираемся в пропускную способность.
Мне интересно, как вы будете гарантировать, что DMA не перезапишет еще не прочитанные данные, в тот самый момент, когда вы с ними работаете
Гарантировать - никак. Предотвратить опасные последствия - правильным использованием watchdog и учитывая в коде, что мой поток может не успевать за DMA и у меня будут пропуски сэмплов.
Впрочем, необходимость увеличения кольцевого буфера DMA или производительности потока чтения, обычно, выявляется ещё при отладке и стресс-тестах.
Выше мы обсуждали 3-битный интерфейс, и мой ответ был про него.
А я вообще не вижу Вашего ответа про чипы на ядре Cortex-M со встроенным WiFi и BLE. Так что давайте двигаться последовательно )
взять другой МК [...] в дополнение к ESP32
Только если Вы компенсируете возросшую в три раза себестоимость готового изделия из собственного кармана.
Или Вы только чужими деньгами так вольно распоряжаться готовы?
Смотря с чем сравнивать. В одной и той же ценовой категории я заметной разницы не вижу. Вы бы более конкретно высказывались.
Понятно, что если бы Espressif внедрили PIO, как в RP2040, то это вообще радикально решает подобные проблемы. Вот только код на ассемблере PIO с Вашей точки зрения уже "небезопасен".
Тогда объясните, как это сделать без копирования и безопасно.
Не надеяться на компилятор, а воспользоваться собственной головой. В общем случае, при работе с bare metall компилятор не помощник для получения безопасного кода.
Взять любой чип на ядре Cortex-M3 или M4
Много ли Вы знаете чипов на ядре Cortex-M со встроенным WiFi и BLE? Это даже не считая того, что если на GPIO нужен параллельный 8-битный интерфейс на восьми из 32 пинов порта, то bit-banding тут уже ничем не поможет.
жестко завязан на Espressif
Я уже указал выше, что это самый доступный МК с WiFi и BLE. Это даже не считая технологий ESP-MESH и ESP-MESH-LITE, аналогов которых я пока на других МК не встречал.
жесткие требования к GPIO
Тоже приводил пример выше с управлением более, чем одной матрицей WS2812.
Даже без DMA, если кольцевой буфер используется для передачи данных между потоком основной программы и обработчиком прерываний, то и тогда передавать владение будет проблематично без запрета прерывания, что может быть неприемлемо.
Не я хочу без копирования, а жесткие ограничения на доступную память и производительность при разработке для встроенных систем требуют избегать копирования.
можно выбрать МК с большим количеством ножек
При чем тут количество "ножек", если речь идет о портах? Мне даже интересно стало, что же Вы предложите вместо ESP32-C2/C3/H2/C6, у которых всего один порт? Вообще отказаться от них, если нужно управлять более, чем одним пином GPIO? А если нужно управлять тремя пинами GPIO, то вообще отказаться от продукции Espressif, так как я не знаю у них ни одного МК, имеющего более двух портов?
Очень странное заявление от разработчика встраиваемых систем. Менять - это не обязательно один раз изменить состояние пина, но, в том числе, и сформировать последовательность сигналов с заданными временными характеристиками и, возможно, достаточно существенной длительностью.
Очень странное утверждение. Например, если у Вас на двух пинах двумя потоками выполняется управление двумя матрицами обычных WS2812, то ±150ns, которые требует их протокол, синхронизируясь между потоками сможете обеспечить только на очень производительных МК. Или же будете полностью блокировать второй поток, пока не выведете всю последовательность сигналов, что будет заметно даже визуально.
В общем случае, когда для обработки различных внешних событий требуются разные потоки. Например, в случае, если менять значения этих пинов нужно по HTTP (TCP, UDP и т.п.) запросу от клиентов. Теоретически, для примера, можно перейти на bare metall умудрившись написать свой функционал, включая LwIP, в однопоточном исполнении. Но по универсальности такое решение будет существенно уступать многопоточному. Тем более, если речь идет о МК с несколькими ядрами, как тот же ESP32-S3.
Естественно речь именно о тех случаях, когда вынужденно нарушаются инварианты для достижения необходимой производительности, путем исключения операций, который алгоритм не требует.
Я как раз наоборот, утверждаю, что несмотря на то, что в unsafe коде нет ошибки, из-за его использования можно допустить ошибку в совершенно другом месте. И даже привел пример с MaybeUnint. Не выполнение инициализации буфера, предназначенного для чтения откуда-то - еще не ошибка. А вот чтение из этого буфера до того, как туда была произведена запись - уже ошибка.
Что приведет к катастрофической деградации производительности. Представьте себе, что на MK мы следим за сигналом с ADC на 100К SPS по DMA. Ваш код на подавляющем большинстве МК просто не успеет обрабатывать такой поток, если на каждый sample будет запрашивать доступ.
Так не экспортируйте в safe блок памяти, пока туда что-то не записано.
Вы предлагаете останавливать DMA после каждой транзакции и инициализировать его заново? А зачем он тогда вообще нужен?
могу содержимое памяти по указателю передать в safe код, который не должен заботиться, правильно ли всё сделано
Можете. Но потеряв в производительно на лишнее копирование память-память, что для MK на батарейном питании может привести вообще к невозможности решения поставленной задачи.
Я специально, хоть и под спойлером, объяснил, что без GIST гарантировать отсутствие пересечения диапазонов было бы проблематично. Возможно, для каких-то задач и допустимо ограничивать конкурентный доступ к БД блокировками, рискуя получить deadlock, но уж точно не для всех.
Не имею ничего против NoSQL баз данных. Сам использую CH, Redis (ValKey), Cassandra.
Если сравнивать, то для этого нужно сначала реализовать то, что с чего начиналась статья и задача. А именно, обеспечить гарантированное отсутствие пересечений диапазонов при конкурентной модификации данных разными процессами с соблюдением принципов ACID. Без этого говорить о производительности выборки, по меньшей мере, преждевременно.
Как раз размер кольцевого буфера DMA задаётся и за его пределы он не выйдет. Но на этом его ответственность заканчивается. Как на МК, так и на десктопах и серверах.
Вся ответственность за пропущенные данные лежит на программисте. Можете потерять данные - значит учитывайте это в протоколе, чтобы можно было их запросить заново.
Даже обычные роутеры или коммутаторы могут терять данные при большой загрузке. Но ни к чему катастрофическому это не приводит. Просто упираемся в пропускную способность.
Интересно, а как Вы сами работаете с DMA?
Очень интересно увидеть такой код. Но напоминаю, без запрета прерываний!
Про то, что в самом обработчике прерываний ни о каких ожиданиях даже речи быть не может, надеюсь, указывать не надо?
Гарантировать - никак. Предотвратить опасные последствия - правильным использованием watchdog и учитывая в коде, что мой поток может не успевать за DMA и у меня будут пропуски сэмплов.
Впрочем, необходимость увеличения кольцевого буфера DMA или производительности потока чтения, обычно, выявляется ещё при отладке и стресс-тестах.
А я вообще не вижу Вашего ответа про чипы на ядре Cortex-M со встроенным WiFi и BLE. Так что давайте двигаться последовательно )
Только если Вы компенсируете возросшую в три раза себестоимость готового изделия из собственного кармана.
Или Вы только чужими деньгами так вольно распоряжаться готовы?
На таймере оно и есть, под управлением FreeRTOS. Но дополнительные задержки в синхронизации между потоками тут явно не позволят уложиться в +-150ns. А DMA тут вообще не при чём: There is no connection at all between the GPIO module and the DMA subsystem
Смотря с чем сравнивать. В одной и той же ценовой категории я заметной разницы не вижу. Вы бы более конкретно высказывались.
Понятно, что если бы Espressif внедрили PIO, как в RP2040, то это вообще радикально решает подобные проблемы. Вот только код на ассемблере PIO с Вашей точки зрения уже "небезопасен".
Не надеяться на компилятор, а воспользоваться собственной головой. В общем случае, при работе с bare metall компилятор не помощник для получения безопасного кода.
Много ли Вы знаете чипов на ядре Cortex-M со встроенным WiFi и BLE? Это даже не считая того, что если на GPIO нужен параллельный 8-битный интерфейс на восьми из 32 пинов порта, то bit-banding тут уже ничем не поможет.
Я уже указал выше, что это самый доступный МК с WiFi и BLE. Это даже не считая технологий ESP-MESH и ESP-MESH-LITE, аналогов которых я пока на других МК не встречал.
Тоже приводил пример выше с управлением более, чем одной матрицей WS2812.
Даже без DMA, если кольцевой буфер используется для передачи данных между потоком основной программы и обработчиком прерываний, то и тогда передавать владение будет проблематично без запрета прерывания, что может быть неприемлемо.
Вот только как Вы собрались передавать владение контроллеру DMA и обучить его отдавать владение коду на CPU?
Не я хочу без копирования, а жесткие ограничения на доступную память и производительность при разработке для встроенных систем требуют избегать копирования.
При чем тут количество "ножек", если речь идет о портах? Мне даже интересно стало, что же Вы предложите вместо ESP32-C2/C3/H2/C6, у которых всего один порт? Вообще отказаться от них, если нужно управлять более, чем одним пином GPIO? А если нужно управлять тремя пинами GPIO, то вообще отказаться от продукции Espressif, так как я не знаю у них ни одного МК, имеющего более двух портов?
Очень странное заявление от разработчика встраиваемых систем. Менять - это не обязательно один раз изменить состояние пина, но, в том числе, и сформировать последовательность сигналов с заданными временными характеристиками и, возможно, достаточно существенной длительностью.
Очень странное утверждение. Например, если у Вас на двух пинах двумя потоками выполняется управление двумя матрицами обычных WS2812, то ±150ns, которые требует их протокол, синхронизируясь между потоками сможете обеспечить только на очень производительных МК. Или же будете полностью блокировать второй поток, пока не выведете всю последовательность сигналов, что будет заметно даже визуально.
В общем случае, когда для обработки различных внешних событий требуются разные потоки. Например, в случае, если менять значения этих пинов нужно по HTTP (TCP, UDP и т.п.) запросу от клиентов. Теоретически, для примера, можно перейти на bare metall умудрившись написать свой функционал, включая LwIP, в однопоточном исполнении. Но по универсальности такое решение будет существенно уступать многопоточному. Тем более, если речь идет о МК с несколькими ядрами, как тот же ESP32-S3.
Естественно речь именно о тех случаях, когда вынужденно нарушаются инварианты для достижения необходимой производительности, путем исключения операций, который алгоритм не требует.
Я как раз наоборот, утверждаю, что несмотря на то, что в unsafe коде нет ошибки, из-за его использования можно допустить ошибку в совершенно другом месте. И даже привел пример с MaybeUnint. Не выполнение инициализации буфера, предназначенного для чтения откуда-то - еще не ошибка. А вот чтение из этого буфера до того, как туда была произведена запись - уже ошибка.
Я и указываю, что это написать "безопасно" не получится. Особенно, если это существенный поток, например, на уровне 100К SPS с ADC.
Чаще всего это невозможно. Даже на 8-битных МК, не говоря уже о 32-битных.
Если бы всё можно было делать "безопасно", то и usafe в Rust был бы не нужен )
Другой вопрос, что безопасную работу с памятью потенциально можно обеспечить с аппаратной поддержкой. Например, частично это уже обеспечивается SSM.
У меня Zyxel LTE7240-M403 позволяет регистрировать на нем ESP32-C3 с антенной на печатной плате на расстоянии свыше 500 метров.
Направленный в противоположном направлении Tenda O1V1.0 не сильно ему уступает, добивая на 300 метров. Но у него и столб ниже.
Так что всё очень сильно зависит от роутера, его исполнения и высоты размещения на столбе.
Иными словами, предлагаете вообще отказаться от написания критического к времянке кода на Rust? Агитируете за C/С++? )))
Как это нет, если этот объект затем передается, например, в функцию чтения в этот буфер?
Что приведет к катастрофической деградации производительности. Представьте себе, что на MK мы следим за сигналом с ADC на 100К SPS по DMA. Ваш код на подавляющем большинстве МК просто не успеет обрабатывать такой поток, если на каждый sample будет запрашивать доступ.
Вы предлагаете останавливать DMA после каждой транзакции и инициализировать его заново? А зачем он тогда вообще нужен?
Можете. Но потеряв в производительно на лишнее копирование память-память, что для MK на батарейном питании может привести вообще к невозможности решения поставленной задачи.