Пол шестого как пишется цифрами

Звуко буквенный разбор слова: чем отличаются звуки и буквы?прежде чем перейти к выполнению фонетического разбора с примерами обращаем ваше внимание,

Звуко буквенный разбор слова: чем отличаются звуки и буквы?

Прежде чем перейти к выполнению фонетического разбора с примерами обращаем ваше внимание, что буквы и звуки в словах — это не всегда одно и тоже.

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

Список всех букв — это просто алфавит

Почти каждый школьник знает сколько букв в русском алфавите. Правильно, всего их 33. Русскую азбуку называют кириллицей. Буквы алфавита располагаются в определенной последовательности:

Алфавит русского языка:

Аа «а» Бб «бэ» Вв «вэ» Гг «гэ»
Дд «дэ» Ее «е» Ёё «йо» Жж «жэ»
Зз «зэ» Ии «и» Йй «й» Кк «ка»
Лл «эл» Мм «эм» Нн «эн» Оо «о»
Пп «пэ» Рр «эр» Сс «эс» Тт «тэ»
Уу «у» Фф «эф» Хх «ха» Цц «цэ»
Чч «чэ» Шш «ша» Щщ «ща» ъ «т.з.»
Ыы «ы» ь «м.з.» Ээ «э» Юю «йу»
Яя «йа»

Всего в русском алфавите используется:

  • 21 буква для обозначения согласных;
  • 10 букв — гласных;
  • и две: ь (мягкий знак) и ъ (твёрдый знак), которые указывают на свойства, но сами по себе не определяют какие-либо звуковые единицы.

Звуки — это фрагменты голосовой речи. Вы можете их услышать и произнести. Между собой они разделяются на гласные и согласные. При фонетическом разборе слова вы анализируете именно их.

Звуки в фразах вы зачастую проговариваете не так, как записываете на письме. Кроме того, в слове может использоваться больше букв, чем звуков. К примеру, «детский» — буквы «Т» и «С» сливаются в одну фонему [ц]. И наоборот, количество звуков в слове «чернеют» большее, так как буква «Ю» в данном случае произносится как [йу].

Что такое фонетический разбор?

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

Фонетическая транскрипция

Для звуко-буквенного разбора применяют специальную транскрипцию в квадратных скобках. К примеру, правильно пишется:

  • чёрный ->  [ч’о́рный’]
  • яблоко  ->  [йа́блака]
  • якорь    ->  [йа́кар’]
  • ёлка      ->  [йо́лка]
  • солнце ->  [со́нцэ]

В схеме фонетического разбора используются особые символы. Благодаря этому можно корректно обозначить и отличить буквенную запись (орфографию) и звуковое определение букв (фонемы).

  • фонетически разбираемое слово заключается квадратные скобки – [ ];
  • мягкий согласный обозначается знаком транскрипции [’] — апострофом;
  • ударный [´] — ударением;
  • в сложных словоформах из нескольких корней применяется знак второстепенного ударения [`] — гравис (в школьной программе не практикуется);
  • буквы алфавита Ю, Я, Е, Ё, Ь и Ъ в транскрипции НИКОГДА не используются (в учебной программе);
  • для удвоенных согласных применяется [:] — знак долготы произнесения звука.

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

Как сделать фонетический разбор слова?

Провести буквенный анализ вам поможет следующая схема:

  • Выпишите необходимое слово и произнесите его несколько раз вслух.
  • Посчитайте сколько в нем гласных и согласных букв.
  • Обозначьте ударный слог. (Ударение при помощи интенсивности (энергии) выделяет в речи определенную фонему из ряда однородных звуковых единиц.)
  • Разделите фонетическое слово по слогам и укажите их общее количество. Помните, что слогораздел в отличается от правил переноса. Общее число слогов всегда совпадает с количеством гласных букв.
  • В транскрипции разберите слово по звукам.
  • Напишите буквы из фразы в столбик.
  • Напротив каждой буквы квадратных скобках [ ] укажите ее звуковое определение (как она слышатся). Помните, что звуки в словах не всегда тождественны буквам. Буквы «ь» и «ъ» не представляют никаких звуков. Буквы «е», «ё», «ю», «я», «и» могут обозначать сразу 2 звука.
  • Проанализируйте каждую фонему по отдельности и обозначьте ее свойства через запятую:
    • для гласного указываем в характеристике: звук гласный; ударный или безударный;
    • в характеристиках согласных указываем: звук согласный; твёрдый или мягкий, звонкий или глухой, сонорный, парный/непарный по твердости-мягкости и звонкости-глухости.
  • В конце фонетического разбора слова подведите черту и посчитайте общее количество букв и звуков.

Данная схема практикуется в школьной программе.

Пример фонетического разбора слова

Вот образец фонетического разбора по составу для слова «явление» → [йивл’э′н’ийэ]. В данном примере 4 гласных буквы и 3 согласных. Здесь всего 4 слога: я-вле′-ни-е. Ударение падает на второй.

Звуковая характеристика букв:

я  [й]   — согл., непарный мягкий, непарный звонкий, сонорный    [и]   — гласн., безударныйв  [в]   — согл., парный твердый, парный зв.л  [л’]  — согл., парный мягк., непарн. зв., сонорныйе  [э′]   — гласн., ударныйн  [н’]   — согласн., парный мягк., непарн. зв., сонорный и  [и]   — гласн., безударный  [й]   — согл., непарн. мягк., непарн. зв., сонорный    [э]   — гласн., безударный________________________Всего в слове явление – 7 букв, 9 звуков. Первая буква «Я» и последняя «Е» обозначают по два звука.

Теперь вы знаете как сделать звуко-буквенный анализ самостоятельно. Далее даётся классификация звуковых единиц русского языка, их взаимосвязи и правила транскрипции при звукобуквенном разборе.

Фонетика и звуки в русском языке

Какие бывают звуки?

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

— Сколько в русской живой речи звуков?

Правильный ответ 42.

Делая фонетический разбор онлайн, вы обнаружите, что в словообразовании участвуют 36 согласных звуков и 6 гласных. У многих возникает резонный вопрос, почему существует такая странная несогласованность? Почему разнится общее число звуков и букв как по гласным, так и по согласным?

Всё это легко объяснимо. Ряд букв при участии в словообразовании могут обозначать сразу 2 звука. Например, пары по мягкости-твердости:

  • [б] — бодрый и [б’] — белка;
  • или [д]-[д’]: домашний — делать.

А некоторые не обладают парой, к примеру [ч’] всегда будет мягким. Сомневаетесь, попытайтесь сказать его твёрдо и убедитесь в невозможности этого: ручей, пачка, ложечка, чёрным, Чегевара, мальчик, крольчонок, черемуха, пчёлы. Благодаря такому практичному решению наш алфавит не достиг безразмерных масштабов, а звуко-единицы оптимально дополняются, сливаясь друг с другом.

Гласные звуки в словах русского языка

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

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

— Сколько гласных звуков в русской фонетике?

В русской речи используется меньше гласных фонем, чем букв. Ударных звуков всего шесть: [а], [и], [о], [э], [у], [ы]. А букв, напомним, десять: а, е, ё, и, о, у, ы, э, я, ю. Гласные буквы Е, Ё, Ю, Я не являются «чистыми» звуками и в транскрипции не используются. Нередко при буквенном разборе слов на перечисленные буквы падает ударение.

Фонетика: характеристика ударных гласных

Главная фонематическая особенность русской речи — четкое произнесение гласных фонем в ударных слогах. Ударные слоги в русской фонетике отличаются силой выдоха, увеличенной продолжительностью звучания и произносятся неискаженно. Поскольку они произносятся отчетливо и выразительно, звуковой анализ слогов с ударными гласными фонемами проводить значительно проще. Положение, в котором звук не подвергается изменениям и сохранят основной вид, называется сильной позицией. Такую позицию может занимать только ударный звук и слог. Безударные же фонемы и слоги пребывают в слабой позиции.

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

В русском языке неизменяемые фонетические свойства сохраняет лишь одна фонема «У»: кукуруза, дощечку, учусь, улов, — во всех положениях она произносятся отчётливо как [у]. Это означает, что гласная «У» не подвергается качественной редукции. Внимание: на письме фонема [у] может обозначатся и другой буквой «Ю»: мюсли [м’у´сл’и], ключ [кл’у´ч’] и тд.

Разбор по звукам ударных гласных

Гласная фонема [о] встречается только в сильной позиции (под ударением). В таких случаях «О» не подвергается редукции: котик [ко´т’ик], колокольчик [калако´л’ч’ык], молоко [малако´], восемь [во´с’им’], поисковая [паиско´вайа], говор [го´вар], осень [о´с’ин’].

Исключение из правила сильной позиции для «О», когда безударная [о] произносится тоже отчётливо, представляют лишь некоторые иноязычные слова: какао [кака’о], патио [па’тио], радио [ра’дио], боа [боа’] и ряд служебных единиц, к примеру, союз но.
Звук [о] в письменности можно отразить другой буквой«ё» – [о]: тёрн [т’о´рн], костёр [кас’т’о´р]. Выполнить разбор по звукам оставшихся четырёх гласных в позиции под ударением так же не представит сложностей.

Безударные гласные буквы и звуки в словах русского языка

Сделать правильный звуко разбор и точно определить характеристику гласного можно лишь после постановки ударения в слове. Не забывайте так же о существовании в нашем языке омонимии: за’мок — замо’к и об изменении фонетических качеств в зависимости от контекста (падеж, число):

  • Я дома [йа до‘ма].
  • Новые дома [но’выэ дама’].

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

  • горы — гора = [го‘ры] — [гара’];
  • он — онлайн = [о‘н] — [анла’йн]
  • свидетельница = [св’ид’э‘т’ил’н’ица].

Подобные изменения гласных в безударных слогах называются редукцией. Количественной, когда изменяется длительность звучания. И качественной редукцией, когда меняется характеристика изначального звука.

Одна и та же безударная гласная буква может менять фонетическую характеристику в зависимости от положения:

  • в первую очередь относительно ударного слога;
  • в абсолютном начале или конце слова;
  • в неприкрытых слогах (состоят только из одного гласного);
  • од влиянием соседних знаков (ь, ъ) и согласного.

Так, различается 1-ая степень редукции. Ей подвергаются:

  • гласные в первом предударном слоге;
  • неприкрытый слог в самом начале;
  • повторяющиеся гласные.

Примечание: Чтобы сделать звукобуквенный анализ первый предударный слог определяют исходя не с «головы» фонетического слова, а по отношению к ударному слогу: первый слева от него. Он в принципе может быть единственным предударным: не-зде-шний [н’из’д’э´шн’ий].

(неприкрытый слог)+(2-3 предударный слог)+ 1-й предударный слог ← Ударный слог → заударный слог (+2/3 заударный слог)

  • впе-ре-ди [фп’ир’ид’и´];
  • е-сте-стве-нно [йис’т’э´с’т’в’ин:а];

Любые другие предударные слоги и все заударные слоги при звуко разборе относятся к редукции 2-й степени. Ее так же называют «слабая позиция второй степени».

  • поцеловать [па-цы-ла-ва´т’];
  • моделировать [ма-ды-л’и´-ра-ват’];
  • ласточка [ла´-ста-ч’ка];
  • керосиновый [к’и-ра-с’и´-на-вый].

Редукция гласных в слабой позиции так же различается по ступеням: вторая, третья (после твердых и мягких соглас., — это за пределами учебной программы): учиться [уч’и´ц:а], оцепенеть [ацып’ин’э´т’], надежда [над’э´жда]. При буквенном анализе совсем незначительно проявятся редукция у гласного в слабой позиции в конечном открытом слоге (= в абсолютном конце слова):

  • чашечка;
  • богиня;
  • с песнями;
  • перемена.

Звуко буквенный разбор: йотированные звуки

Фонетически буквы Е — [йэ], Ё — [йо], Ю — [йу], Я — [йа] зачастую обозначают сразу два звука. Вы заметили, что во всех обозначенных случаях дополнительной фонемой выступает «Й»? Именно поэтому данные гласные называют йотированными. Значение букв Е, Ё, Ю, Я определяется их позиционным положением.

При фонетическом разборе гласные е, ё, ю, я образуют 2 звука:

Ё — [йо], Ю — [йу], Е — [йэ], Я — [йа] в случаях, когда находятся:

  • В начале слова «Ё» и «Ю» всегда:
    • — ёжиться [йо´жыц:а], ёлочный [йо´лач’ный], ёжик [йо´жык], ёмкость [йо´мкаст’];
    • — ювелир [йув’ил’и´р], юла [йула´], юбка [йу´пка], Юпитер [йуп’и´т’ир], юркость [йу´ркас’т’];
  • в начале слова «Е» и «Я» только под ударением*:
    • — ель [йэ´л’], езжу [йэ´ж:у], егерь [йэ´г’ир’], евнух [йэ´внух];
    • — яхта [йа´хта], якорь [йа´кар’], яки [йа´ки], яблоко [йа´блака];
    • (*чтобы выполнить звуко буквенный разбор безударных гласных «Е» и «Я» используется другая фонетическая транскрипция, см. ниже);
  • в положении сразу после гласного «Ё» и «Ю» всегда. А вот «Е» и «Я» в ударных и в безударных слогах, кроме случаев, когда указанные буквы располагаются за гласным в 1-м предударном слоге или в 1-м, 2-м заударном слоге в середине слов. Фонетический разбор онлайн и примеры по указным случаям:
    • — приёмник [пр’ийо´мн’ик], поёт [пайо´т], клюёт [кл’уйо´т];
    • аюрведа [айур’в’э´да], поют [пайу´т], тают [та´йут], каюта [кайу´та],
  • после разделительного твердого «Ъ» знака «Ё» и «Ю» — всегда, а«Е» и «Я» только под ударением или в абсолютном конце слова: — объём [аб йо´м], съёмка [сйо´мка], адъютант [адйу‘та´нт]
  • после разделительного мягкого «Ь» знака «Ё» и «Ю» — всегда, а «Е» и «Я» под ударением или в абсолютном конце слова: — интервью [интырв’йу´], деревья [д’ир’э´в’йа], друзья [друз’йа´], братья [бра´т’йа], обезьяна [аб’из’йа´на], вьюга [в’йу´га], семья [с’эм’йа´]

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

Безударные гласные «Е» и «Я» обозначают два звука и в фонетической транскрипции и записываются как [ЙИ]:

  • в самом начале слова:
    • — единение [йид’ин’э´н’и’йэ], еловый [йило´вый], ежевика [йижив’и´ка], его [йивo´], егоза [йигаза´], Енисей [йин’ис’э´й], Египет [йиг’и´п’ит];
    • — январский [йинва´рский], ядро [йидро´], язвить [йиз’в’и´т’], ярлык [йирлы´к], Япония [йипо´н’ийа], ягнёнок [йигн’о´нак];
    • (Исключения представляют лишь редкие иноязычные словоформы и имена: европеоидная [йэврап’ио´иднайа], Евгений [йэ]вге´ний, европеец [йэврап’э´йиц], епархия [йэ]па´рхия и тп).
  • сразу после гласного в 1-м предударном слоге или в 1-м, 2-м заударном слоге, кроме расположения в абсолютном конце слова.
    • своевременно [свайивр’э´м’ина], поезда [пайизда´], поедим [пайид’и´м], наезжать [найиж:а´т’], бельгиец [б’ил’г’и´йиц], учащиеся [уч’а´щ’ийис’а], предложениями [пр’идлажэ´н’ийим’и], суета [суйита´],
    • лаять [ла´йит’], маятник [ма´йитн’ик], заяц [за´йиц], пояс [по´йис], заявить [зайив’и´т’], проявлю [прайив’л’у´]
  • после разделительного твердого «Ъ» или мягкого «Ь» знака: — пьянит [п’йин’и´т], изъявить [изйив’и´т’], объявление [абйи вл’э´н’ийэ], съедобный [сйидо´бный].

Примечание: Для петербургской фонологической школы характерно «эканье», а для московской «иканье». Раньше йотрованный «Ё» произносили с более акцентированным «йэ». Со сменой столиц, выполняя звуко-буквенный разбор, придерживаются московских норм в орфоэпии.

Некоторые люди в беглой речи произносят гласный «Я» одинаково в слогах с сильной и слабой позицией. Такое произношение считается диалектом и не является литературным. Запомните, гласный «я» под ударением и без ударения озвучивается по-разному: ярмарка [йа´рмарка], но яйцо [йийцо´].

Важно:

Буква «И» после мягкого знака «Ь» тоже представляет 2 звука — [ЙИ] при звуко буквенном анализе. (Данное правило актуально для слогов как в сильной, так и в слабой позиции). Проведем образец звукобуквенного онлайн разбора: — соловьи [салав’йи´], на курьих ножках [на ку´р’йи’х’ но´шках], кроличьи [кро´л’ич’йи], нет семьи [с’им’йи´], судьи [су´д’йи], ничьи [н’ич’йи´], ручьи [руч’йи´], лисьи [ли´с’йи]. Но: Гласная «О» после мягкого знака «Ь» транскрибируется как апостроф мягкости [’] предшествующего согласного и [О], хотя при произнесении фонемы может слышаться йотированность: бульон [бул’о´н], павильон [пав’ил’о´н], аналогично: почтальон, шампиньон, шиньон, компаньон, медальон, батальон, гильотина, карманьола, миньон и прочие.

Фонетический разбор слов, когда гласные «Ю» «Е» «Ё» «Я» образуют 1 звук

По правилам фонетики русского языка при определенном положении в словах обозначенные буквы дают один звук, когда:

  • звуковые единицы «Ё» «Ю» «Е» находятся в под ударением после непарного согласного по твердости: ж, ш, ц. Тогда они обозначают фонемы:
    • ё — [о],
    • е — [э],
    • ю — [у].

    Примеры онлайн разбора по звукам: жёлтый [жо´лтый], шёлк [шо´лк], целый [цэ´лый], рецепт [р’ицэ´пт], жемчуг [жэ´мч’ук], шесть [шэ´ст’], шершень [шэ´ршэн’], парашют [парашу´т];

  • Буквы «Я» «Ю» «Е» «Ё» и «И» обозначают мягкость предшествующего согласного [’]. Исключение только для: [ж], [ш], [ц]. В таких случаях в ударной позиции они образуют один гласный звук:
    • ё – [о]: путёвка [пут’о´фка], лёгкий [л’о´хк’ий], опёнок [ап’о´нак], актёр [акт’о´р], ребёнок [р’иб’о´нак];
    • е – [э]: тюлень [т’ул’э´н’], зеркало [з’э´ркала], умнее [умн’э´йэ], конвейер [канв’э´йир];
    • я – [а]: котята [кат’а´та], мягко [м’а´хка], клятва [кл’а´тва], взял [вз’а´л], тюфяк [т’у ф’а´к], лебяжий [л’иб’а´жый];
    • ю – [у]: клюв [кл’у´ф], людям [л’у´д’ам ], шлюз [шл’у´с], тюль [т’у´л’], костюм [кас’т’у´м].
    • Примечание: в заимствованных из других языков словах ударная гласная «Е» не всегда сигнализирует о мягкости предыдущего согласного. Данное позиционное смягчение перестало быть обязательной нормой в русской фонетике лишь в XX веке. В таких случаях, когда вы делаете фонетический разбор по составу, такой гласный звук транскрибируется как [э] без предшествующего апострофа мягкости: отель [атэ´л’], бретелька [бр’итэ´л’ка], тест [тэ´ст], теннис [тэ´н:ис], кафе [кафэ´], пюре [п’урэ´], амбре [амбрэ´], дельта [дэ´л’та], тендер [тэ´ндэр], шедевр [шэдэ´вр], планшет [планшэ´т].
  • Внимание! После мягких согласных в предударных слогах гласные «Е» и «Я» подвергаются качественной редукции и трансформируются в звук [и] (искл. для [ц], [ж], [ш]). Примеры фонетического разбора слов с подобными фонемами: — зерно [з’ирно´], земля [з’имл’а´], весёлый [в’ис’о´лый], звенит [з’в’ин’и´т], лесной [л’исно´й], метелица [м’ит’е´л’ица], перо [п’иро´], принесла [пр’ин’исла´], вязать [в’иза´т’], лягать [л’ига´т’], пятёрка [п’ит’о´рка]

Фонетический разбор: согласные звуки русского языка

Согласных в русском языке абсолютное большинство. При выговаривании согласного звука поток воздуха встречает препятствия. Их образуют органы артикуляции: зубы, язык, нёбо, колебания голосовых связок, губы. За счет этого в голосе возникает шум, шипение, свист или звонкость.

Сколько согласных звуков в русской речи?

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

Звуко-буквенный разбор: какими бывают согласные звуки?

В нашем языке согласные бывают:

  • твердые — мягкие и образуют соответствующие пары:
    • [б] — [б’]: банан — белка,
    • [в] — [в’]: высота — вьюн,
    • [г] — [г’]: город — герцог,
    • [д] — [д’]: дача — дельфин,
    • [з] — [з’]: звон — зефир,
    • [к] — [к’]: конфета — кенгуру,
    • [л] — [л’]: лодка — люкс,
    • [м] — [м’]: магия — мечты,
    • [н] — [н’]: новый — нектар,
    • [п] — [п’]: пальма— пёсик,
    • [р] — [р’]: ромашка — ряд,
    • [с] — [с’]: сувенир — сюрприз,
    • [т] — [т’]: тучка — тюльпан,
    • [ф] — [ф’]: флаг — февраль,
    • [х] — [х’]: хорек — хищник.
  • Определенные согласные не обладают парой по твердости-мягкости. К непарным относятся:
    • звуки [ж], [ц], [ш] — всегда твердые (жизнь, цикл, мышь);
    • [ч’], [щ’] и [й’] — всегда мягкие (дочка, чаще, твоей).
  • Звуки [ж], [ч’], [ш], [щ’] в нашем языке называются шипящими.

Согласный может быть звонким — глухим, а так же сонорным и шумным.

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

  • Сонорные (л, м, н, р, й) — самые звонкие фонемы, в них слышится максимум голоса и немного шумов: лев, рай, ноль.
  • Если при произношении слова во время звуко разбора образуется и голос, и шум — значит перед вами звонкий согласный (г, б, з и тд.): завод, блюдо, жизнь.
  • При произнесении глухих согласных (п, с, т и прочих) голосовые связки не напрягаются, издаётся только шум: стопка, фишка, костюм, цирк, зашить.

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

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

Подсказка: Для ассоциативной связи запомните фразы: «Ой, мы же не забывали друга.» — в данном предложении содержится абсолютно весь комплект звонких согласных (без учета пар мягкость-твердость). «Степка, хочешь поесть щец? – Фи!» — аналогично, указанные реплики содержат набор всех глухих согласных.

Позиционные изменения согласных звуков в русском языке

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

Позиционное оглушение/озвончение

В определённом положении для согласных действует фонетический закон ассимиляции по глухости-звонкости. Звонкий парный согласный сменяется на глухой:

  • в абсолютном конце фонетического слова: но ж [но´ш], снег [с’н’э´к], огород [агаро´т], клуб [клу´п];
  • перед глухими согласными: незабудка [н’изабу´тка], обхватить [апхват’и´т’], вторник [фто´рн’ик], трубка [трупка].
  • делая звуко буквенный разбор онлайн, вы заметите, что глухой парный согласный, стоящий перед звонким (кроме [й’], [в] — [в’], [л] — [л’], [м] — [м’], [н] — [н’], [р] — [р’]) тоже озвончается, то есть заменяется на свою звонкую пару: сдача [зда´ч’а], косьба [каз’ба´], молотьба [малад’ба´], просьба [про´з’ба], отгадать [адгада´т’].

В русской фонетике глухой шумный согласный не сочетается с последующим звонким шумным, кроме звуков [в] — [в’]: взбитыми сливками. В данном случае одинаково допустима транскрипция как фонемы [з], так и [с].

При разборе по звукам слов: итого, сегодня, сегодняшний и тп, буква «Г» замещается на фонему [в].

По правилам звуко буквенного анализа в окончаниях «-ого», «-его» имён прилагательных, причастий и местоимений согласный «Г» транскрибируется как звук [в]: красного [кра´снава], синего [с’и´н’ива], белого [б’э´лава], острого, полного, прежнего, того, этого, кого.
Если после ассимиляции образуются два однотипных согласных, происходит их слияние. В школьной программе по фонетике этот процесс называется стяжение согласных: отделить [ад:’ил’и´т’] → буквы «Т» и «Д» редуцируются в звуки [д’д’], бесшумный [б’иш:у´мный].
При разборе по составу у ряда слов в звукобуквенном анализе наблюдается диссимиляция — процесс обратный уподоблению. В этом случае изменяется общий признак у двух стоящих рядом согласных: сочетание «ГК» звучит как [хк] (вместо стандартного [кк]): лёгкий [л’о′х’к’ий], мягкий [м’а′х’к’ий].

Мягкие согласные в русском языке

В схеме фонетического разбора для обозначения мягкости согласных используется апостроф [’].

  • Смягчение парных твердых согласных происходит перед «Ь»;
  • мягкость согласного звука в слоге на письме поможет определить последующая за ним гласная буква (е, ё, и, ю, я);
  • [щ’], [ч’] и [й] по умолчанию только мягкие;
  • всегда смягчается звук [н] перед мягкими согласными «З», «С», «Д», «Т»: претензия [пр’итэн’з’ийа], рецензия [р’ицеэн’з’ийа], пенсия [пэн’с’ийа], ве[н’з’]ель, лице́[н’з’]ия, ка[н’д’]идат, ба[н’д’]ит, и[н’д’]ивид, бло[н’д’]ин, стипе[н’д’]ия, ба[н’т’]ик, ви[н’т’]ик, зо[н’т’]ик, ве[н’т’]илъ, а[н’т’]ичный, ко[н’т’]екст, ремо[н’т’]ировать;
  • буквы «Н», «К», «Р» при фонетических разборах по составу могут смягчаться перед мягкими звуками [ч’], [щ’]: стаканчик [стака′н’ч’ик], сменщик [см’э′н’щ’ик], пончик [по′н’ч’ик], каменщик [кам’э′н’щ’ик], бульварщина [бул’ва′р’щ’ина], борщ [бо′р’щ’];
  • часто звуки [з], [с], [р], [н] перед мягким согласным претерпевают ассимиляцию по твердости-мягкости: стенка [с’т’э′нка], жизнь [жыз’н’], здесь [з’д’эс’];
  • чтобы корректно выполнить звуко буквенный разбор, учитывайте слова исключения, когда согласный [р] перед мягкими зубными и губными, а так же перед [ч’], [щ’] произносится твердо: артель, кормить, корнет, самоварчик;

Примечание: буква «Ь» после согласного непарного по твердости/мягкости в некоторых словоформах выполняет только грамматическую функцию и не накладывает фонетическую нагрузку: учиться, ночь, мышь, рожь и тд. В таких словах при буквенном анализе в квадратных скобках напротив буквы «Ь» ставится [-] прочерк.

Позиционные изменения парных звонких-глухих перед шипящими согласными и их транскрипция при звукобуквенном разборе

Чтобы определить количество звуков в слове необходимо учитывать их позиционные изменения. Парные звонкие-глухие: [д-т] или [з-с] перед шипящими (ж, ш, щ, ч) фонетически заменяются шипящим согласным.

  • Буквенный разбор и примеры слов с шипящими звуками: приезжий [пр’ийэ´жжий], восшествие [вашшэ´ств’ийэ], изжелта [и´жжэлта], сжалиться [жжа´л’иц:а].

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

  • Буквосочетания с шипящим «сж» – «зж», произносятся как двойной твердый согласный [ж:], а «сш» – «зш» — как [ш:]: сжали, сшить, без шины, влезший.
  • Сочетания «зж», «жж» внутри корня при звукобуквенном разборе записывается в транскрипции как долгий согласный [ж:]: езжу, визжу, позже, вожжи, дрожжи, жженка.
  • Сочетания «сч», «зч» на стыке корня и суффикса/приставки произносятся как долгий мягкий [щ’:]: счет [щ’:о´т], переписчик, заказчик.
  • На стыке предлога со следующим словом на месте «сч», «зч» транскрибируется как [щ’ч’]: без числа [б’эщ’ ч’исла´], с чем-то [щ’ч’э′мта].
  • При звуко буквенном разборе сочетания «тч», «дч» на стыке морфем определяют как двойной мягкий [ч’:]: лётчик [л’о´ч’:ик], молодчик [мало´ч’:ик], отчёт [ач’:о´т].

Шпаргалка по уподоблению согласных звуков по месту образования

  • сч → [щ’:]: счастье [щ’:а´с’т’йэ], песчаник [п’ищ’:а´н’ик], разносчик [разно´щ’:ик], брусчатый, расчёты, исчерпать, расчистить;
  • зч → [щ’:]: резчик [р’э´щ’:ик], грузчик [гру´щ’:ик], рассказчик [раска´щ’:ик];
  • жч → [щ’:]: перебежчик [п’ир’ибе´ щ’:ик], мужчина [мущ’:и´на];
  • шч → [щ’:]: веснушчатый [в’исну′щ’:итый];
  • стч → [щ’:]: жёстче [жо´щ’:э], хлёстче, оснастчик;
  • здч → [щ’:]: объездчик [абйэ´щ’:ик], бороздчатый [баро´щ’:итый];
  • сщ → [щ’:]: расщепить [ращ’:ип’и′т’], расщедрился [ращ’:э′др’илс’а];
  • тщ → [ч’щ’]: отщепить [ач’щ’ип’и′т’], отщёлкивать [ач’щ’о´лк’иват’], тщетно [ч’щ’этна], тщательно [ч’щ’ат’эл’на];
  • тч → [ч’:]: отчет [ач’:о′т], отчизна [ач’:и′зна], реснитчатый [р’ис’н’и′ч’:и′тый];
  • дч → [ч’:]: подчёркивать [пач’:о′рк’иват’], падчерица [пач’:ир’ица];
  • сж → [ж:]: сжать [ж:а´т’];
  • зж → [ж:]: изжить [иж:ы´т’], розжиг [ро´ж:ык], уезжать [уйиж:а´т’];
  • сш → [ш:]: принёсший [пр’ин’о′ш:ый], расшитый [раш:ы´тый];
  • зш → [ш:]: низший [н’иш:ы′й]
  • чт → [шт], в словоформах с «что» и его производными, делая звуко буквенный анализ, пишем [шт]: чтобы [што′бы], не за что [н’э′ зашта], что-нибудь [што н’ибут’], кое-что;
  • чт → [ч’т] в остальных случаях буквенного разбора: мечтатель [м’ич’та´т’ил’], почта [по´ч’та], предпочтение [пр’итпач’т’э´н’ийэ] и тп;
  • чн → [шн] в словах-исключениях: конечно [кан’э´шна′], скучно [ску´шна′], булочная, прачечная, яичница, пустячный, скворечник, девичник, горчичник, тряпочный, а так же в женских отчествах, оканчивающихся на «-ична»: Ильинична, Никитична, Кузьминична и т. п.;
  • чн → [ч’н] — буквенный анализ для всех остальных вариантов: сказочный [ска´зач’ный], дачный [да´ч’ный], земляничный [з’им’л’ин’и´ч’ный], очнуться, облачный, солнечный и пр.;
  • !жд → на месте буквенного сочетания «жд» допустимо двоякое произношение и транскрипция [щ’] либо [шт’] в слове дождь и в образованных от него словоформах: дождливый, дождевой.

Непроизносимые согласные звуки в словах русского языка

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

В русской фонетике к числу непроизносимых согласных относятся:

  • «Т» — в сочетаниях:
    • стн → [сн]: местный [м’э´сный], тростник [трас’н’и´к]. По аналогии можно выполнить фонетический разбор слов лестница, честный, известный, радостный, грустный, участник, вестник, ненастный, яростный и прочих;
    • стл → [сл]: счастливый [щ’:асл’и´вый’], счастливчик, совестливый, хвастливый (слова-исключения: костлявый и постлать, в них буква «Т» произносится);
    • нтск → [нск]: гигантский [г’ига´нск’ий], агентский, президентский;
    • стьс → [с:]: шестьсот [шэс:о´т], взъесться [взйэ´с:а], клясться [кл’а´с:а];
    • стс → [с:]: туристский [тур’и´с:к’ий], максималистский [макс’имал’и´с:к’ий], расистский [рас’и´с:к’ий], бестселлер, пропагандистский, экспрессионистский, индуистский, карьеристский;
    • нтг → [нг]: рентген [р’энг’э´н];
    • «–тся», «–ться» → [ц:] в глагольных окончаниях: улыбаться [улыба´ц:а], мыться [мы´ц:а], смотрится, сгодится, поклониться, бриться, годится;
    • тс → [ц] у прилагательных в сочетаниях на стыке корня и суффикса: детский [д’э´цк’ий], братский [бра´цкий];
    • тс → [ц:] / [цс]: спортсмен [спарц:м’э´н], отсылать [ацсыла´т’];
    • тц → [ц:] на стыке морфем при фонетическом разборе онлайн записывается как долгий «цц»: братца [бра´ц:а], отцепить [ац:ып’и´т’], к отцу [к ац:у´];
  • «Д» — при разборе по звукам в следующих буквосочетаниях:
    • здн → [зн]: поздний [по´з’н’ий], звёздный [з’в’о´зный], праздник [пра′з’н’ик], безвозмездный [б’извазм’э′зный];
    • ндш → [нш]: мундштук [муншту´к], ландшафт [ланша´фт];
    • ндск → [нск]: голландский [гала´нск’ий], таиландский [таила´нск’ий], нормандский [нарма´нск’ий];
    • здц → [сц]: под уздцы [пад усцы´];
    • ндц → [нц]: голландцы [гала´нцы];
    • рдц → [рц]: сердце [с’э´рцэ], сердцевина [с’ирцыв’и´на];
    • рдч → [рч’]: сердчишко [с’эрч’и´шка];
    • дц → [ц:] на стыке морфем, реже в корнях, произносятся и при звуко разборе слова записывается как двойной [ц]: подцепить [пац:ып’и´т’], двадцать [два´ц:ыт’];
    • дс → [ц]: заводской [завацко´й], родство [рацтво´], средство [ср’э´цтва], Кисловодск [к’иславо´цк];
  • «Л» — в сочетаниях:
    • лнц → [нц]: солнце [со´нцэ], солнцестояние;
  • «В» — в сочетаниях:
    • вств → [ств] буквенный разбор слов: здравствуйте [здра´ствуйт’э], чувство [ч’у´ства], чувственность [ч’у´ств’инас’т’], баловство [баластво´], девственный [д’э´ств’ин:ый].

Примечание: В некоторых словах русского языка при скоплении согласных звуков «стк», «нтк», «здк», «ндк» выпадение фонемы [т] не допускается: поездка [пайэ´стка], невестка, машинистка, повестка, лаборантка, студентка, пациентка, громоздкий, ирландка, шотландка.

  • Две идентичные буквы сразу после ударного гласного при буквенном разборе транскрибируется как одиночный звук и символ долготы [:]: класс, ванна, масса, группа, программа.
  • Удвоенные согласные в предударных слогах обозначаются в транскрипции и произносится как один звук: тоннель [танэ´л’], терраса, аппарат.

Если вы затрудняетесь выполнить фонетический разбор слова онлайн по обозначенным правилам или у вас получился неоднозначный анализ исследуемого слова, воспользуйтесь помощью словаря-справочника. Литературные нормы орфоэпии регламентируются изданием: «Русское литературное произношение и ударение. Словарь – справочник». М. 1959 г.

Использованная литература:

  • Литневская Е.И. Русский язык: краткий теоретический курс для школьников. – МГУ, М.: 2000
  • Панов М.В. Русская фонетика. – Просвещение, М.: 1967
  • Бешенкова Е.В., Иванова О.Е. Правила русской орфографии с комментариями.
  • Учебное пособие. – «Институт повышения квалификации работников образования», Тамбов: 2012
  • Розенталь Д.Э., Джанджакова Е.В., Кабанова Н.П. Справочник по правописанию, произношению, литературному редактированию. Русское литературное произношение.– М.: ЧеРо, 1999

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

TL;DR:

  • Переложив секции кода и данных программы на большие страницы можно существенно ускорить приложение (у нас получилось до +10%) не трогая исходный код.
  • Можно быстро проверить ничего не перекомпилируя, детали здесь.
  • Финальное решение оперирует «классическими» большими страницами (не transparent huge pages), поэтому в какой-то степени его можно назвать дальнейшим развитием libhugetlbfs.

Если вы спросите у инженера как ускорить вашу программу, то ответ будет зависеть от того, в какой области он специализируется:

  • системный архитектор откроет документацию на ваш продукт и будет искать самое слабое звено (компонент — бутылочное горлышко, заменив который система должна получить второе дыхание)
  • SDE сразу попросит доступ к исходному коду, пропадет из поля зрения на пару месяцев, анализируя асимптотики используемых алгоритмов — может быть ребята где-то пропустили «квадрат» или того похуже?
  • SRE станет профилировать ключевые процессы системы и как они взаимодействуют с ядром ОС, как используется память, где и сколько потребляется: perf top / perf stat / perf record / perf report / jemalloc profiler. А может быть pidstat, vmstat, sar? strace/gdb? Если есть новое Linux ядро под рукой, то набирает бешеную популярность eBPF: bcc в руки, и вперед! На выходе список наиболее тяжелых функций, узкие места ОС (сеть, диски, память?).
  • разработчик компиляторов откроет для вас дивный новый мир генерации кода с использованием профиля выполнения: PGO / AutoFDO / BOLT. Предложит LTO для усиления эффектов этих технологий. И, о чудо, оно действительно генерирует значительно более быстрые программы, особенно сильно видно на архитектурах не x86. Применив все это добро правильно, можно серьезно улучшить производительность, не трогая исходный код вообще. Привлекательно, не правда ли?
  • hardware специалист приоткроет двери NUMA-aware архитектур. Что греха таить — мы уже очень давно используем сервера с NUMA, а все наивно верим что все процессоры одинаковые, а RAM общая. Мммм, «Random access memory» — термин остался с прошлого века, сейчас это, прямо скажем, обман. Набор L1/L2/L3 + NUMA + RAM — чем дальше от процессора, выполняющего Ваш код, тем все дольше доступ, тем сложнее синхронизация. Забудьте о гигабайтах памяти, если Вам нужна производительность, представьте, что ваша память простая, предсказуемая, с последовательным доступом, эксклюзивная для потока, и её не так уж и много (пара мегабайт?). Вряд ли сходу вы сможете все это применить для своего продукта, но попытаться все же стоит.
  • разработчик операционных систем, глубоко вздохнув, расскажет о бремени обратной совместимости и петабайтах уже написанных, отлаженных и работающих как часы приложений, а потом Вашему взору откроются новые API асинхронного доступа к современным дискам (libaio, io-uring), ориентированные на облака планировщики задач (linux kernel >= 4) и оптимизации технологии виртуального адресного пространства.

Спектр доступных инструментов и технологий довольно велик, сегодня я расскажу про опыт применения больших страничек в лаборатории баз данных Huawei на примере MySQL сервера: здесь описывается попытка оптимизировать доступ к виртуальному адресному пространству и как с её помощью улучшить утилизацию процессорного времени.

Рассказа про технологию виртуальной памяти, как это сделано внутри Linux, и что такое MMU и TLB, здесь не будет. Есть огромное количество официальных статей, а также зарекомендовавших себя полезных книжных изданий, где это детально описывается. Что-то подзабыли — освежите в Вашей любимой настольной книге по операционным системам.

Разумеется, технология больших страниц не нова (сколько десятилетий прошло с момента выхода Linux 2.6.16?), но почему-то есть не так много программных продуктов, которые дейтвительно используют большие странички хоть как-то. Например, в MySQL большие страницы можно подключить только для внутреннего кеша страниц B-дерева («innodb_buffer_pool»), причем Oracle предлагает это делать через довольно устаревший SystemV shared memory механизм, а ОС требуется дополнительная специфическая конфигурация.

А где же используют большие странички для собственно кода и данных приложения? .text/.data/.bss располагаются в стандартном маппинге в адресном пространстве процесса, его тоже можно положить на большие страницы. Если кода сгенерировано много, обращение к сегменту кода выполняется довольно часто, производительность также страдает от iTLB/dTLB кеш-промахов. Думаю, можно пересчитать по пальцам, где такой подход применяется, хотя попытки появляются с завидной регулярностью (что несомненно радует):

  • libhugetlbfs: ‘remap_segments’ function
  • Google: ‘RemapHugetlbText*’ functions
  • Facebook: ‘HugifyText’ function
  • Intel: ‘MoveRegionToLargePages’ function

И тем не менее, все вендоры едины в своих отчетах: приложения становятся быстрее, если код и данные положить на большие страницы. Наша команда решила детально изучить сей вопрос и убедиться в правильности данного суждения.

Теория гласит: чем больше страница виртуального адресного пространства, тем большее адресное пространство может быть адресовано с помощью фиксированного набора записей, помещающихся в TLB буфер процессора. Как только количество записей превышает TLB буфер, появляются дополнительные накладные расходы на трансляцию виртуального адреса в физический. Кстати, TLB буферов может быть несколько, например, L1 и L2. В этой статье презентован бенчмарк, показывающий влияние первого и второго уровня TLB с привязкой к спецификации испытуемого процессора. Кроме того, разные архитектуры поддерживают разный набор больших страниц (например, x86_64: 2M, 1G; ppc64: 16М; AArch64: 64K, 2M, 512M, 16G (зависит от модели, а иногда и конфигурации ядра ОС)), поэтому выбор в каждом случае зависит от конкретных целей и задач. Для MySQL 8.0 размер сегментов кода и данных, запакованных в ELF формат, составляет около 120-140М, кроме того в Huawei Cloud мы поддерживаем только 2 архитектуры: x86_64 и AArch64, поэтому выбор пал на стандартные 2М большие страницы.

Теперь какую технологию больших страниц выбрать? Есть 2 основных типа больших страниц в Linux:

  • classic hugepages
  • transparent hugepages

Здесь на ум приходит старый добрый Морфеус, и его синяя и красная таблетки:

morpheus

  • Синяя таблетка (transparent huge pages) — вы включаете технологию прозрачных больших страниц, сообщаете Linux ядру, какой маппинг выровнен корректно по границе большой странички ( в нашем случае 2М ) и рекомендуете его использовать. Всё. После «вы просыпаетесь в своей постели с твердой уверенностью, что все это был сон».
  • Красная таблетка (classic huge pages) — вы «копаете» дальше и «узнаете, насколько глубока кроличья нора».

«Cъесть ли синюю таблетку»? Опыт коллег по использованию THP в типовых базах данных нас сильно обеспокоил. В чем же подвох?

  • Дефрагментация физической памяти. Не замечали такой интересный процесс «khugepaged»? Да-да, именно он может притормозить вдруг ваше приложение, даже если вы никогда не планировали использовать какие-то там другие страницы, но ваш процесс останавливается, потому что его кодовый сегмент переносится в другое место физической памяти, чтобы создать побольше больших страниц для своего потребителя. Да и потребитель (к примеру, MySQL сервер) может испытывать случайные скачки TPS/latency в эти моменты времени.
  • Непредсказуемость поведения. Какова светлая мечта любого DBA? Правильно, чтобы система работала предсказуемо, понятно, быстро и просто. THP — это оптимизация работы ядра, она может работать и давать результаты, а может не работать или временно не работать, и только ядро конкретной версии знает, почему так происходит. Оценить изменение производительности — уже достаточно сложно решаемая задача. Оценить прирост от оптимизации ядра, которая срабатывает по своему заложенному алгоритму — на порядок сложнее, разве только вы специалист ядра Linux и регулярно «комитите» в ядро, но тогда вряд ли вы это читаете :)
  • Свопинг. На старых Linux ядрах, когда большая страница выгружается в файл подкачки, то она разбивается на множество стандартных страниц, когда загружается обратно — снова сливается воедино. Разумеется, этот процесс бьет по производительности системы. Классические страницы выделяются в RAM перманентно, и в swap не выгружаются. На момент написания статьи я видел патчи в ядро, которые решают этот вопрос.
  • Рост потребления памяти. Случается при неудачном динамическом выделении в коде конечного приложения, когда отдельно нужно хранить данных пару килобайт, но выделяется каждый раз для этого одна полная страничка памяти (например, 2М). Знаю, что данный симптом присущ и классическим большим страничкам, но прямого контроля над THP программист не имеет. Согласен, пунктик спорный, однако в статьях упоминается регулярно, поэтому решил его также добавить.

Надо все же признать, что разработчики ядра Linux активно улучшают эту технологию, и в ближайшем будущем ситуация может кардинальным образом измениться (возможно, будущее уже наступило). Недаром такие техно-гиганты как Google/Facebook/Intel в своих решениях предлагают использовать THP и отдать ядру решающий голос. Увы, для нас был важен результат здесь и сейчас, и, кроме того, процесс принятия на вооружение новых Linux ядер в Huawei достаточно сложный, ответственный и занимает много времени.


Итак, мы «проглотили красную таблетку».

Думаю, каждая команда, которая пробовала перемапливать сегменты кода и данных на большие страницы, начинала свой путь с боевого крещения огнем, а именно с библиотеки libhugetlbfs. Сей комбайн создавался на заре внедрения технологии больших страниц в народные массы, поддерживает очень старые ядра (2.6.16) и toolchain’ы (да-да, вот эти линкерные скрипты создавались для них: libhugetlbfs/ldscripts), а также умеет работать не только под Linux, а после прочтения имплементации создается стойкое ощущение, что библиотека активно используется (или использовалась) во встраиваемых системах малой мощности с очень небольшим количеством памяти на борту. В общем, что воду лить? Прикоснуться к истории и почерпнуть мудрости можно на сайте проекта.

Разумеется, это решение взлетело не сразу, однако эффект ускорения был очевидным. MySQL сервер смог устойчиво выдавать на 10% больше TPS (transactions per second) в OLTP PS (point select) на 1vCPU инстансе (эмулятор виртуальной машины на 1 CPU с использованием Linux cgroups, x86_64). iTLB-misses упал в разы. На AArch64 платформе прирост производительности был ещё больше. Наша команда более детально изучила эффект перемапливания .text/data/bss сегментов по отдельности и всех вместе, результат можно представить одной картинкой (процессор AArch64: Huawei Kunpeng 920):

chart

Конечно же, это был «усиленный» CPU-bound бенчмарк (острая нехватка ресурсов процессора), но +10% определенно стоили того, чтобы продолжать исследование. A походу проведения тестов стали отчетливо видны следующие ограничения:

  • Включение ASLR на сервере, где работал MySQL (дефолтная сборка с PIE), приводило к SIGSEGV. Анализ выявил явный баг со стороны libhugetlbfs, и ваш покорный слуга с превеликим удовольствием сей баг зарепортил (сразу с фиксом): https://github.com/libhugetlbfs/libhugetlbfs/issues/49. Спустя год мне так же радостно ответили: «не воспроизводится», даже не взглянув на патч. Я в печали …
  • Ограничение на количество сегментов, которые можно перемапить — 3. Думаю, дело опять же в истории, раньше GNU BFD линкер генерировал только 2 ELF сегмента для загрузки динамическим линковщиком: код (r-x: чтение/выполнение) и данные (rw-: чтение/запись). Потом требование безопасности сделало его немного умнее (выделение сегмента для констант: r—), а разработчики, от греха подальше, выставили такую конфигурацию дефолтной. В итоге новый линкер создает 4 сегмента (r-x, r—, r-x, rw-: он все же недостаточно умный, чтобы сделать 3 сегмента, поэтому получаем 4), в итоге библиотека не перемапливает 1 финальный RW сегмент, который обычно является самым объемным.
  • Перемапливание финального сегмента автоматически отмапливает HEAP сегмент. Происходит это втихую, без каких-либо внешних проявлений, системный вызов brk просто перестает работать. Влияет только на стандартный аллокатор из glibc, который использует brk для аллокаций до 128К, а для всего остального — mmap; после сего несчастья glibc переключается на mmap для любых аллокаций. Доподлинно неизвестно, как это влияет на производительность приложения и системы в целом: если у вас есть идеи — делитесь в комментариях. Не влияет на jemalloc, который всю свою память выделяет через mmap.
  • Нет как таковой интеграции в целевое приложение — вся работа выполняется в конструкторе динамической библиотеки без каких-либо сообщений об ошибках. Если все плохо, приложение не стартует, а разбор полетов занимает много времени.
  • Используется специализированная файловая система hugetlbfs ядра Linux, что означает, что, как минимум, нужно примонтировать её с правильными параметрами, плюс обеспечить приложению корректные права доступа. В облаках, на виртуальных машинах, эта зависимость создает дополнительные проблемы, особенно учитывая тот факт, что начиная с Linux 2.6.32 можно сразу создать анонимный маппинг на больших страницах (системный вызов mmap). Ярмо обратной совместимости с Linux 2.6.16.
  • Приложение должно быть по-особому слинковано (конкретные флаги линкера: common-page-size=2M max-page-size=2M). Это сделано для обеспечения безопасности, поэтому не скажу, что это «ограничение» в прямом смысле слова, скорее обязательная рекомендация для финального деплоя в production, однако для тестового запуска для первоначальной оценки изменения производительности в любом случае требуется пересобрать целевое приложение — это не удобно.

Часть проблем критичные, иными словами не production-ready. Ох…

facepalm


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

Сразу оговорюсь, рассматривается вариант Linux 64-bit / программа в ELF формате / установлена glibc.

Чтобы расставить все точки над «и», стоит затронуть алгоритм запуска типового приложения в ОС Linux. Например, что скрывается за конкретным системным вызовом execve? Опять же, стоит отметить уже существующие шикарные статьи с повышенной детализацией конкретных функций и вызовов в glibc / Linux kernel. Далеко ходить не будем, здесь отслеживается каждый шаг запуска GNU утилиты ls в интерпретаторе bash.

Из этого обилия технической информации нас сейчас интересует несколько моментов:

  • Вызов execve для исполняемого ELF файла приводит к вызову load_elf_binary в fs/binfmt_elf.c в ядре Linux
  • load_elf_binary:
    • разбирает ELF файл, достает из него сегменты данных и кода
    • создает маппинг для кода и данных приложения, потом инициализирует heap сегмент сразу за этими маппингами
    • примапливает VDSO сегмент
    • вычитывает текущий интерпретатор для ELF файла (обычно это динамический линковщик glibc), и загружает его в память (код и данные DSO объекта)
  • Linux ядро выполняет еще некоторые служебные функции, потом всю информацию о созданных маппингах сохраняет на стеке, после передает управление динамическому линковщику glibc (или напрямую программе, если интерпретатор не указан, а программа слинкована статически)
  • Динамический линковщик:
    • инициализирует список текущих маппингов (регистрирует те, что уже созданы ядром)
    • вычитывает список DSO, от которых зависит приложение
    • выполняет поиск по системе и загрузку всех необходимых DSO (результат подключается к списку текущих маппингов)
    • выполняет конструкторы в каждом DSO, а также в основной программе
    • передает выполнение функции main основного приложения

Итого, получаем, что список маппингов нашей программы можно получить у:

  • ядра Linux,
  • библиотеки выполнения glibc,

a описание этих маппингов лежит в ELF файле.

Ядро Linux публикует маппинги приложения в /proc/$pid/smaps (детальный список) и /proc/$pid/maps (короткий список). Пример короткого списка с Ubuntu 20.04 (kernel 5.4):

$ cat /proc/self/maps
555555554000-555555556000 r--p 00000000 08:02 24117778                   /usr/bin/cat
555555556000-55555555b000 r-xp 00002000 08:02 24117778                   /usr/bin/cat
55555555b000-55555555e000 r--p 00007000 08:02 24117778                   /usr/bin/cat
55555555e000-55555555f000 r--p 00009000 08:02 24117778                   /usr/bin/cat
55555555f000-555555560000 rw-p 0000a000 08:02 24117778                   /usr/bin/cat
555555560000-555555581000 rw-p 00000000 00:00 0                          [heap]
7ffff7abc000-7ffff7ade000 rw-p 00000000 00:00 0
7ffff7ade000-7ffff7dc4000 r--p 00000000 08:02 24125924                   /usr/lib/locale/locale-archive
7ffff7dc4000-7ffff7dc6000 rw-p 00000000 00:00 0
7ffff7dc6000-7ffff7deb000 r--p 00000000 08:02 24123961                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7ffff7deb000-7ffff7f63000 r-xp 00025000 08:02 24123961                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7ffff7f63000-7ffff7fad000 r--p 0019d000 08:02 24123961                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7ffff7fad000-7ffff7fae000 ---p 001e7000 08:02 24123961                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7ffff7fae000-7ffff7fb1000 r--p 001e7000 08:02 24123961                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7ffff7fb1000-7ffff7fb4000 rw-p 001ea000 08:02 24123961                   /usr/lib/x86_64-linux-gnu/libc-2.31.so
7ffff7fb4000-7ffff7fb8000 rw-p 00000000 00:00 0
7ffff7fc9000-7ffff7fcb000 rw-p 00000000 00:00 0
7ffff7fcb000-7ffff7fce000 r--p 00000000 00:00 0                          [vvar]
7ffff7fce000-7ffff7fcf000 r-xp 00000000 00:00 0                          [vdso]
7ffff7fcf000-7ffff7fd0000 r--p 00000000 08:02 24123953                   /usr/lib/x86_64-linux-gnu/ld-2.31.so
7ffff7fd0000-7ffff7ff3000 r-xp 00001000 08:02 24123953                   /usr/lib/x86_64-linux-gnu/ld-2.31.so
7ffff7ff3000-7ffff7ffb000 r--p 00024000 08:02 24123953                   /usr/lib/x86_64-linux-gnu/ld-2.31.so
7ffff7ffc000-7ffff7ffd000 r--p 0002c000 08:02 24123953                   /usr/lib/x86_64-linux-gnu/ld-2.31.so
7ffff7ffd000-7ffff7ffe000 rw-p 0002d000 08:02 24123953                   /usr/lib/x86_64-linux-gnu/ld-2.31.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

Смотрим список программных сегментов в ELF заголовке:

$ readelf -Wl /bin/cat

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000000040 0x0000000000000040 0x0002d8 0x0002d8 R   0x8
  INTERP         0x000318 0x0000000000000318 0x0000000000000318 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x0016e0 0x0016e0 R   0x1000
  LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x004431 0x004431 R E 0x1000
  LOAD           0x007000 0x0000000000007000 0x0000000000007000 0x0021d0 0x0021d0 R   0x1000
  LOAD           0x009a90 0x000000000000aa90 0x000000000000aa90 0x000630 0x0007c8 RW  0x1000
  DYNAMIC        0x009c38 0x000000000000ac38 0x000000000000ac38 0x0001f0 0x0001f0 RW  0x8
  NOTE           0x000338 0x0000000000000338 0x0000000000000338 0x000020 0x000020 R   0x8
  NOTE           0x000358 0x0000000000000358 0x0000000000000358 0x000044 0x000044 R   0x4
  GNU_PROPERTY   0x000338 0x0000000000000338 0x0000000000000338 0x000020 0x000020 R   0x8
  GNU_EH_FRAME   0x00822c 0x000000000000822c 0x000000000000822c 0x0002bc 0x0002bc R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x009a90 0x000000000000aa90 0x000000000000aa90 0x000570 0x000570 R   0x1

DSO зависимости:

$ ldd /bin/cat
        linux-vdso.so.1 (0x00007ffff7fce000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffff7dba000)
        /lib64/ld-linux-x86-64.so.2 (0x00007ffff7fcf000)

Анализ /proc/$pid/maps:

  • libc.so.6 — это libc-2.31.so
  • ld-linux-x86-64.so.2 — это ld-2.31.so
  • linux-vdso.so.1 — это [vdso], виртуальная DSO поставляемая ядром для ускорения работы четырех (для x86_64) системных вызовов, подробнее здесь
  • [vvar] и [vsyscall] — устаревшая имплементация [vdso] (ядро держит обратную совместимость)
  • [heap] и [stack] — здесь все понятно
  • /usr/bin/cat — это как раз LOAD сегменты из результатов readelf, сдвинутые на 0x555555554000 ядром.

Кстати, можно заметить, что LOAD сегментов у нас 4, а маппингов 5. Все дело в GNU_RELRO технологии (и снова безопасность!): по этим адресам располагается PLT таблица (1 страница, 4К). Её заполняет динамический линковщик, а когда дело сделано, сбрасывает на ней право записи. Теперь, если приложение пытаются взломать путем подмены PLТ адреса какой-нибудь широко известной функции (например, printf@plt), переписать ничего не получится, ибо ядро пришлёт SIGSEGV. Проверяем адреса GNU_RELRO сегмента:

  • 0x55555555e000 — 0x55555555f000: 4K (начало/конец маппинга, одна системная 4К страница)
  • 0x555555554000 + 0xaa90 = 0x55555555ea90 («ядерный» сдвиг плюс адрес начала GNU_RELRO сегмента)
  • 0x55555555ea90 & (~(0x1000 — 1)) = 0x55555555e000 (выравниваем предыдущий результат по границе 4К страницы => получаем начало маппинга)
  • 0x55555555f000 — 0x570 = 0x55555555ea90 (от конца маппинга отнимаем размер GNU_RELRO сегмента, получаем, с поправкой на выравнивание 4К, начало маппинга)
  • Цифры сходятся, и это хорошо!

Беглая справка по выводу readelf:

  • Offset = offset in ELF file
  • VirtAddr = virtual address in application address space
  • PhysAddr = physical address (не использовал это поле, интересно когда это нужно?)
  • FileSiz = размер данных внутри ELF файла
  • MemSiz = FileSiz + (область памяти, которую нужно занулить, используется для .bss)

С точки зрения glibc получить все маппинги приложения по ходу его выполнения можно с помощью функции dl_iterate_phdr: справка и небольшая заметка — через этот интерфейс вы получите честные 4 LOAD сегмента, ровно как и в выводе readelf.


Итого, вооружившись всем вышеперечисленным, приступаем к достижению своей цели — перемапить LOAD сегменты.

Нацеливаемся на большие страницы размером 2М (не THP), используем AArch64 или X86_64.

В основу первой версии elfremapper (так я решил наречь своё создание) положим функцию remap_segments из libhugetlbfs и чтобы сделать жизнь проще, сделаем нашу библиотечку статической. Смотрим в libhugetlbfs и делаем аналогично:

  1. Загрузка текущих LOAD сегментов используя dl_iterate_phdr (спасибо тебе, glibc, за точность, пунктуальность и беспристрастность в представлении данных: никакой дополнительной магии с GNU_RELRO)
  2. Проверка: сегменты не пересекаются с поправкой на выравнивание в 2М
  3. Дополнительно выравниваем сегменты в случае, если включен ASLR (в этом случае, сегменты имеют сдвиг 0x555555554000 и дополнительный рандомный сдвиг, который генерируется ядром каждый раз при запуске приложения — и эти сдвиги, разумеется, выравниваются ядром по границе 4К)
  4. Выделяем большие странички, используя специальную файловую систему hugetlbfs (для каждого нашего маппинга кода и данных — свою копию, доступ MAP_PRIVATE)
  5. Копируем туда все наши маппинги по очереди: открыли файл на hugetlbfs, сделали mmap, получили виртуальный базовый адрес от ядра, скопировали, сделали munmap.
  6. Оставляем файловые дескрипторы открытыми для последующих операций.
  7. Проверочка — данные действительно скопировались? Мапим первый же файловый дескриптор от hugetlbfs, куда только что переносили данные — и — там пусто!

Что ж, читаем более детально реализацию libhugetlbfs, смотрим в документацию ядра, и приходим к выводу, что MAP_PRIVATE маппинг, созданный с помощью hugetlbfs, теряется после вызова munmap (он же PRIVATE!), при этом неважно, в каком состоянии остался соответствующий файловый дескриптор. Выдержка из man mmap:

MAP_PRIVATE     Create a private copy-on-write mapping. Updates to the mapping are not visible to other processes mapping the same file, and are not carried through to the underlying file. It is unspecified whether changes made to the file after the mmap() call are visible in the mapped region.

А libhugetlbfs использует MAP_SHARED! Хорошо, скрепя сердце, делаем маппинги MAP_SHARED, открытые файлы тут же удаляем при помощи unlink из файловой системы. Продолжаем:

  • Проверка: данные действительно скопировались, держим открытыми файловые дескрипторы (файлы-то мы удалили!)
  • Отмапливаем наши текущие маппинги кода и данных — и — получаем SIGSEGV на следующей за munmap строчке кода.

Как так??? libhugetlbfs делает munmap и не падает, а у нас так же не работает… Думаем. Думаем. Ещё раз думаем.

Когда выполняется код, он зачитывается CPU из ровно такого же маппинга, как и все остальные. Единственное отличие — этот маппинг имеет флаг права выполнения. Получается, как только мы отмапили сегмент кода, который выполняем, чтение следующей ассемблерной инструкции привело к обращению к адресному пространству, которое не принадлежит нашему процессу, и вполне резонно мы получаем SIGSEGV. Почему же не падает libhugetlbfs? Дело в том, что это DSO и, естественно, имеет свой отдельный маппинг, который остается нетронутым — мы перемапливаем только LOAD сегменты основного процесса.

Что делать? Ещё раз думаем… Читаем man mmap:

MAP_FIXED     Don't interpret addr as a hint: place the mapping at exactly that address. addr must be suitably aligned: for most architectures a multiple of the page size is sufficient; however, some architectures may impose additional restrictions. If the memory region specified by addr and len overlaps pages of any existing mapping(s), then the overlapped part of the existing mapping(s) will be discarded. If the specified address cannot be used, mmap() will fail.

Так-так, значит, если мы сделаем MAP_FIXED на существующий маппинг, то ядро само его отмапит. Интересно! Что если зайти в системный вызов mmap со старого маппинга, а выйти на новом маппинге? Если виртуальные адреса останутся прежними, тогда ничего не должно измениться. Проверяем:

  • Не отмапливаем текущие маппинги кода и данных, берем открытые файловые дескрипторы (указывают на hugetlbfs) и делаем MAP_SHARED + MAP_FIXED маппинг поверх существующих. Работает!
  • Проверяем /proc/$pid/maps — вместо имени нашего приложения напротив LOAD сегментов мы видим наши файлики, созданные в hugetlbfs, например, /dev/hugepages/g4PcpN (deleted) (точка монтирования /dev/hugepages, файлики создавались с помощью mktemp)

Справочка: монтирование hugetlbfs (если не подмонтировано) и выделение страничек статически:

$ mkdir /dev/hugepages
$ mount -t hugetlbfs -o pagesize=2M none /dev/hugepages
$ sudo bash -c "echo 100 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages"

Суммируем:

  • Это подход, при котором перемапливающий код слинкован статически (перемапливает сам себя)
  • Мы использовали MAP_SHARED для сегментов кода и данных. «Будут последствия» — вероятно, подумали вы, и вы правы!
  • Проверяем сколько страниц реально потребляется — оказывается, что цифры здесь сходятся один в один, сколько нужно было страниц (например, 67), ровно столько страниц будет задействовано системой (nr_hugepagesfree_hugepages). Это очень важный пункт, так как в случае, если нам не хватит больших страниц, нужно аккуратно сообщить об ошибке, и в общем случае переключиться на использование обычных — т.е. вернуть все как было на место.

Прописываем алгоритм с учётом обработки out of memory (нехватки больших страниц):

  1. открываем файловый дескриптор на hugetlbfs;
  2. выделяем «большую» память с помощью mmap (передаем файловый дескриптор);
  3. здесь проверяем успешен ли mmap, если нет, сообщаем об ошибке, возвращаем все на место;
  4. копируем наш рабочий сегмент в выделенную память;
  5. отмапливаем «большую» память, оставляем открытым файловый дескриптор;
  6. делаем финальный mmap (fixed|shared) поверх существующего рабочего маппинга;
  7. этот системный вызов никогда не падает из-за нехватки памяти, так как маппинг shared (нет необходимости делать резервирование страниц в ядре), а вся «большая» память уже выделена на шаге 2 и проверена на корректность на шаге 3.

Чем чревато MAP_SHARED под маппингом кода/данных?

  1. Перестаёт работать fork. Нет, он работает корректно, но не копирует shared маппинги между потомком и родителем (что логично), это в свою очередь приводит к хаотичным непредсказуемым ошибкам в связи с гонками при доступе к одной и той же памяти из потомка и родителя.
  2. Перестают работать новые версии gdb: gdb attach, корректная загрузка core файлов. При этом старые версии работают штатно, что интересно, но дальше наша команда в эту сторону не копала.

Есть ещё одна глобальная проблема, на которой стоит остановиться отдельно: perf перестает резолвить символы. В итоге perf top/perf record отображают россыпь неагрегированных друг с другом адресов. Увы и ах, perf использует для загрузки символов ELF файлы, указанные в том же самом файлике /proc/$pid/maps, который изменился. К счастью, с этой напастью можно бороться штатными средствами утилиты perf. В своё время, когда на свет появились JIT-компиляторы ( например, в таких популярных языках как Java или Python), в perf появился интерфейс для JIT кода: если утилита не может загрузить символы, она пытается загрузить их из файла /tmp/perf-$pid.map, который имеет предельно простой сsv формат (3 колонки: адрес начала, длина, имя символа). Итого, данная проблема закрывается так:

  • компилируем наше приложение с дебаг-символами
  • генерируем файлик с символами, используя утилиту nm:
    $ nm --numeric-sort --print-size --demangle $app | awk '$4{print $1" "$2" "$4}' | grep -Ee"^0" > /tmp/perf-$pid.map

Как сделать текущее решение лучше? Заглядываем в libhugetlbfs, там финальный mmap выполняется с флажком MAP_PRIVATE|MAP_FIXED (пункт 6 алгоритма). Хорошо, пробуем, радуемся (fork/gdb в строю!), выкладываем в среду предрелизного нагрузочного тестирования, и спустя 3 недели работы продукт падает с SIGSEGV и нечитаемой полупустой «коркой».

Детальный анализ:

  • MAP_PRIVATE приводит к двойному потреблению больших страниц. В момент финального mmap ядро копирует все shared страницы: это логично, срабатывает copy-on-write + reservation. Как минимум, есть пик двойного потребления памяти в процессе работы алгоритма, хотя в моём случае память не вернулась в систему даже после закрытия всех файловых дескрипторов на hugetlbfs.
  • Вторая волна выделения памяти приходится на финальный mmap, и если в этот момент большие страницы заканчиваются, mmap падает, и не просто падает, а с крайне неприятным сайд-эффектом: ядро отмапливает все перекрывающиеся сегменты, и если случается ошибка (нет памяти), то на место маппинги не возвращаются. Наблюдаем аналогичную munmap ситуацию — секция с кодом покидает адресное пространство процесса — и здравствуй, SIGSEGV!

Думаем! Думаем! Усиленно думаем!

libhugetlbfs данную ситуацию никак не обрабатывает — если все плохо, приложение завершается сигналом SIGABORT. Продукты Google/Facebook/Intel используют THP, но при этом активно пользуют mremap. Что если использовать его для больших страниц? Выделить private маппинг, но не отмапливать его, а просто перенести в адресном пространстве в другую область памяти, как раз на рабочие виртуальные адреса кода и данных.

Интересно, пробуем — и — получаем ошибку MAP_FAILED (EINVAL). Почему?

Оказалось, если проследить системный вызов mremap в исходном коде ядра Linux, то окажется, что Linux до сих пор не поддерживает перемещение адресных блоков на больших страницах (https://github.com/torvalds/linux/blob/master/mm/mremap.c):

if (is_vm_hugetlb_page(vma))
  return ERR_PTR(-EINVAL);

Багфикс — откатываемся на shared маппинг. Грусть-тоска меня съедает…

И все же я хочу сделать решение лучше! Как? Вероятно, исходный постулат в виде «статическая линковка делает жизнь лучше» в данном конкретном случае не работает от слова совсем, скорее наоборот. Хорошо, создаем свою DSO!

Можно сбросить оковы, вздохнуть полной грудью и расправить крылья — теперь можно делать несколько системных вызовов и корректно обрабатывать коды возврата, а ещё можно отказаться от hugetlbfs. Если вы заметили, в первом подходе нужно было за один системный вызов подменить маппинг под кодом, который выполняется, иначе — SIGSEGV. И чтобы этого достичь с использованием mmap нужно передать и новые адреса, и указать на уже подготовленный блок памяти на больших страницах, т.е нужен файловый дескриптор на hugetlbfs (ну или сделать себе новый syscall, перекомпилить ядро, разлить по продакшн машинам, пройти security review… в общем, вы поняли).

Алгоритм меняем на следующий:

  1. Делаем анонимный 4K маппинг ровно с одной целью — заставить ядро найти в адресном пространстве процесса место для текущих рабочих маппингов кода и данных.
  2. Переносим (mremap) текущие рабочие маппинги в только что выделенное адресное пространство (случается перекрытие адресов => только что выделенный маппинг теряется без единого page fault). Так как код, который это делает, находится в DSO и имеет свой выделенный маппинг (который мы не трогаем), то SIGSEGV не случается.
  3. Выделяем на старых рабочих виртуальных адресах новый маппинг на больших страницах (mmap private + fixed + huge2m), по факту, это место сейчас вакантно.
  4. Если на этом этапе заканчивается память — возвращаем старые маппинги (которые мы утащили в пункте 2 в сторону) на старое место, если все хорошо — продолжаем.
  5. Копируем все бинарные данные из старых маппингов в новые.
  6. Отмапливаем старые маппинги — возвращаем 4К память системе.

Как видно, DSO явно меняет мир к лучшему. Какие же подводные камни ожидают нас в этом светлом и радужном месте?

  • Нужно заранее заполнить GOT/PLT таблицы, иначе вернется старый, добрый и всеми крайне любимый SIGSEGV. Дело в том, что по умолчанию динамический линковщик работает в ленивом режиме, а именно резолвит имена внешних DSO функций в адреса только по мере их использования. Эти таблицы хранятся в LOAD сегментах (помните историю с GNU_RELRO?). Наша DSO также использует спектр libc функций (mmap/mremap/memcpy), таблицы PLT/GOT этих функций лежат в LOAD сегменте нашего DSO, если резолвинг еще не выполнялся, запускается динамический линковщик. Если LOAD сегментов основного приложения нет на фиксированных виртуальных адресах, линковщик в ходе своей работы получает «access violation». Честно говоря, не копал, чего конкретно не хватило: heap живет отдельно (где хранится метаинформация линковщика), LOAD сегмент моего DSO живет также отдельно (не перемапливается), однако, как говорится, факт остается фактом. Данная проблема решается достаточно просто: добавляем флаг компиляции -Wl,-znow, что заставляет динамический линковщик быть более расторопным и сделать все необходимые расчеты на старте приложения (до входа в main).
  • Если в ходе работы fork память заканчивается, процесс получает SIGBUS. Да, мы сделали честный private маппинг, и fork его корректно копирует, дальше происходит copy-on-write, ядро пытается найти свободную большую страницу, и если этого сделать не получается, посылает SIGBUS. Что ж, это лучше, чем получить неопределенное поведение и повреждение данных, но все же хочется плавно переключиться на обычные страницы. Признаюсь, мы не писали обработчик для SIGBUS, чтобы в нем выполнить обратное перемапливание на 4К в потомке, скопировав данные родителя. На этом месте запал иссяк, и я просто сдвинул код перемапливания после вызова fork. Припомнился THP — у этой технологии есть положительные стороны, в частности, данный кейс, согласно беглому поиску, должен обрабатываться корректно, хотя как он реально обрабатывается на практике — ни разу не видел. Если знаете, расскажите.

Как известно, для каждой NUMA ноды большие страницы выделяются отдельно. Не верите?

$ echo /sys/devices/system/node/node*/hugepages/hugepages-2048kB

Наше Linux ядро в случае с NUMA и виртуальными машинами ведет себя хитро и жестоко. Виртуальная машина обычно ограничена внутри одной NUMA ноды (/sys/fs/cgroup/cpuset/$vm/cpuset.mems). Когда выполняется системный вызов mmap, то он анализирует доступные страницы на всех NUMA нодах, если памяти суммарно хватает, вызов завершается успешно. Потом случается page fault, ядро начинает искать большие странички на текущей NUMA ноде, не находит свободных и посылает процессу SIGBUS. В сумме, память как бы есть, но на самом деле её нет!

Чтобы побороть подобные всплески потребления больших страниц, мы пришли к следующей схеме:

  • Прикидываем, сколько может быть виртуальных машин в среднем на NUMA ноде и сколько страниц можно безболезненно выделить — выделяем статически
  • Остальное оформляем через overcommit с большим запасом (скажем, 10Гб):
    echo 5120 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_overcommit_hugepages

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

Помните, когда я перечислял недостатки libhugetlbfs, я рассказал, что библиотека отмапливает HEAP сегмент от адресного пространства приложения. Сейчас расскажу, почему это происходит.

Когда мы инструктируем линковщик выровнять LOAD сегменты внутри ELF файла по границе 2M, то этот процесс никак не затрагивает HEAP. Все корректно, HEAP создается ядром при старте приложения, и выравнивается по границе в 4К. Получается, что «куча» вплотную «приклеена» к последнему LOAD сегменту. Когда мы перемапливаем последний LOAD сегмент, мы выравниваем его конец по 2М, и, разумеется, это перекрывается с «кучей». Дальше мы копируем только данные LOAD сегмента, а про «кучу» никто не вспоминает. Кроме того, перемапливание обычно делается в начале работы приложения, то есть «куча» ещё маленькая, поэтому часто случается, что вся она умещается в «хвосте» последнего LOAD сегмента. Итог печальный:

  • потеря данных, которые были сохранены на куче;
  • потеря самого HEAP сегмента — так как он часто целиком перекрывается LOAD сегментом, то полностью отмапливается, после этого brk перестает выделять память.

Почему ядро Linux радикально отмапливает HEAP сегмент, если на него сверху кладется большая страница, покрывающая «кучу» целиком — вопрос открытый. Если знаете, просветите!

Решить эту проблему получилось достаточно просто:

  • адреса «кучи» зачитываются из /proc/$pid/maps, далее, если она перекрывается с последним LOAD сегментом, её данные также копируются в новый маппинг по старым виртуальным адресам;
  • если «куча» целиком попадает в «хвост» последнего сегмента, она искусственно увеличивается на размер 2М, то есть после перекрытия адресов часть HEAP’a все же остается нетронутой, экспериментально доказано, что в этом случае brk продолжает работу корректно, системный аллокатор из glibc тоже. Что будет, если системный аллокатор освободит всю выделенную память (включая ту, которая была перемаплена на большие страницы) — неизвестно. Предполагаю, что brk возвращает ошибку, когда аллокатор пробует это сделать, и эта ошибка обрабатывается корректно, ибо «крашей», связанных с этой проблемой, я пока не видел.

Если вы используете аллокатор памяти, получающий память через mmap (anonymous), например, jemalloc, то эта проблема вас не коснется.

Также, если включить ASLR, то ядро генерирует рандомно сдвинутый стартовый адрес для «кучи», обычно достаточно далеко от LOAD сегментов (>2M), поэтому это как раз тот редкий случай, когда ASLR не добавляет, а, наоборот, устраняет проблемы.

Много слов уже сказано о том, как и что мы делали, чтобы получить стабильно работающее приложение, а также упомянуто увеличение TPS в OLTP тестах. Однако увидеть воочию на реальном железе эффект применения больших страниц лучше всего с использованием perf. Дело в том, что узких мест в конкретной программе может быть много, и применение нашего опыта для вашего проекта может не дать вообще никаких результатов. Тем не менее, perf обязательно покажет, как изменилась картина для процессора.

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

Конструируем из таблички запрос на снятие метрик (скажем, за 30 секунд):

$ perf stat -e cycles -e cpu/event=0x08,umask=0x10,name=dwalkcycles/ -e cpu/event=0x85,umask=0x10,name=iwalkcycles/ -e cpu/event=0x08,umask=0x01,name=dwalkmiss/ -e cpu/event=0x85,umask=0x01,name=iwalkmiss/ -e cpu/event=0xbc,umask=0x18,name=dmemloads/ -e cpu/event=0xbc,umask=0x28,name=imemloads/ -p $app_pid sleep 30

Берем sysbench для генерации синтетической OTLP нагрузки здесь. Далее, компилируем MySQL 8.0 (в нашем случае, это 8.0.21).

Запускаем сервер на NUMA0:

  • разворачиваем БД в /dev/shm (InnoDB / UTF8);
  • загружаем 10 таблиц по 1М записей (2.4 GB)
  • CPU: Intel® Xeon® Gold 6151 CPU @ 3.00GHz, no boost/turbo
  • No ASLR

Детали запуска сервера MySQL

  • innodb_buffer_pool = 88G
  • innodb_buffer_pool_instances = 64
  • innodb_data_file_path=ibdata1:128M:autoextend
  • threadpool_size = 64
  • performance_schema=ON
  • performance_schema_instrument=’wait/synch/%=ON’
  • innodb_adaptive_hash_index=0
  • log-bin=mysql-bin

Далее, запускаем sysbench (OLTP PS / 128 threads) на NUMA1:

$ sysbench --threads=128 --report-interval=1 --thread-init-timeout=180 --db-driver=mysql --mysql-socket=/tmp/mysql.sock --mysql-db=sbtest --mysql-user=root --tables=10 --table-size=1000000 --rand-type=uniform --time=3600 --histogram --db-ps-mode=disable oltp_point_select run

Нагрузка CPU-bound / read-only.

Снимаем perf stats с оригинала (TPS=581K):

 3,213,429,932,057      cycles                                                        (57.15%)
   194,753,410,016      dwalkcycles                                                   (57.14%)
   139,241,762,335      iwalkcycles                                                   (57.14%)
     3,977,146,385      dwalkmiss                                                     (57.14%)
     4,969,951,701      iwalkmiss                                                     (57.14%)
        15,102,884      dmemloads                                                     (57.14%)
            30,794      imemloads                                                     (57.14%)

      30.005683086 seconds time elapsed

Теперь перемапливаем на большие страницы код и данные (TPS=641K):

 3,213,038,157,768      cycles                                                        (57.15%)
    78,822,186,791      dwalkcycles                                                   (57.15%)
    18,042,959,892      iwalkcycles                                                   (57.15%)
     1,306,771,287      dwalkmiss                                                     (57.15%)
       695,958,356      iwalkmiss                                                     (57.14%)
        18,090,550      dmemloads                                                     (57.15%)
             4,574      imemloads                                                     (57.15%)

      30.005697688 seconds time elapsed

Сравниваем:

  • iwalkcycles упал в 7.7 раза, dwalkcycles в 2.4 раза
  • iwalkmiss — 7.1 раза, dwalkmiss — 3 раза
  • TPS: +10.3%

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

Применяем PGO/LTO/BOLT к тому же коду (обучающая нагрузка — OLTP RW), запускаем те же тесты.

perf stats без больших страниц (TPS=915K):

 3,212,892,465,135      cycles                                                        (57.14%)
   175,161,815,648      dwalkcycles                                                   (57.15%)
    64,908,489,131      iwalkcycles                                                   (57.15%)
     3,579,819,559      dwalkmiss                                                     (57.15%)
     2,108,905,920      iwalkmiss                                                     (57.15%)
        21,031,821      dmemloads                                                     (57.15%)
            85,002      imemloads                                                     (57.14%)

      30.004624838 seconds time elapsed

С большими страницами под кодом и данными (TPS=952K):

 3,213,313,736,349      cycles                                                        (57.15%)
    92,547,731,364      dwalkcycles                                                   (57.15%)
    22,334,822,336      iwalkcycles                                                   (57.15%)
     1,611,692,765      dwalkmiss                                                     (57.15%)
       804,414,164      iwalkmiss                                                     (57.14%)
        25,627,581      dmemloads                                                     (57.12%)
            15,717      imemloads                                                     (57.12%)

      30.006456928 seconds time elapsed

Сравниваем:

  • iwalkcycles упал в 2.9 раза, dwalkcycles в 1.9 раза
  • iwalkmiss — 2.6 раза, dwalkmiss — 2.2 раза
  • TPS: +4%

Резюмируем: диспетчер, взлет прошел успешно, полет нормальный:

takeoff

Что ж, технология перемапливания кода и данных на большие страницы имеет право на жизнь, учитывая текущее состояние API ядра и библиотеки glibc. Однако, обмозговав всё, что здесь написано, приходишь к одной простой мысли: почему не создать маппинги сразу на больших страницах? Во всех подходах мы имели дело с уже созданным маппингом (дефолтные системные страницы), который потом, приседая и ударяя в бубен, перекладывался на другой маппинг (2M страницы).

Daniel Black из MariaDB предложил простое и элегантное решение — сделать всю эту работу сразу в динамическом загрузчике glibc. Единственная проблема — способ запуска приложения. Если запускать по-старинке, то LOAD сегменты загружаются в память ядром, а изменять ядро очень не хочется. Однако, динамический загрузчик умеет запускать приложения самостоятельно! Пробовали запускать динамический загрузчик? Да-да, по факту, это DSO, но на самом деле — универсальный солдат:

$ /lib64/ld-linux-x86-64.so.2
Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]
You have invoked `ld.so', the helper program for shared library executables.
This program usually lives in the file `/lib/ld.so', and special directives
in executable files using ELF shared libraries tell the system's program
loader to load the helper program from this file.  This helper program loads
the shared libraries needed by the program executable, prepares the program
to run, and runs it.  You may invoke this helper program directly from the
command line to load and run an ELF executable file; this is like executing
that file itself, but always uses this helper program from the file you
specified, instead of the helper program file specified in the executable
file you run.  This is mostly of use for maintainers to test new versions
of this helper program; chances are you did not intend to run this program.
...

$ /lib64/ld-linux-x86-64.so.2 /bin/echo "HELLO, WORLD"
HELLO, WORLD

Положительные моменты этого решения.

  • Не требуется писать дополнительный код в приложение.
  • Можно загружать на большие страницы не только LOAD сегменты исполняемого бинаря, но также и DSO, от которых оно зависит.
  • Загрузка на большие страницы становится динамической: один и тот же код вызывается как при старте приложения, так и при вызове dlopen.

Попытка сделать «грязный» патч на наш локальный форк glibc выявило лишь одну неприятную особенность — серьезный перерасход памяти. Дело в том, что типовые системные DSO имеют крайне маленькие LOAD сегменты. Порой, даже 4К страница для них является избыточной. Кроме того, каждая системная DSO содержит внутри себя несколько маленьких LOAD сегментов (вспоминаем про безопасность). И, честно говоря, для таких маленьких библиотек большие страницы не требуется вовсе — стандартный TLB буфер и системные 4К страницы справляются со своей задачей на ура. Поэтому для подхода с динамическим загрузчиком нужно сделать фильтр: класть на большие страницы только основную программу и, скажем, список наиболее тяжелых и активно используемых DSO.

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

Я хотел бы лично поблагодарить команду облачных СУБД в Российском исследовательском институте Huawei, которая принимала активное участие в проектировании, исследованиях и ревью.

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

Исходный код, выкованный кровью и потом, выложен в открытый доступ здесь.

  • https://wiki.debian.org/Hugepages
  • https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
  • https://www.1024cores.net/home/in-russian/ram—ne-ram-ili-cache-conscious-data-structures
  • https://medium.com/applied/applied-c-memory-latency-d05a42fe354e
  • https://yandex.ru/images
  • https://e7.pngegg.com/pngimages/908/632/png-clipart-man-wearing-black-jacket-illustration-morpheus-the-matrix-neo-red-pill-and-blue-pill-youtube-good-pills-will-play-fictional-character-film.png
  • https://alexandrnikitin.github.io/blog/transparent-hugepages-measuring-the-performance-impact/
  • https://www.percona.com/blog/2019/03/06/settling-the-myth-of-transparent-hugepages-for-databases/
  • https://bugs.mysql.com/bug.php?id=101369
  • https://jira.mariadb.org/browse/MDEV-24051
  • https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-4.html
  • https://man7.org/linux/man-pages/man7/vdso.7.html
  • https://man7.org/linux/man-pages/man3/dl_iterate_phdr.3.html
  • https://github.com/dmitriy-philimonov/elfremapper
  • https://github.com/akopytov/sysbench
  • https://i1.wp.com/freethoughtblogs.com/affinity/files/2016/06/facepalm_estatua.jpg
  • https://pbs.twimg.com/media/EroZF0DXYAIDYI4.jpg

Нужно срочно переходить на отечественное программное обеспечение, а то враг не дремлет, Билл Гейтс точит зубы на Россию и вскоре закроет нам все «форточки». Примерно такими откровениями порадовал нас на днях «гарант», впрочем, не установив никаких временных ориентиров. Видимо, ему таки доходчиво объяснили, что в нынешних реалиях это попросту невозможно.

Предыдущий раунд истерики по поводу «цифрового импортозамещения» случился в апреле сего года. Тогда Минцифра раструбила, что уже с 2022 года на все продаваемые в РФ устройства обяжут устанавливать отечественное ПО. И даже сказало какое — почту Mail.ru и прочие подобные программульки. Для того, чтобы враг не проник в наши секреты.

Тогда же глава РСПП Александр Шохин заявил, что на российском рынке НЕТ аналогов иностранного программного обеспечения. И оценил, что затраты компаний по переходу на российский софт превысят 1 трлн. руб. Минимум…

Что-то как-то не складывается. Давайте разберёмся, что у нас в стране есть, а чего нет. По-простому, на пальцах, без «птичьего» языка кнопкодавов-программеров.

Допустим, у нас есть авто. Машина ездит, колёса крутятся, мотор работает, а кондей кондит. И мы начинаем её немножко «колхозить» — в меру собственных сил и способностей. Этих самых сил и способностей мало, да и все материалы — импортные. Налепим в салоне всяких «фенечек», зачем-то соорудим своими руками (из импортных радиодеталей) зарядку для телефона вместо покупной, иконку присобачим на торпедо, и т. д. Во! Получилось очень даже скрепно и православно.

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

Именно про это и говорил Александр Шохин — человек, все всякого сомнения, очень умный и эрудированный. Его воззрения далеко не всем нравятся, но главу РСПП данный факт, судя по всему, не особо смущает. Кто-то же должен говорить правду. И его оценки стоимости перехода на российское ПО, как говорят специалисты, ещё сильно занижены. Видимо, чтобы власти совсем уж не испугались.

Ибо у нас нет НИЧЕГО. Автомобили, то есть в данном случае операционные системы, у нас все импортные. И что-то городить на их основе бесполезно. Это просто смешно.

«То, что чиновники говорят про защиту данных — полная (непечатное слово). Вот представьте: сидит шпиён, перед ним лежит открытый шифроблокнот, и он строчит на бумажке донесение. Алекс — Юстасу. А за его спиной стоит контрразведчик, он смотрит и в бумажку, и в шифроблокнот, да ещё и ржёт в голос. Вот примерно такая у нас ситуация. Всё ПО, которое мы используем для программирования, импортное, там есть „закладки“, но даже это — не главное. Нет базы — своих операционных систем. И на этом фоне всё остальное просто полная чушь», — объясняет программист одной российской компании.

Таким образом, никакой такой «защиты данных» не получится, это в принципе нереально. Какую «фенечку» не налепи на Android, Windows или MacOS, системы будут исправно поставлять информацию своим владельцам.

Для справки: компания Google (ОС Android их творение) — детище ЦРУ и АНБ, Microsoft и Apple тоже более чем тесно сотрудничают с американскими спецслужбами, всё иные крупные разработчики ПО также имеют у себя отделы, где сидят те самые «особисты». И они не только занимаются сбором и анализом информации, но и выдают задания. Сделать то или иное, дабы взять под контроль ту или иную сферу деятельности потребителей софта. Никакой «теории заговора», просто проза жизни.

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

По словам Путина, доступ к иностранным программам может быть закрыт для российских госкомпаний и они должны быть к этому готовы. Тут президент совершенно прав. Впрочем, данный факт далеко не новость, «СП» именно об этом недавно писала. И не только для госкомпаний — вообще для всех.

То, что глава государства признал проблему, конечно, хорошо. Но тут же встаёт вопрос: а что он и его команда делали последние 20 лет? Можно подумать, что вчера всё было хорошо, и вот только сегодня вдруг оказалось, что мы с голым задом. Причём по всем параметрам. В любой момент в ЦРУ или иной структуре могут щёлкнуть мышкой и всё — как говорят в Рунете, всему придёт «пушной зверек».

И ладно Рунет — да, он перестанет существовать как таковой. Сперва деинсталлируют все те программы, которые управляют хозяйством «Газпрома», электростанций, банков, нефтянки и т. д. А депутатам Госдумы придётся заново учиться писать, так как их планшеты и ноутбуки превратятся в мёртвые куски пластмассы.

Глобальной катастрофы не произойдёт — газ и электричество продолжат поступать в дома людей, хотя перебои возможны. Но наш народ умный, талантливый, специалисты найдут как обойти сдохшую электронику. Условно говоря, подключат напрямую. Простые люди так и вовсе вытащат из загашников диски с «пиратскими» программами и оживят свои компьютеры.

Вот связи не будет, это — проблема. Мобильной точно, да и с проводной возникнут проблемы. Надёжные советские АТС давно поменяли на импортную «цифру», а её тоже «отключат». В совокупности, страна будет отброшена где-то на уровень 60-х годов ХХ века, хорошо, что хоть стоящие на дежурстве советские ракеты управляются простой, но надёжной электроникой Made in USSR.

Есть ли в РФ свои собственное разработки ПО? Можно сказать, что и нет вовсе. Все те корявые поделки, что выдаются за очередные «прорывы», помимо всего прочего, созданы на базе импортных программ. Точнее, на основе так называемого «Открытого программного обеспечения» (Open-source software). Да, наверное, оно открытое. Но им ведает расположенный в Бостоне Free Software Foundation, некоммерческая организация, и всё такое. Дальнейшие объяснения нужны?

Пару лет назад прошла информация, что на базе этого «открытого ПО» российские разработчики создали отечественную операционную систему. Однако быстро выяснилось, что «Эльбрус» не является ОС для простых пользователей, а некая «внутрикорпоративная» разработка.

Наша компания ПО не занимается, но пришлось заняться и программированием — не от хорошей жизни. В подробности вдаваться не буду, их не все поймут, но ставить «Эльбрус-3» и «Эльбурс-4″ рядовым пользователям не стоит», — объяснял тогда начальник отдела проектов по развитию бизнеса АО «МЦСТ» Максим Горшенин.

Однако даже в том случае, если бы ОС и сделали, толк от неё был бы нулевым. ЦРУ-шные «особисты» из Free Software Foundation в любой момент смогут «выключить» и её.

За последние два десятилетия «вставания с колен» в плане создания действительно отечественного ПО не сделано НИЧЕГО. Огромные бюджетные деньги просто «пилили», и не более того. Всё то, что с такой помпой представляли — вроде «дырявого» портала Госуслуги» — сделано на импортных программах.

Стоит, конечно, отметить, что проблема сильно запущена. Выпуск отечественных персональных ЭВМ «Агат» прекратился в 1993 году, примерно тогда же канули в Лету все советские наработки в плане программирования. А они являлись очень передовыми — математическая наука в нашей стране всегда была на высоте.

Но до середины 90-х работы велись, существовали как отечественные ОС, так и системы управления базами данных (СУБД). Для экономики и прочих дел учёта — первейшая штука.

«Вставание с колен» никак не помогло отечественному программированию, денег на него не дали. Власти сосредоточились на защите прав интеллектуальной собственности Билла Гейтса и иже с ним, а на интересы наших компаний банально «положили». Программисты по большей части разбежались по заграницам, все наработки времён СССР были утеряны.

Сейчас, по большому счёту, нужно начинать с нуля. Или почти с нуля. Более того, отдельно от ЭВМ писать программы невозможно, значит, нужно и отечественное «железо». Но денег на всё это типа уже нет — всё прогадили на всякие олимпиады, мундиали (извините за слово) и прочие «нацпроекты». Или тупо украли.

Деньги, конечно, найти можно, например, взяв за «фаберже» тех, кто их выводит из страны — с начала года уже более $60 млрд. утекло за границу. А дальше? Дальше туго.

Нужно опять-таки с нуля создавать электронную промышленность, своего оборудования у нас нет, а купить его непросто. Хотя можно. Но ведь крысюки-чиновники вместо покупок заводов всё украдут и скажут, что так и было. Пример известного деятеля по прозвищу Мебельный налицо. Жив-здоров, на новой должности, процветает. Хотя в КНР такого без разговоров бы поставили к стенке.

Без стенки в «эрэфии» точно не получится. Между тем Мебельного простил именно Путин. И как тогда строить «импортозамещение»? Какой-то замкнутый круг получается.

Нужны крупные госкомпании (тут, увы, без вариантов) по разработке ПО. Но опять встаёт «кадровый вопрос» — кто их возглавит? Дело даже не только в воровстве, уж больно подмочена репутация у чиновников. Программисты народ вольный и обидчивый, сотрудничать с хамами и «барчуками» не станут. Проверено.

«Я больше не пойду работать в госкомпанию, ни за какие деньги. Был опыт когда-то. Платили так себе, но зато от дома добираться удобно, и было прилично свободного времени на подработки. Но в какой-то момент к нам начальником посадили сынка одного известного чиновника. И этот хамский щенок решил показать, что он тут босс. Я тут же уволился, другие тоже недолго продержались. Это было лет 10 назад, но, как говорится, осадочек остался», — рассказывает программист Александр.

Власти стоило бы показать серьёзность своих намерений. Тем более, что ситуация в стране и в мире тревожная, попахивает войной и народными волнениями. Нужно принимать решения. По китайскому сценарию. А там, глядишь, и народ подтянется. Да и деньги есть даже сейчас, достаточно обнулить бюджеты на так называемую «культуру» — содержание клоунов, шутов и скоморохов — и пустить эти деньги в дело. Появится и наши ЭВМ, и своя ОС, и прочее ПО. И на стройках будет кому заменить гастарбайтеров.

Категория «Политическая сатира и юмор» 
в сообществе «Политика, экономика, общество (без банов)» 

Если сокращение числа бедных пойдет такими темпами, как это произошло в III квартале 2021 года, то бедных в России и вправду скоро не останется. Как отчитался Росстат, по итогам III квартала 2021 года в стране насчитывалось 16 миллионов бедных, или 11% от общей численности населения России. До этого, по итогам 1-го полугодия 2021 года, в стране было 19,3 млн человек (13,2% от общей численности населения), которых Росстат относил к бедным. То есть всего лишь за один квартал в стране стало на 3,3 млн бедняков меньше. При этом сам Росстат указывает: последние данные о численности населения с денежными доходами ниже границы бедности отличаются от опубликованных ранее данных по 2021 году о численности населения с денежными доходами ниже величины прожиточного минимума.

7524237 5765398

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

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

Если в первом десятилетии ХХ века в России действительно наблюдалось серьезное сокращение количества бедных — с более чем 40 млн человек в 1999–2000-х годах до 15,4 млн человек в 2012 году, то потом этот процесс серьезно застопорился и даже развернулся в другую сторону. Недаром в конечном итоге задача сокращения числа бедных была даже сформулирована в виде национальной цели. Произошло это с некоторой задержкой — в 2018 году, когда в качестве национальной цели было названо снижение в 2 раза уровня бедности в Российской Федерации (до 2024 года).

Однако уже 2020-м стало очевидно, что со снижением бедности в стране большие проблемы: если в 2018 году у нас насчитывалось 18,4 млн бедных, то по итогам первого полугодия 2020-го таковых было уже 19,4 млн человек. Решение нашлось простое: взяли и сдвинули достижение цели на 2030 год, уточнив для верности, что к этому сроку бедность в России должна снизиться в 2 раза по сравнению с 2017 годом. В 2017 году бедных насчитывалось 12,9% от общей численности населения (18,9 млн человек). Соответственно, согласно «новой» национальной цели, к 2030 году бедных должно быть не более 6,5% от общей численности населения.

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

Отметим, что Росстатом оценка численности населения с денежными доходами ниже величины прожиточного минимума проводится аж с 1992 года. Величина прожиточного минимума формировалась на основе стоимостной оценки потребительской корзины, а также обязательных платежей и сборов. Да-да, это была та самая минимальная потребительская корзина, которую часто и не без оснований критиковали. Наполнение этой корзины всегда вызывало массу вопросов: почему столько-то составляет минимально необходимая норма хлеба; а почему столько-то предусмотрено сахара; а кто сказал, что человеку необходимо минимально съедать столько-то штук яиц в год, и не больше и не меньше?..

И вот буквально год назад решились наконец-то расстаться с этой устаревшей методологией — подсчетом минимальной потребительской корзины. Одновременно решили определять прожиточный минимум так, как это делается во многих развитых странах. Соответствующим законом был изменен порядок и периодичность величины расчета прожиточного минимума, в соответствии с которым величина этого показателя, начиная с 2021 года, стала устанавливаться в целом на календарный год (до 2021 года — ежеквартально) и определяться в размере 44,2% значения медианы среднедушевого дохода.

Медианный доход — это такой размер дохода, относительно которого одна половина населения имеет доходы выше него, а другая — ниже. Звучит это наукообразно, но на самом деле все, как видите, довольно просто. Теперь о том, откуда взялась эта цифра — 44,2%. Тут тоже все просто: взяли последний расчет прожиточного минимума на основании потребительской корзины и эту величину соотнесли с медианным доходом. Таким образом и были получены 44,2%. В общем-то называется это подгонкой под ответ.

Хотя расчет прожиточного минимума на основе медианного дохода — это, в принципе, нормальный и цивилизованный подход. Но уж коли стали его использовать, то надо было брать и норматив такой, какой используется в развитых странах. И это вполне было бы нормально, ведь речь идет о цифрах не абсолютных, а относительных. В странах ЕС, к примеру, считаются бедными те, кто имеет доход ниже 60% медианного дохода. Понятно, почему не использовали такой норматив, а появились странные 44,2%. Это сколько же бедных тогда насчитали бы в России! Думаю, что раза в полтора больше, чем те показатели, которые фиксируются сейчас. 

Однако считали на основе медианного подхода для определения количества бедных совсем недолго. В конце ноября 2021 года правительственным постановлением были утверждены Правила определения границ бедности.

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

Новшество же состоит в том, что теперь будут определять еще и границу бедности. Эта граница будет устанавливаться на уровне прожиточного минимума за IV квартал 2020 года. А базовые границы бедности будут пересчитываться с учетом инфляции. То есть фактически граница бедности меняться не будет, так как в реальном выражении она будет заморожена. Одновременно обещают, что такой подход обеспечит сопоставимость данных об уровне бедности за предыдущие периоды. Это является главным аргументом, который пришлось услышать от сторонников подобной новации.

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

На самом деле основная неафишируемая причина, почему вдруг решили считать еще и границу бедности, состоит в следующем: при этом подходе гораздо проще улучшить статистику по числу бедных. И только что обнародованные данные за III квартал 2021 года, приведенные выше, полностью подтверждают это. Но тогда есть резонный вопрос: нам что в конечном итоге надо — реальное или формально статистическое сокращение численности бедных? Формально статистически, это уже понятно по первым данным в соответствии с новым подходом, мы национальную цель по снижению бедности наконец-то выполним и перевыполним. Это ли нам надо? Понятно, что чиновникам надо именно это, но людям — вряд ли.

Автор: ИГОРЬ НИКОЛАЕВ

Pure Poison


  • #901

Привет) Молодец что вернулась.
Я вот что поняла за время своей трезвости: алкоголиком быть не страшно. Ничего хорошего в этом нет, но если не пить, то ничего плохого тоже. Это просто знание о себе, которое спустя время перестаёт тебя пугать. Так что грустить по этому поводу тоже не стоит, на мой взгляд.

Привет) спасибо? да, просто это нужно принять.

Fluffy


  • #902

Привет) спасибо? да, просто это нужно принять.

А ну спать быстро
сидит тут она, панимаешь )

Радуга света


  • #903

А ну спать быстро
сидит тут она, панимаешь )

А ты домой. Совсем от рук отбился!

Pure Poison


  • #904

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

Pure Poison


  • #905

А ну спать быстро
сидит тут она, панимаешь )

Хорошо, пап)

Fluffy


  • #906

А ты домой. Совсем от рук отбился!

У вас бенифис Скарлет
Берегу душевный покой
свой

Fluffy


  • #907

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

Не расплескай настрой, хорошо идет пока

  • #908

Да так уж последних. Медведей вполовину бы отстрелять. Естественных врагов почти нет, кроме них самих. А этот процент отстрела в коммерческой охоте мизерный. Мяско-то кушаешь? Свининку? Говядинку? Не жалко?

Жалко
Я наверно могла бы без мяса жить
В целом я больше овощи люблю

Но многие люди без мяса не могут

А вот без шуб сейчас вполне можно
Есть экошубы и всякие технологии чтоб не мерзнуть

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

Pure Poison


Pure Poison


  • #910

Именно украинское слушаю. В Киеве его и скачала. О нем напоминает. Эх, манит меня Киев❤️

  • EAD30EA3-8BCE-4791-8494-9100FF604E7F.png

    EAD30EA3-8BCE-4791-8494-9100FF604E7F.png

    121.6 KB · Просмотры: 3

Медовух


  • #911

Киев = Свобода = Природа = Доброта = Красота. А сейчас так вообще необыкновенно красиво. Сегодня рано возвращался домой , между фонарей теплая осень, ночью прошел дождь, думал станет холодней , нет, стало гораздо теплее. Возле куренёвского парка (парк Фрунзе в прошлом) открылась ярмарка, у нас постоянно их затевают на выходные. Пол шестого утра, уже люди ходят, что то выбирают. Приехал к себе, заказал чашечку кофе в любимой забегаловке — кайф. А сейчас тучи расходятся уже видно озаренные солнцем облака. Возможно сегодня Киев ожидает тепленький денёк)) Это здорово! Все кто вам скажут , что Киев это мегаполис — врут . Киев это колыбель кайфа! Доброе утро!

Pure Poison


  • #912

Киев = Свобода = Природа = Доброта = Красота. А сейчас так вообще необыкновенно красиво. Сегодня рано возвращался домой , между фонарей теплая осень, ночью прошел дождь, думал станет холодней , нет, стало гораздо теплее. Возле куренёвского парка (парк Фрунзе в прошлом) открылась ярмарка, у нас постоянно их затевают на выходные. Пол шестого утра, уже люди ходят, что то выбирают. Приехал к себе, заказал чашечку кофе в любимой забегаловке — кайф. А сейчас тучи расходятся уже видно озаренные солнцем облака. Возможно сегодня Киев ожидает тепленький денёк)) Это здорово! Все кто вам скажут , что Киев это мегаполис — врут . Киев это колыбель кайфа! Доброе утро!

Согласна. Очень уютный, романтичный город❤️ Люблю Крещатик, Подол…больше всего люблю Киев зимой. Та я вообще больше зиму люблю по ходу. Все белое, можно утеплиться, классно посидеть в уютном кафе, погулять. И домой всегда приятно возвращаться. Спишь хорошо. Рано темнеет, поздно светает (все как я люблю, уже писала, что нравится красивое искусственное освещение, не люблю дневной свет, мама сказала, что я крот. Малой тоже крот? У нас сегодня пасмурно, снег, низкое давление — моя любимая погода? Если зимой яркое солнце и мороз — мне капец! Башка раскалывается?

Медовух


  • #913

И что ты думаешь. Вылезла таки у меня лихорадка на губе)) Значит это не вакцина, видимо всё таки переохладился, мне даже как то лучше стало, морально. Вчера вообще сил не было, сегодня после суток бодрячком, если мои нимфы позовут меня на прогулку , пойду непременно. Сейчас хорошо у залива , уточки, чаечки, чаёк ,кофеёк. Прогулка у воды в приятной компании, что может быть лучше)

Радуга света


  • #914

Жалко
Я наверно могла бы без мяса жить
В целом я больше овощи люблю

Но многие люди без мяса не могут

А вот без шуб сейчас вполне можно
Есть экошубы и всякие технологии чтоб не мерзнуть

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

Значит плачешь и колешься, как в анекдоте про кактус и мышь, но продолжаешь есть. Неправильно это как-то. Корова-то не виновата, что не в лесу родилась. Что же до дикой природы, поскольку я тут недавно интересовалась, по случаю и предметом беседы был медведь, напишу. Количество медведей сейчас около 200 000 это очень примерная цифра, т.к. вести учет зверя крайне затруднительно и процент ошибки около 30%, т.е. его с равной вероятностью может быть и 150000 и 250000 особей. Это в 2,5 раза больше, чем 20 лет назад. Медведь территориальное животное, т.е. занимает определенную территорию и живёт на ней. Площадь неосвоенных территорий нашей страны около 7 500 000 кв. км. суши . Получается, что на одного Мишку приходится около 36 кв. км. Это много? Это расстояние 6 на 6 км. С учетом того, что взрослый медведь порой занимает пространство в несколько сотен квадратных километров, нужных ему, чтобы прокормиться. Сколько еды нужно одному мишке весом 300-400 кг в день, по большей части вегетерианцу, чтобы нагулять жир толщиной не менее трети своего веса, чтобы лечь в спячку? А если не накопит, то не ляжет, тогда кабздец всем и медведю в том числе. И получается, что медведям тупо не очень хватает места, вот они и выходят к городам, особенно молодые, не имеющие большого опыта встреч с человеком. А медведь, вышедший к человеку это потенциальный убийца и труп. Он теряет страх перед человеком и может задрать человека. Видела фото задранных насмерть медведем людей? А если это ребенок? А если он просто за молочком вышел??? Почти та же история с кабанами. Лицензия к слову на отстрел стоит 150 000 руб. Не каждый житель нашей страны может позволить себе такое дорогое удовольствие. Но почти у каждого есть дети. А убьешь медведко без лицензии — заплатишь 500 000. Так что охотнадзор не зря существует. Не надо в крайности впадать, сидя на диване. Лучше почитай, как медведица на Сахалине лет 10 назад задрала девочку 20 лет во время соревнований по спортивному ориентированию и мальчика покалечила. А дело, между прочим, не в лесу проходило, а в близлежащем парке. На месте этой девочки мог быть любой ребенок.
Прошу прощения у автора темы за флуд. Жути нагнала с утра в субботу. Больше не буду.

Последнее редактирование:

Pita4ok


  • #915

P.S. проскочила свой срок пития. Пить не хочу.

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

Pure Poison


  • #916

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

Как это говорят, заякорить. Тревожность моя тоже испаряется с каждым днём) Постоянно говорю себе — снижаем важность.

Pita4ok


  • #917

Как это говорят, заякорить. Тревожность моя тоже испаряется с каждым днём) Постоянно говорю себе — снижаем важность.

Вот здесь вчера нашел очень хороший совет. Сам так делаю уже 8 месяцев. Стал гораздо спокойнее

Там важно писать все на ночь и сразу байбай. Ничего не читать и не писать. Не обижаешься, что влезаю? Это мой метод, с ним трезвею. Нет, что ты, я рада «коллегам» по методу и вообще советам. Тока, если стебать не начинают, я барышня чувствительная, сразу в обморок:-D Вот у меня самая большая…


notdrink.ru

notdrink.ru

Виз


  • #918

Доброе утро, Саша.
Увидел, что ты читала мою тему, там лучше не с момента регистрации читать, а со второго захода в трезвость.
Первый раз я не попил год с небольшим и решил, что можно «по немногу». Закончилось как обычно через несколько месяцев)

Вот эта запись на три года трезвости может быть полезна

Так ты и не алкаш) ой, прекратите мне вот это


notdrink.ru

notdrink.ru

Pure Poison


  • #919

Доброе утро, Саша.
Увидел, что ты читала мою тему, там лучше не с момента регистрации читать, а со второго захода в трезвость.
Первый раз я не попил год с небольшим и решил, что можно «по немногу». Закончилось как обычно через несколько месяцев)

Вот эта запись на три года трезвости может быть полезна

Так ты и не алкаш) ой, прекратите мне вот это


notdrink.ru

notdrink.ru

Привет, @Виз) непременно почитаю ?

Марцина


  • Пол юли как пишется
  • Пол экземпляра как пишется слитно или раздельно
  • Пол юбки как пишется
  • Пол экрана как пишется
  • Пол франции как пишется правильно