Telegram Web Link
На эту тему вспомнил лайфхак. Американцы часто скажут "I can do it и I can't do it" совершенно одинаково.

Как отличить? В положительном предложении ударение будет на основной глагол (do) а в отрицательном - на модальный (can't).

Британцы скажут четко "кЕн" и кАн(т)", с британцами жить проще.
👍19🔥1
Очень много человекочасов потратил на прикручивание к Rust буквально двух SNMP-функций - для взять SNMP OID по имени из MIB и для обратно.

Под Rust существует как минимум 5 популярных крейтов для работы с SNMP, но ни один MIB'ы не умеет. Оно и понятно - SNMP страшное, а MIB'ы еще страшнее. Технологии из раньшего времени. Поэтому пришлось опять идти к страшной сишной net-snmp, но идти мало - нужно же чтобы оно еще собиралось на всех таргетах, причем статиком и даже работало.

Тот, кто напишет Rust-native процессор для SNMP MIBs, будет очень уважаемым человеком. Но шансы на такое чудо исчезающе малы.
👍9
перфокарты. на 5 мегабайт
👍10🔥3
В Праге, как и в любом другом приличном городе, существует культура стартапов. А где культура - там и конкурсы стартапов, на которых кормят и поят участников. Давно появилась даже особая категория этих участников - которые кодят только для вида, чтобы ходить по конкурсам стартапов и там питаться.

Но, похоже, индустрия впадает в кризис. Вчера на одном конкурсе стартапов, вместо крафтового катеринга нам подали KFC. Фи.
😁10👍6💩3
Под Rust мало биндингов для 1-Wire, в основном всё касается совсем embedded HALs (без OS) или что-то совсем обрезанное, через w1-модуль ядра.

Поэтому сделал SDK под свою любимую OWFS, с биндингом на libowcapi и некоторой небольшой обвеской. Если кому надо - тут https://crates.io/crates/owfs

owfs - это пример, как нужно на сях писать сложные библы, в отличие от netsnmp работать всегда приятно. Причем, всегда совершенно поражался как она лихо жрет всякие пропиетарные w1-шины через i2c. Ну и отдельное спасибо за полный unix-way.
👍6
Хороший JS-продажник у нашей Alza. Если на сайте выделить название товара, то вылазит форма: "вы наверное хотите поискать цену получше. Если найдёте - напишите сюда, мы вам сделаем ещё дешевле"

Очень грамотно. При минимальных технических затратах.
👍21😁4
Ищем хороший сервер для сборок, есть интересные нюансы.

Обычные серверные процы рассчитаны на более-менее равномерную нагрузку и не предназначены для турбо-режимов. А эти ваши CI/CD работают немножко по-другому - довольно большую часть времени простаивают, а когда появляется билд - должны собрать его максимально быстро. Тоесть скажем для компиляции Раста, какойнить AMD Epyc 7F52 влегкую сдает 10-15% тому же Ryzen 5950x, потому что турба у первого 3.9 Ghz, а у второго - почти 5. И это при цене первого в несколько раз выше, не говоря уже о потреблении. Аналогичная ситуация и у интелей.

Тоесть по логике лучший сервер для сборок - это десктопный проц в серверной обвязке, с BMC и прочим, но вот беда - десктопные процы не тянут ECC, а собирать что-то mission critical без ECC - ну шансов на косяк мало, но я бы не играл в рулетку.

Но внезапно производитель пошел навстречу пользователю, потому что куда денутся - конкуренция. AMD тянет ECC уже начиная с Zen3. И тут внезапно пару месяцев назад Intel объявляют, что Alder Lake - тоже с ECC (правда только на чипсете W680), потому что раз у конкурента есть - то и они не против.

Так что чувствую уже совсем скоро наш Jenkins уедет со старого Xeon'а на новый Ryzen. Или на "обычный" интель 12й генерации. Другой вопрос, что из (полу)приличных людей для AMD AM4 серверные платы делает только ASROCK, а вот у интелей ассортимент куда лучше.
👍9🔥4
И раз уж про серверное железо заговорили - никогда не берите сервера с 10GbE+. Ни SoC, ни в материнках, просто никогда и ни при каких условиях. Я уже задолбался считать сколько их видел DoA и сколько сдохло в процессе. А если берете - будьте готовы, что это такая же крутая "фича", как встроенная саундкарта.

Купите ящик 10-гбиток и втыкайте по мере их смерти. Всё, что больше гигабита - расходник. В былые времена на всё подобное ставили не только отдельные карты, а еще и съемные трансиверы, а теперь совсем разленились.
👍6🔥2
Мой первый SSD. Ему 15 лет. Писал отвратительно, мегабайт 30 в секунду. Зато читал просто супер - целых 150.

Пришлось везти такой мощный агрегат из Америки. Стоил штуку баксов.
👍12
Казалось бы, обратная совместимость - правило хорошего тона и большой бонус клиентам. Но на самом деле нихрена - на легаси уходит куча сил, легаси тормозит развитие архитектур, легаси - вообще зло. Но иногда надо.

Когда же надо тянуть легаси? Да очень просто - при выходе новой версии, ваш продукт начинает конкурировать сам с собой. И отсуствие совместимости - всегда минус для апгрейда/миграции. Самая, пожалуй, хрестоматийная история - широко известный в узких кругах MetaTrader. Вот уже 12 лет "метак" v5 конкурирует с v4, поскольку пятая версия - практически несовместимая, а под четверку написаны кучи конфигураций и роботов.

"Король легаси" Microsoft, на самом деле срал и будет продолжать при случае срать на разработчиков и пользователей. Главное ведь побольше кричать, что у нас обратная совместимость, а то что ее нету - это потому что вы дураки:

- мы в Windows поддерживаем практически всё DosAPI (ту самую Int 21h)!
- но кто же под Dos писал только с Int 21h? Вы же сами давали рекомендации по видеопамяти, по ASCII-таблицам, по прерываниям... и, это, где TSR'ы?
- не помним! не было такого. это вы дураки и лохи

Но лохи не хотели сидеть на Dos, потому что под Windows были иконки.

- мы в Windows 95 поддерживаем весь WinAPI!
- но вы же убили нахер совместимость по драйверам...
- потому что у нас совершенно другой HAL! и вообще молчите, вот вам за это DirectX. Рубите бабки с геймеров!

И приходилось выпускать новые драйвера под Windows 95, потому что там был DirectX. И рубить бабки с геймеров, покрывая расходы на миграцию. Потом подобное опять провернули, уже c NT, но никто даже не возражал - привыкли. Зато ОС "нового поколения", не имеющая анало говно.

Даже наш "любимый" Python долго конкурировал 3й со вторым. Примерно так до 3.5 на тройку плевать все хотели. Но комьюнити поставило девелоперов перед фактом - двойка будет EOL. А еще в тройке есть async/await, а у вас нет. А ну быстро переделали код! И ведь взяли и переделали.

Поставь юзеров перед фактом и они переделают. Куда им деваться. Но дай им конфетку. Но хорошую конфетку. А то будет как с "метаком".
👍16💩2
Бежишь, спешишь, срочно открываешь приложение на телефоне, чтобы что-то быстро сделать

- оцените наше приложение
- не сейчас
- почему? что вам не нравится?
- да идите вы нахер!
- когда вам напомнить нас оценить?

Уважаемые мобильные девелоперы. Вас ведь когда-то могут вычислить по айпи.
👍34🔥13😁4
По Rust появилась украинская группа и уже довольно активная. Кто владеет или хотя бы понимает украинский - велком

https://www.tg-me.com/rustlang_ua

К слову, мои орлы на западной Украине, которым младше 25, реально уже по русски не говорят. Так что это не только всякий разный патриотизм, но уже и техническая необходимость.

Такие дела.
👍25👎10🔥3😁3
Есть такая типичная проблема организации RPC-over-messaging: если вам важен ордеринг поступающих сообщений, они должны разгребаться в одном blocking-обработчике, не имея возможности запустить хендлеры в фоновом режиме (это про события, RPC в фоне обычно пускать можно - оно ни на что как правило не влияет, с другой стороны есть конкретный caller который ждет конкретный ответ).

Беда начинается, когда мы вызываем обработчик событий, который хочет по тому же RPC отправить вызов другому клиенту, что нужно ему для обработки текущего события. Но ответ ему никогда не придет, а RPC-обработчик зависнет. Почему? Объясняю, кто сразу не понял:

- RPC-слой получает фрейм, который является событием, вызывает обработчик событий и ждет, пока тот отработает, чтобы соблюсти ordering
- Обработчик событий вызывает RPC метод и зависает навечно (или до таймаута, но ответ он никогда не получит)
- Потому что как же ему получить ответ, если RPC-слой ждет его самого? А никак

Как решается эта проблема на практике:

- Не использовать RPC-вызовы в обработчиках событий. Проще всего, но ведь иногда нужно

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

- Сделать каналы с приоритетами. Пусть RPC-ответы имеют наивысший приоритет, а события - низший. Работает, пока канал не будет весь забит событиями. Придется делать еще и "резерв" для фреймов разного приоритета - так более-менее работает. Но медленно. Очень усложняется логика канала.

- Зарегистрировать нового клиента у брокера и получить от него новую трубу, по которой гонять RPC из таких обработчиков. Вот это единственное, что реально работает всегда и не влияет на скорость.

Для решения этой проблемы я выбрал последний вариант, как самый простой и в ELBUS, начиная с 0.2.5, появились "secondary clients", которые предназначены специально для этого (и еще для некоторых других задач). Почему не просто регистрация нового клиента? Потому что так удобнее:

- secondary-клиенты регистрируются под именем NAME%%SFX, где NAME - имя основного клиента, а SFX - уникальный суффикс
- при регистрации, основной клиент NAME должен быть зарегистрирован на брокере
- при регистрации/дерегистрации secondary, брокер не рассылает анонсы по внутренним служебным топикам
- как только основной клиент отключается от брокера, последний принудительно отключает все secondaries
- при регистрации secondary, если используется security-модель - он получает те же права, что у primary, не нужно вписывать в модель все алиасы и имена
- поскольку формат secondaries стандартен, другие участники, при необходимости, всегда могут идентифицировать, за кого работает secondary sender, который прислал им вызов

Тут подробнее https://elbus.readthedocs.io/en/latest/rpc_blocking.html

p.s. для Rust-биндингов теперь имеется новый метод client.register_secondary(), который сделает всё за вас.
👍8
По вопросам дебильных оптимизаций. Вот не поленился, сделал пример на Расте с use:

use std::{
atomic::{self, AtomicBool, Ordering},
marker::Unpin,
net::{IpAddr, SocketAddr},
sync::{Arc, RwLock},
time::{Duration, Instant},
};
use tokio::{
io::{AsyncReadExt, AsyncWriteExt, BufReader},
net::{TcpListener, TcpStream, UnixListener, UnixStream},
sync::Mutex,
task::{self, JoinHandle},
time,
};

и т.д. еще на 10 этажей.

- Оптимален ли такой код? Оптимален
- Читаем ли такой код? Не очень, глаза постоянно бегают к parent крейтам и обратно
- удобен ли такой код? Не очень, зависимости быстро не закомментить и не скопировать
- Влияет ли этот код как-то на производительность? Нихера он ни на что не влияет
👍10👎1
Чем больше смотрю на Beckhoff ADS, тем больше не люблю все остальное. Могут же, если захотят. Включая тусовку на гитхабе и крейты для ржавого.

Хотя, чего удивляться, Beckhoff - частная небольшая компания и PLC - их хлеб. А у больших дядей PLC это ящик для управления турбиной, который идёт с ней в комплекте.
👍1
В общем Beckhoff ADS мне нравился, пока я его гонял локально на нормальном железном компутере, а как только клиенты выдали PLC (или как говорят в Beckhoff - "индастиральный компутер") - радость сразу уменьшилась. Особенно когда пришлось бутать винду, чтобы помогать его настроить - до сих пор не могу отойти от шока, хорошо что хватило виртуалки.

Итак, знакомьтесь - TwinCAT ADS, потому что у Ethernet/IP есть фатальный недостаток (ну вы поняли). Шо мы можем.

- Можем присвоить переменной handle и дергать её по нему, вместо того чтобы каждый раз по имени (это я уже где-то видел у Rockwell)

- Можно делать балк-реквесты! Наконец-то! Но не спешите радоваться - не больше 500 переменных за раз. Так что если надо вытянуть какую-то структуру, то не вымахивайся, тяни не полями, а всю и парси сам из байтиков.

- Есть пуш! Но опять не спешите радоваться - это вам не чатик, а PLC. А в PLC если у вас есть push, то у кого-то есть pull - программа не будет ждать, пока кто-то там куда-то запушит данные, она скинет их в память и пойдет дальше. А кто-то будет гонять цикл и пушить их для вас за вас. Спецификация позволяет пуш 1мс, сколько на практике - еще не пробовал, но есть подозрение, шо если я закину пушать 4000-5000 полей из структур, то оно сдохнет. Не рискну такое выставлять на продакшн.

Итого, реальная работа:

- балки можно по 500 за раз
- запросы отвечает примерно со скоростью 200Hz (по 5мс на запрос), плюс разве, что почти любой сложности (без фанатизма)
- будете делать хендлы всем полям структур - будете упираться в те же 5мс, и поэтому стартовать весьма долго (не желательно)
- так что для всего сложного - тяни структуру сам и парсай, как обычно
- есть REAL80 (f80), может кому надо, мне - не дай боже
- отдельное спасибо автору ржавого крейта "ads", храни его Бог, Ктулху и святой Илон Маск собственной персоной

p.s. я когда-то доживу до PLC, который умеет нормальный пуш и отдает данные сразу в Msgpack или на худой конец в CBOR? Или опять всё самому делать? Вот только не надо ща про производительность - при цене промышленных ящиков, в них можно спокойно даром поставить отдельный проц, который будет только и заниматься тем, что жать и разжимать жсоны.
👍6
Как отличить современный embed от винтажного? В современном ARRAY<bool>[1000] занимает 1000 байт.
😁22👍6
Вот у нас хорошо один интегратор работает. Поставили железо, приемники, передатчики. И каждый месяц еще выкатывают инвойсы клиентам

- за что это?
- за подключение к LoraWAN - международной сети интернета-вещей и индастри 4.0!
👍7😁4💩4
- Вы не могли бы объяснить, как в вашем продукте делается high availability?
- Какая high availability блять. Упсы поставьте в серверную и проводку почините. Свет тухнет чаще, чем у меня в 90х на районе
- Ну что вы сразу такой резкий?..
😁27👍3
Реалтаймовые процессы на Linux. Бросьте эти все ваши наколенные RTOS и научитесь настраивать ядро - говорят коллеги. Пробуем.

С точки зрения локальной реалтаймовости, как ни странно, по-большому счету наплевать, используете вы ядро с RT_Preempt или без. Намного лучше реалтайм-процессы получаются, если выделить им конкретные головы процессора.

Для этого загружаете ядро системы с опцией isolcpus, например isolcpus=0,1 будет значить что мы используем первые две головы процессора для реалтайм-процессов, а остальные для всего другого. На эти головы ядро системы не будет сажать ни один поток, пока он либо четко не заявит об этом сам, либо мы не переместим его с помощью taskset, например. Для тестов в целом это не критично - редкие джиттеры и прерывания можно игнорировать, но критично для будущего продакшна.

В качестве теста я использовал простой код на Rust, в котором один поток замеряет CLOCK_MONOTONIC, шлет небольшой UDP-пакет во второй, а после получения ответа замеряет разницу. Второй, соответственно, пакет принимает и отправляет acknowledge.

Реальные результаты. Как ни странно, из всего моего хардварного зоопарка (условия понятно - никакого контроля частот, никакого hyperthreading и т.д.), неплохие результаты у Ryzen 5950x, но самое лучшее latency выдал Cortex A-73 - 24 микросекунды, из чего следует полагать что сигнал доходит за 12 (с non-blocking даже 10/5), с jitter примерно в пару микросекунд. Кроме того, у ARM имеется интересная особенность - если оба потока работают на одном ядре, показатели те же, как если они работают на разных. На Intel и AMD, при использовании разных ядер, latency сразу же возрастает. Верю, что на Cortex-R результаты будут еще круче, но таких систем под рукой нет.

Следущий шаг - соединить процессы уже на двух ящиках и добиться минимальной latency сигнала через шину. Заказал две платы с A-73, буду играться как приедут. Попробуем пока не городить всякие-разные I2C, а помучать TCP/IP. В крайнем случае еще есть EtherCAT, но это не наши методы. Верю, что спустя 20 лет можно изобрести что-то еще более крутое.
👍12🔥5
2025/10/01 11:08:33
Back to Top
HTML Embed Code: