All streams
Search
Write a publication
Pull to refresh
5
0
Владислав @ihost

Программист

Send message

В каком-нибудь таком случае вполне себе изменит https://godbolt.org/z/brn7brjoE , плюс все __sync_* функции все равно форсированно приводят указатель к volatile, благодаря чему оно верно и компилируется. Условный TBB от Intel тоже вполне себе использует volatile в многопоточном коде Search · volatile (github.com)

В общем, не вижу смысла в дальнейшей дискуссии. Исходный тезис был "multithreading и многопоточность несовместимы", а это не верно. Показать примеры из промышленного кода я не могу по NDA, а сидеть выдумывать аналогичные простые примеры - не вижу смысла

Чтобы подвести bottom line - смысл volatile (не технически, а скорее философски) примерно такой же, как у std::launder - надавать компилятору по рукам, где в высокооптимизированном (и скорее всего массивно-многопоточном) highload-коде проведены ручные микрооптимизации под целевую платформу, и надо отвадить компилятор от неверной кодогенерации :)

Все-таки volatile + __sync_* intrinsics дают большие возможности контроля Compiler Explorer (godbolt.org)

Atomic конечно соберется с любым процессором, но может оказаться, что там всадили lock - в каких-то случаях это плюс, но в каких-то лучше пусть не скомпилируется, зато это повод явно разработать lockless-версию для целевой платформы, и не нарваться на lock

Хотя вы конечно скажите `static_assert(std::atomic<T>::is_always_lock_free == true, "LOCK DETECTED ALARM")` - в общем, на вкус, на цвет, и на грануларность контроля :)

Я особенно ничего доказывать не хочу, мне просто слишком резанула глаз цитата про единственное исключение - все-таки исключение-то не единственное, и вполне себе можно сочетать volatile и multithreading при должно сноровке :)

Никогда, слышите, никогда не используйте volatile в одном предложении с multithreading. Единственное исключение: предыдущее предложение.


А так спору нет, более того, вне экзотических случаев, лучше вообще использовать готовенький TBB, решающий большинство проблем подо все адекватные платформы :)

Так где выше хоть слово о том, что так `a=1; b=2;` надо делать - там же явно написано

Проверенная годами и highload-нагрузкой схема - volatile, CAS, выравнивание по линейке кеша, серийник в старших битах для обхода ABA-проблемы

При соблюдении всех требований целевой архитектуры - вполне себе рабочее решение :)

Разве ж C и C++ отличаются в поведении относительно volatile?

Проверенная годами и highload-нагрузкой схема - volatile, CAS, выравнивание по линейке кеша, серийник в старших битах для обхода ABA-проблемы - и примитив для многопоточного lockless-алгоритма на X86-64 архитектуру, даже с множеством numa-нод готов - в большинстве случаев даже fence-ы не нужны

Понятно что есть красивый фасад в виде std::atomic вокруг кучи intrinsic-ов, и джунам лучше использовать его, чтобы не выстрелить себе в ногу, но в целом же это банальный синтаксический сахар, и странно говорить что volatile не подходит для многопоточности, в то время как он отлично подходит в решениях, проверенных годами

В конце концов, интринсик всего лишь или вставляет машинную инструкцию, или же инструктирует компилятор об аспектах кодогенерации (например запрещает переставлять операции в целях оптимизации, или маркирует неявную возможную замену объекта при девиртуализации в std::launder, к примеру)

Это примерно из того же разряда, как проверять свойства типов в compile time - классическим SFINAE или через темплейтную auto-лямбду? У второго подхода есть свои плюсы, но странно говорить, что старый добрый SFINAE уже не подходит для этого

никогда не используйте volatile в одном предложении с multithreading

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

При наличии прямых рук нет ничего лучше, чем хорошо спроектированный lockless с соответствующими volatile-ами и барьерами - тот же DPDK юзает в хвост и гриву все вышеуказанное

Для C++-ных junior-ов да, лучше использовать высокоуровневые абстракции типа std atomic-ов, но в целом для highload многопоточных приложений без volatile, барьеров, фенов, CAS-ов - никуда

А почему они должны отмываться, когда все конкуренты поступают та же?

Это настолько очевидная правда, но для ново-левых активистов признать это страшнее, чем расстаться с жизнью

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

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

Оурвеллу такое даже не снилось в страшных снах, а Вы говорите конкуренты :)

Абсолютно поддерживаю: зачем вообще запускать RDBMS в контейнерах, ведь единственное что можно получить - снижение производительности и падение fault tolerance?! Сколько раз приходилось сталкиваться с ситуацией, когда кто-то запускал RDBMS в каких-нибудь условных кубах, и потом жаловался, что приложение (использующее базу) работает очень медленно и нестабильно, посколько время выполнения SQL-запросов падает даже не в разы, а на порядок-два

Удивительно, что не видать нигде ни в открытом доступе, ни в виде коммерческого решения связи из какой-нибудь хорошей RDBMS вроде Postgres и DPDK (Home - DPDK), чтобы запускать базу сразу на нативном сетевом интерфейсе без огромного оверхеда на TCP/IP-стек ядра и тонны системных вызовов с переключением контекстов - на основе так называемого Poll Mode Driver

На одном проекте лет 5 назад пришлось столкнуться с ситуацией, похожей на описанной автором статье: в проекте было близкое к 100% покрытие unit-тестами и ноль интеграционных и функциональных, причем TDD-адепты были категорически против их написания

Доходило до абсурдных ситуаций, когда нерабочий код вливали в релиз-бранч, причем настолько нерабочий, что приложение даже не запускалось (sic!) - выяснялось, что TDD-адепты никогда не запускали приложение перед влитием ветки в релиз-бранч(sic!!), а обходились запуском юнит-тестов

Когда впоследствии TDD-адепты не могли обеспечить 100% ковераж чистыми юнит-тестами, в ход шли моки, фейки и стабы в настолько невероятном количестве, что юнит-тест фактически тестировал только мок-машину, а само приложение только прирастало багами, не говоря уже об уродовании кода ради удобства моков

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

Насчет RDBMS абсолютно плюсую, ACID-база имеет отличные гарантии и консистентность, и функционал на порядки шире новомодного Nosql

Насчет подключения к Rds serverless V1 - там же только два варианта - или VPC, или Rds data api, а еще в относительно недавнем прошлом класть лямбды в VPC имело множество неприятных последствий - лямбды имели медленный холодный старт из VPC, и после перехода в VPC переставали работать с некоторыми другими AWS-сервисами

Сейчас когда лямбды быстро стартуют из VPC и отлично привязываются к HTTPS через Lambda@edge proxy, собственно и было принято выкинуть Rds data api и работать с базой через нативный драйвер посредством TCP-соединения на порт 5432 (Ну или если был бы mysql, то 3306)

Плюс под нагрузкой возникает нюанс, что лямбды периодически аварийно падают, а tcp-соединения к базе висят до tcp timeout , что создает их переизбыток и невозможность подключиться из новых лямбд - но это конечно все дело техники и давно решено (Есть даже готовые npm-пакеты вроде postgres-serverless и mysql-serverless)

С транзакциями вообще отдельная история - из-за общения с СУБД через Stateless REST API, которым фактически является Rds Data Api, единственный способ организовывать транзакции - это передавать их в специальном HTTP-заголовочке, чтобы SQL-запрос был ассоциирован с транзакцией

При этом транзакции именуются специальным guid-ом (не имеющим ничего общего с xid/virtualxid в postgres), который видимо под капотом Rds Data Api использует, чтобы знать, в какую транзакцию направлять поступивший по HTTP SQL-запрос

Так вот, при определенной нагрузке Rds Data Api в лучших традициях начинает обманывать - при отправке "commit" он отвечает, что все ок, а на самом деле транзакция откачена. Из-за этого пришлось заводить специальные служебные таблицы по схемам, чтобы хранить в них глобальный журнал примененных guid-ов транзакций

К сожалению, все на реальных событиях - давайте внимательно рассмотрим исходную архитектуру RDS Serverless Aurora+ Rds Data API по пунктам из статьи на reddit:

1) База данных Postgres serverless лежит спрятанная в приватной VPC-сети, Амазон сам управляет вертикальным масштабирование сервера СУБД, сам перезапускает его и т.д. - физического доступа к серверу у вас нет, возможности покдлючения по TCP тоже нет

2) Амазоновский сервис с незамысловатым названием Rds Data Api - это именно сервис, а не библиотечка, и представляет он собой HTTPS-сервер, в который можно отправлять stateless HTTP-запросы с SQL-запросами и получать в ответ строчки из СУБД. Этот сервис имеет публичный хост+порт + авторизацию по aws secret manager, и это единственный способ общаться с serverless-базой

3) Набор однопоточных лямбд на nodejs, каждая из которых общается с сервисом Rds Data Api, и условно говоря, случайным образом делает "SELECT 0" или "SELECT 1" из СУБД. Если этих лямбд достаточно много, то ответы начинают перепутываться - условно тем, кто запросил "SELECT 0" приходит ответ "1" и наоборот

Конечно же, Вы правы в том смысле, что это проблема highload и многопоточности, только вот нюанс в том, что у лямбд вообще нет соединений с базой данных, и все однопоточные и stateless, а запросы перепутываются **внутри** амазоновского сервиса Rds Data Api, поскольку его разработчики, в отличие от нас с Вами, видимо никогда с настоящим highload-ом в жизни не встречались :)

То же самое и по остальным пунктам. Конечно же, при нагрузке СУБД и сеть могут отбиваться с разнообразными ошибками, и необходимо правильно их retry-ить по смыслу и с правильным дрожанием времени (jitter) между попытками. Однако здесь между вами и СУБД есть многострадальный сервис Rds Data Api, который сам внутри падает с неопределенными ошибками, список которых нигде не задокументирован.

Список ошибок удалось составить только эвристически за несколько недель синтетической нагрузки на сервис. При этом эксперементальным путем было выяснено, что Rds Data Api написан на Java, поскольку часть сыпавшихся ошибок - это необработанные исключение с соответствующим стектрейсом из JDK :)

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

Только в чем тогда вообще задача AWS, если они не могут ни структуризировать ошибки, ни работать с многопоточностью, за что им платить денежку, причем немалую? :)

Единственный приятный момент во всей этой истории случился после обнаружения способа прямого подключения к СУБД в приватной VPC-сети и работы с Postgres-ом напрямую. Rds Data Api был успешно выключен и выкинут, а его разработчики (мысленно) отправлены учить матчасть highload сервисов

И конечно важная ремарка касательно всего вышесказанного - все описанные проблемы возникают стабильно при нагрузке >500 одновременных соединений, а при нагрузке >100 соединений могут проявиться с некоторой вероятностью (за 24 часа вероятность хотя бы одного инцидента стремится к 100%)

Но рассматривать и использовать условно-бесконечно-масштабируемый сервис без нагрузки, конечно, смысла никакого нет - хотя на малой нагрузке все работает терпимо

Что именно почитать? Если про инцидент с перепутыванием запросов, то я больше не публиковал на reddit, поскольку это довольно бессмысленная операция - только немного попинал их в твиттере (1, 2, 3), но фактически тоже безрезультатно - если год назад, когда Data API было в бета-версии и они предпринимали какие-то шаги (к примеру, можно было пообщаться с PM-ом этого сервиса), то сейчас стало понятно, что единственный вариант - это съехать с Rds Data API на VPC

Если про БЧ в API, то здесь BeginTransaction - Amazon RDS Data Service разломали протокол - теперь поле transactionId не ограничено 192 байтами, а могут прислать и 240, при этом БЧ внесли на горячую в работающем кластере, и нигде не заявили об этом, да и документация как видно до сих пор не правленная

Если про доступ через VPC, то толком это нигде не описано, но схема рабочая - краешком это упоминается здесь Using Amazon Aurora Serverless v1 - Amazon Aurora и здесь Best practices for working with Amazon Aurora Serverless | AWS Database Blog

К вопросу о бета-версии ситуация еще интереснее - они вроде как вышли из беты, но работать так ничего толком не стало. В итоге они сейчас в процессе выпуска Aurora Serverless 2.0 - учитывая предыдущий опыт ошибок, они выкинули в нем RDS Data API, обещают прямое подключение к СУБД и хорошие нагрузки, правда доступен только MySQL 5.7

Плюс хитрецы-маркетологи переобулись на лету и откровенно пишут Amazon Aurora Serverless | MySQL PostgreSQL Relational Database | Amazon Web Services , что Aurora Serverless 1.0, то есть текущая версия, вообще предназначен для малых нагрузок или тестирования, а если хотите настоящую нагрузку, то переходите на 2.0 и ждите, когда она выйдет из бета-тестирования

Ситуация вышла интересная: в течение года часть проблем с RDS Data API была решена со стороны aws, часть проблем заткнута набором workaround-ов и эвристик с нашей стороны, и в принципе, все работало довольно стабильно

Но 27 мая этого года, без объявления войны, aws намертво все разломал - внес без предупреждения breaking changes в API (которые до сих пор не задокументированы), а запросы с ответами снова стали перепутываться случайным образом - весь stage, использовавший Rds Data API, развалился фактически без возможности починки

Поэтому было предпринято срочное решение по переезду в VPC - сейчас пользоваться Aurora Postgres Serverless можно с подключением к СУБД напрямую, минуя сломанное Rds Data API, но из приватной VPC-сети - что в конечно итоге было сделано, и с тех пор проблем больше лет - все летает и вертикально масштабируется

Сама по себе AWS RDS Mysql/Postgres serverless отличная база, с автоматическим вертикальным масштабированием, но предоставляемый по умолчанию интерфейс взаимодействия RDS Data API - это не просто недостаточно некачественный сервис, а абсолютно мусорного уровня, включая перепутывание запросов с ответами, бесчисленные недокументированные сервисные ошибки, наполовину работающие транзакции и так далее, и абсолютно наплевательное отношение техподдержки (Если интересно ознакомиться, в этом посте AWS Postgresql Serverless - tricks and caveats : serverless (reddit.com) мной рассказывается вся история с начала до текущих дней :)

However, shadowed window and document objects from inner iframe are accessible


const o = __proto__.__proto__.__proto__.__proto__.constructor;
try{o.defineProperty(__proto__, "w", {get: function() { return this } });}catch(e){};
const d = w.document;

Information

Rating
4,339-th
Location
Тула, Тульская обл., Россия
Date of birth
Registered
Activity