• Rust: «Небезопасные абстракции»
    +6
    Тут сразу стоит сказать что сам по себе `unsafe` не делает ничего особенного и не увеличивает магическим образом производительность на 146% самим фактом своего использования. Он всего лишь позволяет программисту сказать компилятору «я знаю что делаю» и успокоить его анализатор, который в противном случае бы не дал написать потенциально небезопасную конструкцию.

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

    Например, если у вас есть вектор элементов то, как уже было сказано в статье, безопасная реализация обязана проверить, что переданный индекс не выходит за пределы массива. Даже если вы храните этот индекс в объекте и твердо уверены, что он верный, при каждом обращении все равно будет выполняться проверка.

    В этом случае вы можете использовать небезопасный вариант операции «получить значение по индексу», который не выполняет проверку условия. Тогда ответственность будет лежать на вас.

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

    Один из примеров, где такое срезание углов имеет смысл — это реализация итератора по массиву. Доступный размер массива известен заранее, поэтому итератору достаточно хранить у себя текущий индекс. При создании итератора текущий индекс выставляется в 0 и увеличивается на единицу каждый раз, когда пользовательский код зовет `next` и если в массиве есть еще непосещенные элементы. Поскольку этот индекс по определению не может выйти за пределы массива, имеет смысл операцию обращения к элементу делать без проверки индекса (проверка заложена в саму логику итератора), тем самым, повышая производительность, путем убирания лишней проверки, а не всех проверок вообще. Код по-прежнему остается безопасным, просто обеспечение этой безопасности вынесено на другой уровень.

    По этой самой причине Rust рекомендует писать код именно с использованием итераторов и фильтров, так как они оказываются более эффективными, нежели традиционный императивный код с доступом по индексу.

    Конкретные цифры будут слишком малоинформативны, поскольку зависят от сотни факторов, включая конкретное место использования итератора, оценку компилятором весов при инлайнинге, архитектуру процессора и т.д.
  • Rust: «Небезопасные абстракции»
    +4
    Позволю себе добавить, что помимо сегфолтов, Rust позволяет статически (на этапе компиляции) доказать отсутствие в программе гонок по данным так же, как он предотвращает обращение к неинициализированной или уже освобожденной памяти без необходимости GC. Причем без каких-либо накладных расходов, то есть производительность от этого не страдает.
  • Rust vs. C++ на алгоритмических задачах
    +3
    Спасибо на добром слове :)
  • Ой, у меня задержка. Часть 2
    +1
    Да, разумеется.
  • Ой, у меня задержка. Часть 2
    +1
    Короче, PCR вообще нужен только при real-time вещании.
    Поправлю. Он нужен во всех случаях, когда у вас на руках в каждый момент времени есть только фрагмент стрима. Даже в случае HLS/DASH, хотя вроде бы «все должно быть нормально, ибо есть большой запас в несколько сегментов и ~30 секунд». Именно из-за clock drift-а, который упорно не хочет понимать топикстартер, декодоер рано или поздно упрется в одну из границ буфера и привет лаги/дропы. А потом начинают говорить, что стандарт говно. Именно поэтому, стандарт MP2 специфицирует допустимый дрифт PCR не более чем на 500 наносекунд.

    Резюмируя: когда вам весь TS доступен локально на диске, то PCR не нужен. Когда вы получаете его из кабеля (QAM) или скачиваете из сети по частям (стриминг, VOD и особенно realtime) — нужен. Во втором случае надо использовать PCR pacing в демультиплексоре.
  • Ой, у меня задержка. Часть 2
    0
    DASH — типичный пример академического дизайна. Он рассчитан на поток строго из SDI и строго с атомных часов. Т.е. уже банальный стрим с мобильного телефона, пропущенный через RTMP уже не укладывается в прокрустово ложе DASH и MSE.
    Вы сейчас говорите про сам стандарт или про его реализации? То что реализации оставляют желать лучшего, это и так понятно. Особенно опен-сорсные. Именно потому что, как правило, кладут на половину спецификации и «забивают на PCR». В итоге имеем, что имеем.

    Про PCR: многим клиентам вообще наплевать на PCR, они его не читают, потому что в аудио и видео потоках идут DTS. Но конечно для олдовых mpegts-пуристов это ересь требующая очистительного костра

    И это очень печально. Потому что PTS/DTS и PCR это фундаментально разные вещи. То что декодер можно завести только на PTS не означает, что PCR не нужен. Но вы, как специалист, это и так должны понимать.

    А потом возникает ситуация, что «у меня все сутками работало на тестах», а как только код попадает в поле, да еще на миллионы устройств — приехали. Особенно это критично для транскодеров, стоящих, как правило, в аппаратной кабельного оператора и работающих годами.
  • Ой, у меня задержка. Часть 2
    0
    Подробнее, пожалуйста.

    Я то же самое могу сказать и про HLS, особенно, если сценарии использования выходят за пределы «проиграть хоть как-то, в бытовых условиях».

    А если задавать разные неудобные вопросы, вроде синхронизации разных MPEG2-TS стримов через PCR и поведения, не определенного стандартом, то вообще мрак.
  • Ой, у меня задержка. Часть 2
    0
    Спасибо за статью, интересно посмотреть на проблемы коллег с другой стороны. По работе мне приходится сталкиваться с QAM/IP вещанием в сетях кабельного телевидения.

    Скажите, а DASH в вашей сфере насколько хорошо себя чувствует? С учетом того, что в плане полноты стандарта по сравнению с DASH, HLS выглядит как дешевая подтирка, очень странно, что все по-прежнему активно цепляются за HLS.

    И еще момент: существуют ли свои подходы к ABR? Я так понимаю, что для рилтайм стриминга критерии могут существенно отличаться от таковых для обычного вещания и тем более от VOD.
  • Rust vs. C++ на алгоритмических задачах
    +9
    Rust — уникальный проект. И как язык и как экосистема.

    Как язык он уникален тем, что ядро команды составляют великолепные специалисты по теории типов, которые, тем не менее, ориентируются на практичность, а не на академическую чистоту/новизну языка. В итоге получился язык с весьма мощной системой типов, который однако, можно успешно применять в повседневной разработке.

    Философия языка — это сплав современных представлений computer science и хиропрактик системного программирования, повернутых, однако, лицом к программисту-прикладнику.

    Ключевая, на мой взгляд, идея, идущая красной нитью через весь язык, — программист, как и любой другой человек не всесилен и склонен совершать ошибки. Соответственно, язык, который сваливает вину за промахи на программиста — плохой язык.

    Да, тут я говорю и про C++. Программирование на C++ — это сделка с дьяволом. Ты получаешь большие возможности в обмен на свою душу, когда самолет под управлением твоей программы грохнется в океан. C++ пестрит ситуациями, приводящими к неопределенному поведению, о которых программист обязан помнить.

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

    Rust пытается сделать то же самое на уровне системного программирования. Есть фундаментальная разница между утверждениями «корректность системы проверена тестами» и «корректность системы доказана математически». В первом случае, даже после десяти лет эксплуатации, мы все равно не можем быть уверены, что система надежна.

    Ключ к решению — формализация тех отношений в коде, которые в традиционных языках остаются на совести программиста. Например отношения владения памятью и поддержания ссылочной целостности на уровне указателей. Rust физически не допускает ситуаций, могущих привести к неопределенному поведению, нарушению алиасинга, состоянию гонок или обращению к уже освобожденной или еще не выделенной памяти.

    Все вместе позволяет без опаски реализовывать (а главное рефакторить!), сложные многопоточные программы. Здесь очень кстати будет классический уже пост Fearless Concurrency от одного из авторов языка, плюс великолепная серия статей Lin Clark про внутреннее устройство Firefox Quantum, который стал возможен исключительно благодаря возможностям Rust.

    Как экосистема Rust уникален тем, что ядру команды удалось сформировать удивительное сообщество, готовое к диалогу и дружелюбное к новичкам. Буквально каждый момент взаимодействия с этим сообществом вызывает чувство глубокой благодарности. Тем удивительнее это видеть в среде, близкой к системному программированию.
  • Rust vs. C++ на алгоритмических задачах
    +15
    За статью, безусловно, спасибо. Однако, подача материала, а главное, цель статьи меня смущают.

    Мне кажется, что плюсер, прочитавший статью и не знакомый с Rust, в лучшем случае «пожмет плечами» или пробурчит «как на Фортране можно писать на любом языке программирования».

    Сила Rust не только и не столько в итераторах, ссылках и семантике перемещения, сколько в иной философии и подходу к проектированию программ. Но из статьи этого понять не выйдет.

    У меня по крайней мере, сложилось бы впечатление, вроде: «Мда… ну и зачем весь этот бред? Учитесь писать на плюсах, а не выдумывайте очередного его “убийцу”».
  • Разработчики о самых грязных программных трюках в играх
    0
    А зачем было колхозить таймеры, если они и так поддерживались нативно в редакторе? Хоть на экран выводи.
  • Разработчики о самых грязных программных трюках в играх
    +3
    «Матерый хряк попался! Глаз подбил и кортик отобрал»
  • Опрос пользователей Хабра
    +1
    Было бы еще лучше, если бы в tmfeed/RSS сразу указывался бы автор публикации. Я к примеру, обожаю местные статьи по физике, но только определенных авторов.
  • Что каждый программист на C должен знать об Undefined Behavior. Часть 1/3
    +2
    Спасибо за перевод! Эту серию статей давно надо было перевести.
  • Почему LLVM может вызвать никогда не вызываемую функцию?
    +4
    Я не предлагаю отказываться полностью. Я предлагаю лишь не замалчивать потенциальные проблемы.

    Мир контроллеров это особый мир, со своими правилами и проблемами, и к нему уж точно не стоит апеллировать в статье на общую тему.

    Те, кому надо выжать из камня максимум, рано или поздно сами придут к битовым операциям, но уже с полным осознанием последствий.
  • Почему LLVM может вызвать никогда не вызываемую функцию?
    +6
    Я просто не пойму зачем провоцировать людей на подобное трюкачество? Вот такая функция точно так же будет преобразована в одну инструкцию fneg на тех компиляторах, которые это умеют:

    float negate(float num) {
        return num * -1;
    }

    Только, в отличие от примера в статье, данная функция:
    • Абсолютно понятна читающему
    • Ни при каких условиях не провоцирует неопределенное поведение
    • Не работает с указателями — больше простора для оптимизации
    • На кривых компиляторах все равно отработает как надо
  • Почему LLVM может вызвать никогда не вызываемую функцию?
    +6
    Причем здесь проявляется или не проявляется? Вам ли не понимать, к чему может привести UB в коде. Если флаг -strict-aliasing указан то все, приехали.
  • Почему LLVM может вызвать никогда не вызываемую функцию?
    +4
    Спасибо за статью. Вот только написать
    Пусть мы решили написать функцию, которая меняет знак у float, меняя 31-й бит бинарного представления float
    и не сказать о том, что так лучше не делать — может быть чревато.
  • Весь веб на 60+ FPS: как новый рендерер в Firefox избавился от рывков и подтормаживаний
    0
    Вопрос был про загрузку. Этот тест на загрузку. Тест на плавность анимации приведен в статье.
  • Весь веб на 60+ FPS: как новый рендерер в Firefox избавился от рывков и подтормаживаний
    +1
    Нет. Посмотрите видео. Например, вот это:
  • Весь веб на 60+ FPS: как новый рендерер в Firefox избавился от рывков и подтормаживаний
    0
    Edge так же как и Safari — платформозависимые броузеры, которые договорились с ОС. Хром и Лиса вынуждены играть по общим правилам.
  • 160-терабитный трансатлантический кабель Marea закончен
    +1
    Посмотрите на гугловский Loon. Они летают выше погоды.
  • Как может вызваться никогда не вызываемая функция?
    +2
    Нет, вроде бы там было честное условие.
    Не думаю, что можно сделать так, чтобы обе ветви if'а исполнялись — то что исполнится только одна ветвь определяется строением SSA-дерева.
    Не факт. Думаю, что при выполнении loop peeling-а и loop unrolling-а, могут появляться дублирования выражений, которые дальше могут поехать по-разному из-за UB.
  • Как может вызваться никогда не вызываемая функция?
    +4
    Не UB, а если встречал в коде директиву #pragma, поскольку в стандарте на тот момент про это ничего сказано не было.
  • Как может вызваться никогда не вызываемая функция?
    0
    Не, там была именно конструкция вида if (x) { A } else { B } и при этом и А и B выполнялись (в неопределенном порядке).
  • Как может вызваться никогда не вызываемая функция?
    +3
    В моем списке маразмов выше только вызов обеих ветвей условия подряд. К сожалению, за давностью лет потерял артефакт, который приводил к такому поведению.
  • Go быстрее Rust, Mail.Ru Group сделала замеры
    0
    Я так понимаю, что речь о сравнении стандартного инструментария наиболее подходящего для решения поставленной задачи. Иначе можно докатиться до холиваров и сравнения того, что входит, а что не входит в стандартную библиотеку/поставку языка.
  • Go быстрее Rust, Mail.Ru Group сделала замеры
    +2
    str — это безразмерный (unsized) тип, представляющий строковое значение, а &str — ссылка на него. Примерно как void и void* в Си, только без костылей.

    Сишники вполне себе обращаются с void, но почему-то все становится плохо, когда эту идею пытаются развить и строго объяснить с позиции системы типов и идеологии языка.

    Вероятно потому, что с void сишник знакомится в младенчестве и просто принимает на веру, что «надо писать void, когда функция не возвращает значения, а void* это… ну просто указатель, когда не знаем, на что указываем». В итоге человек к этому привыкает и перестает об этом думать.
  • Go быстрее Rust, Mail.Ru Group сделала замеры
    +1
    Выше уже писали, что изначальная задумка была сравнить дефолтные инструменты в той и другой экосистеме, а не one shot велосипеды. В такой постановке вопроса это вполне имеет смысл (при корректном проведении и правильных выводах).
  • Go быстрее Rust, Mail.Ru Group сделала замеры
    +3
    mkpankov на реддите написал ретроспективный анализ своей реализации, где разобрал причины.

  • Удивительно полезный инструмент: lsof
    0
    Вопрос не в странности, а в том, что это устоявшееся выражение, которое используют в книгах. Например в переводе классической книги Стивенса «UNIX: разработка сетевых приложений», или в «Ядре Linux» за авторством Бовет и Чезати.
  • Удивительно полезный инструмент: lsof
    0
    Опция -U позволяет вывести все файлы сокетов домена Unix.
    Омг. Так доменные сокеты еще никто не называл. Неужели так сложно перед публикацией дать вычитать перевод специалисту?
  • Интернет вещей популярно: почему мы перестанем выгуливать собак
    0
    Можно подумать у нас люди убирают… печаль.
  • Попиксельная заливка экрана в Wolfenstein 3D
    +2
    На правах маразма: если забыть об эффективности, то похожий результат можно достичь, обходя квадрат по кривой Гильберта (или Мура), но не подряд, а с некоторым шагом :)
  • «Магическая константа» 0x5f3759df
    +2
    А самое главное, любой читающий код поймет, что тут происходит, даже без пояснений. Главное не подпускать к коду тех, кто вопит про неэффективность и упущенную прибыль возможность оптимизации :)

    Хотя, конечно, по-прежнему остается проблема разных размеров. Кэп подсказывает, что надо добавить ассерт, плюс использовать типы с фиксированным размером, вроде uint32_t.
  • «Магическая константа» 0x5f3759df
    0
    На том же Stackoverflow есть хороший вопрос после которого понятно, что ничего непонятно.

    Очевидно, что верить нужно стандарту, вот только пользуемся мы продуктами интерпретации оного, так что правильного ответа я не знаю.

    Но судя по изменениям, движемся мы в сторону разрешения type punning через union.
  • «Магическая константа» 0x5f3759df
    0
    Я видел. Это были мысли вслух, а не наезд :)
  • «Магическая константа» 0x5f3759df
    0
    Могу посоветовать две статьи: раз и два.
  • «Магическая константа» 0x5f3759df
    +2
    что конкретно не так в коде функции в статье?
    Код в статье нарушает стандарт С++ и провоцирует UB. Дальше можно уже не разбираться, ибо на этом месте заканчиваются все гарантии.

    Типы примитивные, массивов нет, компилятор поместит i и x в регистры или на стеке… и что не так?
    Что именно компилятор будет делать со значениями зависит от сотни-другой параметров, включая оценку весов при инлайнинге и register pressure в данной точке. Сама попытка объяснить, что сделает компилятор из общих соображений и «здравого смысла» уже обречена на провал.

    Ради интереса скомпилировал тест с -O3 и -O0 с включенным и выключенным алиасингом на g++ и clang++ (std=c++14) — результат выполнения одинаков.
    То что он одинаков здесь и сейчас не значит, что он будет одинаков всегда. В этом и засада. Пример того, что может случиться, озвучивается в докладе в районе 28 и 29 слайдов.

    К сожалению, самое страшное, что может сделать программист в непонятной ситуации, — «это проверить на практике и убедиться, что все хорошо».
  • «Магическая константа» 0x5f3759df
    +1
    Идя таким путем, вы вступаете на очень зыбкую почву. Неизвестно еще, что будет хуже.

    Если возникает объективная потребность в небезопасных манипуляциях, их нужно изолировать, вплоть до ручного написания функции на ассемблере.

    Другое дело, что вся эта машинерия может негативно сказаться на производительности и потерять в итоге смысл.

    Современные компиляторы достаточно умные, чтобы использовать весь набор доступных инструкций, включая уже названную rsqrtps. Главное просто не мешать и не считать себя умнее компилятора.