Search
Write a publication
Pull to refresh
50
0.6
Valentin Nechayev @netch80

Программист (backend/сети)

Send message

На вм операции выполняются совершенно в другом кольце команд

Вообще отношение хозяин/гость ортогонально "кольцу команд" (слишком x86 термин, ну да пусть).

величины задержек времени выполнения операций стабильно выше на 14-27% по сравнению с аналогичными на физическом стенде.

Какой был процессор, в каком режиме работала kvm (как минимум, EPT/NP или shadow tables), какая битность систем, были ли вложенные гости?

А у кого есть доступ к железу, есть доступ вообще ко всему :)

Если железо его допускает и цена на операцию подъёмная. В случае Intel SGX, вам, например, денег точно не хватит, чтобы найти, как в конкретном процессоре чего доработать напильником прямо на кристалле, чтобы добраться до памяти анклава в нешифрованном виде:)

Угу. Ну вот в том и дело, что когда речь идёт про CPU, доступ к диску и т.п., мы можем обеспечить какие-то гарантированные объёмы ресурса простейшими локальными методами, а если про сеть - то на это требуется обеспечение по всему пути до каждого ремота. А так как IntServ начали завозить, потом вывезли обратно и больше не завезут (локальные сети на IB и прочее за прайс x20 не считаю), то весь рассказ ТС про "гарантии стабильности и полную свободу" - уже даже не маркетинговое враньё.

Вот против такого и придумали Intel Software Guard Extensions (не знаю насчёт адекватных аналогов у остальных), есть на программном уровне варианты шифровать все данные и обрабатывать в шифрованном виде (чисто алгоритмически описано у Шнайера), наверняка ещё что-то придумали, я только поверхностно знаю. Но у Intel и AMD сейчас даже память, занятая виртуалками, может проходить шифрование данных, чтобы при случайной её выдаче соседям или хозяйской системе они ничего не прочитали. Диск может быть запаролен, а пароль вычисляться при старте на основании данных лукапа куда-то извне. И прочая и прочая.

В сумме это не даёт 100%, конечно, но на порядки резко усложняет подглядывание нечестным админом.

сервис на стеке java spring boot

А вы не пробовали возить товары в магазинчик за углом не на Ан-22? И с каких это пор Spring Boot тождественно Java?

Кстати, какую именно память вы меряли? Их несколько.

Python судя по бенчмаркам потребления памяти лучше джавы раза в 2

Что означает выбор вами в сравнении менее прожорливого фреймворка, не более того.

Менее прожорлива это сколько?

У меня с реально равным по сути и объёму кодом получалось от полутора раз, зависит от данных.

Утверждения про прожорливость Java отстают лет на 15. И в любом случае она будет менее прожорлива, чем Python на тех же задачах.

Утверждения про проблемы с поддержкой - я не понял, к какому именно языку они относятся.

И тут возникает вопрос - а как при виртуализации чувствует себя этот кэш: не сможет ли один VDS начать бесконтрольно его использовать, мешая остальным?

Лучше считать, что при переключении виртуалок на конкретном ядре кэш чистится в ноль. (Это может быть и явным действием для защиты от проблем типа Meltdown/Spectre, и неявным за счёт того, что другой гость начинает активно использовать кэш, и тогда данные прежнего вымываются.)

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

Была такая технология в начеле 10-х (и вроде как, и сейчас есть) - Single Root IO Virtualization (SR-IOV).

Спасибо, я в 2011 её щупал.
Основной вариант разделения по MAC, но можно и как-то ещё извратиться. В гостя выставляется интерфейс типа обычной сетевухи, но попроще. Но:

а потому вероятность стать узким местом при DDOS для него невелика.

Кабель всё равно один. И та часть карты, что принимает и раскладывает по гостям, одна. Я именно про это говорю.

до Win12 R2 включительно

Win12?

Приличное увеличение производительности (на 20–30% в Python 3.11+) устраняет традиционные возражения против использования языка в высоконагруженных системах

Ну уж нет, если переходом на Go, Java и прочих можно с ходу получить 10-30-кратное (в сравнении с CPython), 5-20-кратное (в сравнении с PyPy) ускорение, и, например, двукратную экономию по памяти, и всё это не теряя плюшек AutoMM. "Цуть-цуть" оттянуть неизбежное - да.

А вот список инструментов, угу, неплохой.

Сейчас это один вид услуг — полностью изолированный виртуальный сервер с выделенными ресурсами.

Использую один как раз VPS хостинг, классический VZ-like. Знаю места, где такого много. Так что не надо обобщать.

На практике виртуальные серверы получают реальный сетевой интерфейс (1, 10 или даже 40 Гбит) и выделенный публичный IP.

Ага, как процессор (ядро, харт) так не выделяется, а как сетевой адаптер так выделяется? И как же, если их как раз заведомо меньше, чем ядер у серверного процессора?

В свою очередь, VDS даёт гарантии стабильности и полную свободу.

Особенно когда сеть забита DoS трафиком, угу.

За такое только минус.

Сейчас из-за этого кэширования получается неравномерное время запросов, что стреляет в некоторых случаях и даёт неровную работу сервисов. Но нет возможности сказать типа "раз у тебя осталось на эту запись TTL<60, обнови её сейчас принудительно вслед моему запросу". Вот за исправление этого многие сказали бы "спасибо".

DNS изначально придуман с кэшированием на всех уровнях. Даже если вы в пределах своей инфраструктуры объедините вообще всё, окажется, что на промежуточных уровнях может что-то кэшироваться по-своему (стреляет, например, когда вы меняете NSы для вашего базового домена).

ибо дочерние fd выглядят коряво

Коряво, угу. Но работает и имеет свои преимущества. Да, я видел твои замечания про линуксовый подход с xxxfd_create(), но согласись, что в этом случае резко упрощается учёт потраченных ресурсов, для всех сторон. В случае kevent, как увидеть количество, например, таймеров, навешенных на одну конкретную kqueue, процессов, и т.д.? Видеть их всех в виде дескрипторов - просто и достаточно надёжно, то есть вполне себе юниксовый подход "всё есть файл".

(Мне интересно, сколько вообще ведутся споры на эту тему? С 2000, когда появилась kqueue?)

просто устранили эту проблему архитектуры.

Я увидел пассаж:

An endpoint implementing the socket API specified in [RFC6458] MUST NOT indicate user message interleaving support unless the user has requested its use (e.g., via the socket API; see Section 4.3). This constraint is made since the usage of this chunk requires that the application is capable of handling interleaved messages upon reception within an association.

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

Я тут, конечно, ужален проблемами одного почти провального проекта, где из-за аналогичной глупости в Erlang оказалось практически нереально обеспечить стабильный поток проходящих данных, и дую на воду, но для меня теперь вариант "хлебай что дают из пожарного шланга", который реализуется таким подходом, не подходит для чего-то серьёзнее песочницы. (Там было ещё хуже: один вход у "процесса" на всё включая канал регулировки. Тут хотя бы можно назад передавать сообщения типа "добавляю окно на 100кбайт для потока 8" и они могут быть прочтены вперёд собственно данных.)

Так это ж разные уровни - ACK оно по факту приема пакета, который будет положен в буферы сокета (и его нельзя не акнуть, ибо иначе congestion control вскинется), а уже потом, позже, приложение будет решать, какой вычитать.

Если один буфер на все потоки - это уже не то, что нужно. Нужны раздельные.
Повторюсь, если этого нет, то фактически нет разницы с тем, что просто в одном потоке тегировали каждое сообщение ещё и одним байтиком перед ним (или в userdata уложили тот тег). Заодно и деление на чанки точно так же делается на уровне юзера, в пределах того же соединения.

А вот реально раздельное управление потоком по всем потокам (русский тут чего-то зажат в омонимию, per-stream flow control) ты на одном соединении не сделаешь, тут что TCP что SCTP надо сейчас несколько порождать, а тогда ещё и заботиться, чтобы пришло именно на нужный серверный процесс, указать серверу, что это соединение надо ставить в комплект вот этому... марудно. Вот потому, я так понимаю, и стали запускать SPDY с потомками - когда поняли, что от последней попытки (SCTP) ждать хорошего всё равно нельзя.

на практике-то захочется иметь иерархию стримов (даже в HTTP/2 её делали), как в SST, где ребенок borrow'ит окно у родителя, а тот у бабушки...

Я честно не понял ещё смысла в этом навороте. Поищу при случае.

Заметки тоже почитаю.

Однако, "выбрать только из конкретного потока" плохо ложится как на BSD Sockets API, так и на struct sockbuf в ядре...

BSD sockets в базовом виде и так не дают всего, что может SCTP, и есть поэтому свой специфичный набор вызовов. Ещё один добавить - не проблема. Или можно было бы сделать, например, дочерние fd, привязанные к конкретному потоку, чтобы над ними уже вызывать хоть простейший read().

Про struct sockbuf я не в курсе, что там не так.

И если userland API нет для этой возможности, то уже неважно, есть там I-DATA или нет. Я ещё не прочитал RFC, если там что-то не понравится - выскажу отдельно.

Когда потоков много, общий ACK будет гораздо эффективнее, а при правильной реализации это мешать не должно.

А она тут в принципе может быть, эта "правильная" реализация, если у нас вот сейчас настроение выбрать всё из потока 9 не выбирая остальных, даже если для них приёмные буфера забиты?

Обычной задаче и сейчас хватает десятка-двух даже на современном Linux. При том, что 4 с ходу занято на стандартные дескрипторы и "text".

То, что в статье, описывает, что что-то явно подломано. Явная утечка или не запускающийся GC...

(Вариант 100 тестов впараллель я не рассматриваю, так вряд ли будут делать.)

В IDEшках сижу в JetBrainsʼовских, но некоторые вещи удобнее делать через консоль (классический vim; neo варианты не оценил пока). Перекос на 100% что в одну, что в другую сторону - это нехорошо.

Вот Gitʼом в IDEшках так и не научился, не просто "закоммитить всё и в сообщении сказать up", а более сложные вещи.

Слово "боль" в заголовке статьи совершенно неуместно, нет там никакой боли. Просто другие методы и привычки, которые лучше для своего случая.

(Уходя в оффтопик) Ну вообще-то определённая доля насилия со стороны стандартизаторов всегда есть. Например, исключение формы "ложить" из всего ряда (положить, разложить, etc.) - выглядит совершенно неестественно. Я за неимением точных данных верю в легенду, что её исключили, чтобы задавить выражение "ложить х.й". Впрочем, не помогло, тот же предмет стали класть, а не ложить:)
И исключение формы "ихний" немного логично при проблемах выбора - как правильнее "ейный" или "еёный", как писать "егойный" и т.п. - легче оказалось всё скопом запретить, чем разбираться.
Или, почему "февраль" принят в стандарт, при исходном ближе к "феврарь" (Februarius с византийским переходом б->в), а "колидор" - не принимают, изволь говорить "коридор".
Или почему "протвин", которое ближе к исходному Bratpfanne, не допускается, зато стандартизовано "противень", которое выглядит искусственным выгибоном.
Примеры можно долго продолжать.

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

Думаю на старте 3 млн не хватит

Естественно. Железо живёт не год, а минимум 3, а скорее 5 лет. Разве что диски живут 1-2 года. Если покупаете свою железку - сразу эти 5 лет и платите. Если в облаке - то по настроению.

Посмотрите на цену AWS EC2 reserved instances на 3 года вперёд. Уже на мелких вы получите падение цены в 2 раза по сравнением со стандартным on-demand, на крупных - в три раза. А что это за цена?
Я считал уже давно, лет 10 прошло (ну и летит время...), но цена AWS EC2 при закупке на 3 года ("reserved instances") как раз была процентов на 10 больше, чем свой сервер аналогичной конфигурации с установкой в приличный ДЦ, всё в США. В Украине, может, в 2 раза дешевле сам ДЦ, но не железо. Да, это цена гибкости и их страховка на изменение спроса (вдруг что-то произойдёт и каждому бухгалтеру потребуется сервер с AVX1024 и квантовым ИИ процессором;))
Сейчас пересчитывать не хочу, но не думаю, что картина сильно изменилась, скорее наоборот, конкурентов стало больше. А считать облачные провайдеры умеют.

Поэтому - если пока не знаете, что нужно и сколько - берёте on demand. Уверены в надёжности необходимости на год, два, три - покупаете reserved. Вот если это по объёму начинает переваливать, условно, 10 физических серверов - и цена хотя бы на part-time админа нужного качества становится окупаемой - ищете отдельный ДЦ и ставите свои железяки, пока он раскачается, как раз будет время смигрировать.

Главное - что этот переход за счёт таких мер можно делать плавным, а не просто "всё в облаке на on-demand за дикие деньги" vs. "всё на чердаке собственного здания, собственные админы делают всё, от дренажа подвала и смазывания генератора до управления конфигами кубера".

(То, что сети разных ДЦ надо связывать между собой, вопрос отдельный и сложный. Да, на этом облачные провайдеры хорошо зарабатывают.)

это не опечатка и это не копирование строк это копирование данных по массивам указателей. Немного специфичная опирация

"Немного"? Я сильно сомневаюсь, что вы найдёте хоть одну реальную задачу, в которой нужен был бы такой приём, и которая не решалась бы иначе - проще и понятнее. Только не надо изобретать на ходу:)

Я уже тут говорил - 5-й режим, @-(Rn), вообще ни разу не видел вживую, кроме шуточек, а 3-й, @(Rn)+, если не считать применение к регистру PC - в очень редких случаях. И такого копирования там не было.

Еще по командам MOVS и другим специализированным в X86: как там у них с переворотом массивов, сложением массивов, форммированием массивов с чередованием данных из нескольких массивов.

Сложение без переноса - смысла мало, а про перенос мы уже обсуждали, без двухаргументной ADC больно. Остальные задачи встречаются, но достаточно ограниченно, и дополнительный INC или DEC это дёшево. На супер-преимущество автоинкремента/автодекремента не тянет.
И это без дополнительной косвенности. А с такой косвенностью - тот же вопрос, был ли хоть один реальный пример такого употребления на данных командах?

Я прочёл Ваш пример именно как копирование строк, то есть *a++ = *b++. У вас там вторая звёздочка, мне показывает **a++ = **b++. Я считаю её опечаткой, потому что практического смысла в такой операции при двойном разыменовании не вижу; натянутые искусственные примеры не в счёт. Поэтому отвечаю на то, что прочёл.

Если ответить максимально буквально - MOVSB, одна команда. Причём, если с вариантами REP MOVSB, то это полное копирование участка памяти с заданной длиной, а если REPNE MOVSB - то ещё и с остановкой после нулевого байта. Так что ваш пример оборачивается против вас:)

(Начиная с где-то 486 рекомендуют явный цикл, а при наличии SIMD - его методами, когда за итерацию копируется 16, 32, 64, 128 байт, в зависимости от степени развёрнутости цикла. (Можете посмотреть набор реализаций, например, в glibc.) Но это сильно позже и потому за пределами темы.)

Но если рассматривать задачу в её исходном виде - какая часть реального кода в среднем современном приложении занимается копированием строк в массовом порядке? Я думаю, слишком малая, чтобы считать пользу от прямой реализации в духе MOVB (R2)+,(R3)+ чем-то ценной.

Information

Rating
5,719-th
Location
Киев, Киевская обл., Украина
Date of birth
Registered
Activity