Обновить
8K+
11

Пользователь

32,2
Рейтинг
1
Подписчики
Отправить сообщение

Спасибо за краткий пересказ моего комментария для тех, кому было лень читать текст и смотреть код. Всё так :)

Mmap был бы неплох, если бы не один факт: мы заранее не знаем размер файла, т.к пишем лайв поток. При использовании mmap пришлось бы постоянно юзать ftruncate и ремаппить память пропорционально росту файла. В го это был бы дикий оверхед на page faults.
mmap - очень крутая штука для бд(когда используется random acces), у нас же идет строгая последовательная запись(append-only). Стнадрный write в Линуксе работает почти идеально, поэтому связка os.File и FADV_DONTNEED, тупо проще безопаснее и не жрет процессорное время.

Как я уже отвечал на другой комментарий, если бы Sync дергался в гланом цикле стриминга - то да вы бы были правы. Но именно поэтому сам рекордер, это отдельная асинхронная горутина. Ядро раздает всем всем воркерам кадры через неблокирующие каналы. Если диск тупит и Sync повиснет, ядро этого просто не замечает. Канал рекордера забивается = дропаем кадры только для него. Все остальные подписчики работают без задержек.

Ну про vm.dirty замечание оличное, но есть два нюанаса:

  1. Sync не делается на каждый кадр, сброс идет только после закрытия целого чанка fMP4, а это раз в несколько секунд. Диск от такого редкого синка даже не почешется, и в I/O не упрется

  2. А вот касательно vm.dirty, это глобальная настройка всего железного сервера, и ставить ее больше зло чем добро, тк в таком случае поведение кеша изменится для всех и вся(может отвалится та же встроенная БД которой такой кеш жизненно нужен). Флаг же позволяет действовать более тонко, мы трогаем только кэш для наших видеофайлов, а у остальных процессов все по стандарту.

Приветствую! Баг 12309 вы вспомнили очень даже кстати, суть проблемы там похожа. Но вы путаете простую десктопную нагрузку(скопировать файлы, торренты), с хайлоадом который пашет 24/7. При copy ядро линукса действительно само выбросит чистык страницы кеша, когда память кончается. Но разница в том, что 100 камер генерят огромный(по сути бесконечный) пооток грязных страниц, я граязные страницы ядро не может отбросить, пока не сбросит на физический блин диска. Если же диски не поспевают, эти грязные страницы копятся до конечной. И когда соседному процессу срочно нужна память - линукс фризит все I/O, либо вытесняет в своп полезную(!) память соседей по процессам, а вот потом он "позовет ООМ киллера".
Флаг FADV_DONTNEED в этой реализацци, это не костыль от падения, в скорее просто гарнатия того что архив не сожрет 90% озу, и системе останется ресурсы для бизнес-логики.

Спасибо за этот "наброс". Да вы правы, но правы лишь в том как поведет себя ОСь. Действительно при физическом отвале носителя или шары системный вызов Write() или Sync() зависит в ожидании I/O таймаута от драйвера. И да горутина пишущая файл, как вы выразились "замрет как мертвец". Но, это пройзодет только с ней, сервер не пострадает и не зависнет . Подсистема записи (Recorder.go) жестко развязана с ядром получения потоков (Ring.go). Сам рекордер является лишь одним из подписчиков ядра(как и муксер или webrtc-клиент). Это равносильно тому что 1000 зрителей смотрят стрим на твиче, у одного вырубили свет, он перестал смотреть стрим. Все. Больше ничего не произойдет, сам стрим на твиче продолжится как не бывало. Более технично в проекте:
Рассыдка кадров из ядра всем поодписчикам реализована через неблокирующие каналы Go(select +default)

// Внутри ядра рассылки (RingBuffer):
select {
case sub.C <- frame:
    // Кадр ушел подписчику
default:
    // Подписчик тормозит или завис на I/O. 
    // Дропаем кадр, инкрементим счетчик потерь.
    atomic.AddUint64(&sub.Drops, 1)
}

Что произойдет если как вы выразились физически удалить устройство:

  1. Горутина рекордера намертво виснет в системном вызове. Она перестает вычитывать кадры из своего(!) канала.

  2. За милисекнуды канал рекордера забивается полностью(в моей реализации, наполнений = 100 кадров)

  3. Ядро (ringBuffer) при попытке отправить следущий кадр, попадает в ветку default, и просто начнет дропать кадры только для рекордера, не блокируя свою работу вообще, даже на милисекунду.

  4. Итог - запись архива ломается, в логах ошибки дропа, но все остальные подписчики (HLS/WebRTC зрители, ИИ-модули, и все остально что еще не прикручено) продолжать получать видеопоток в лайв режиме

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

Надеюсь, я полностью объяснил то как это работает.

Спасибо, звучит интересно

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

Тсс, мы видели не отредактированный комментарий :)

О, спасибо, за вопрос, если честно то изначально так и планировалось(даже в роадмапе до сих пор стоит), но есть нюансы. Эти флаги требуют жесткого выравнивания в памяти по границе стараницы(4 кб). А вот аллокатор го и сборщик, не может гарантировать что []byte слайс будет выровнен как надо. Что бы это завести пришлось бы мучиться с unsafe, аллоцировать куски руками высчитывать оффсеты и писать отдельный буфферизатор который добивал бы неровные кадры нулями до размера сектора. FADV_DONTNEED же дает тот же профит, но позволяет использовать просто os.File. Ось в данном случае просто сама разруливает невыровненые чанки, а флагом просто заставляем выкинуть кэш в конце.

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

Только лишь за эту фразу, человека сразу можно отнести в "разряд" опытных профессионалов. Абсолютно верное утверждение, любой даже самый "сильный" разраб, который пишет идеальный код, или даже академический - суть ничто, если он не понимает для чего он пишет. И уж тем более если он все это пишет "на ходу" без проекта(хотя бы в голове). Именно поэтому, на мой взгляд ИИ больше гораздо большее добро, чем зло. Ведь если взять за условие что программист это Архитектор/Координатор/Руководитель, а ИИ рабочая сила, которая пишет код - то в чем разница между условным Техлидом, который понимает задачу, проектирует решение, а сам код пишет 5 вчерашних студентов?

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

Полностью согласен, чую скоро стандартом станет строго структурированый MD или вообще - JSON/OpenAPI-спецификация...

Если у вас γ зависит от H как γ ~ H⁻⁴, то получается гравитационная постоянная меняется от потенциала. Но тогда орбиты планет, двойные пульсары и вообще куча наблюдений должны это показывать. Сейчас вроде все измерения говорят что G почти константа. Где это в теории согласуется с наблюдениями?

И Еще момент, Вы пишете что нету горизонта событий, но тогда как объясняется наблюдаемая тень чёрной дыры?

Вы правы, до сих пор сожалею об этом :)

Информация

В рейтинге
244-й
Зарегистрирован
Активность

Специализация

DevOps-инженер
От 200 000 ₽