Pull to refresh

Comments 56

Не могу плюсануть, поэтому выражаю лайк комментом :)

Присоединяюсь!
Отличная статья! Высокий технический уровень.
Спасибо большое!

Привет. Спасибо за пост. Хотел бы добавить несколько комментариев:

1. Кажется, перед "Из предыдущего листинга видно что процесс..." отвалился сам листинг )

2. "Запись в linux всегда быстрее чтения". Не всегда, например, если использовать O_SYNC.

3. vmtouch не нужно собирать, он отлично ставится из apt'a :)

Графоманство продолжается. Навскидку:

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

Ядро оперирует страницами не потому, что следить за каждым байтом накладно, а потому что аппаратура управления памятью (MMU) отображает виртуальные адреса на реальные, в конечном счёте, именно страницами, а не отдельными байтами. И, кстати говоря, размер страницы вовсе не обязан быть равен 4 Кбайтам -- это, как минимум, зависит от возможностей аппаратуры.

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

Во-первых, сегментация -- отличительная фишка архитектуры IA-32 aka x86, доступная в 16- и 32-разрядных режимах, но выпиленная из 64-разрядного режима. У других архитектур такого бреда мне не встречалось (хотя, возможно, альтернативно одарённые архитекторы подвизаются не только в Интел).

Во-вторых, сегментацией практически никто никогда не пользовался с момента появления 80386. В частности, ей никогда не пользовались в 32-разрядных версиях Винды.

Ну и т.д. и т.п. В общем, как обычно: списано у других без особого понимания материала.

Это не бред, а обратная совместимость. То, что, не в последнюю очередь, позволило данной архитектуре завоевать рынок в 80х.

Само появление сегментации, как и целая куча других особенностей интеловской архитектуры, является бредом. Они ухитрились собрать практически все возможные грабли в плане архитектуры -- причём сделали это уже в 1970-80-х годах, а не в 1950-60-х, когда опыт только нарабатывался (да и само понятие "архитектура" и её отделение от конкретной реализации появилось лишь в IBMовской Системе 360, а это 1964-й). Ну а что дальше приходится тянуть совместимость -- оно понятно...

В 8080, разработанной в 70-х, у них не было сегментной модели памяти, никаких граблей они не добавляли. Добавление сегментных регистров в 8086 и 80286 обусловлено, в первую очередь, необходимостью запускать доминирующую тогда в корпоративной среде CP/M на 8086 (фактически эмулируя 8080, для которой эта ОС разрабатывалась) с минимальными тратами на уровне аппаратных ресурсов, это был, по-сути, вынужденный шаг.

Вообще-то, CP/M делалась для 8-разрядных процов и благополучно работала на том же 8080. Сегментные регистры им понадобились, чтобы расширить физическое адресное пространство до 1 Мбайта с 64 Кбайт. И если в 8086 это ещё можно понять (хотя Zilog в Z8000 сделала куда разумнее, ну а раньше это было сделано DECом в PDP-11 -- тоже 16-разрядных, но с физическим адресом в зависимости от модели в 16, 18 или 22 разряда, и с довольно специфическим, но удобным в использовании MMU), то в 80286... Если уж вводите защиту памяти, то вводите по-человечески, а не через задницу. Собственно, по-человечески и пришлось сделать -- но в 80386.

Но претензии далеко не только в сегментации. Сама система команд ужасна, а её кодировка -- это вообще нечто... В частности, нет никакого простого способа определить длину кода команды -- приходится байт за байтом его анализировать. Ну и сравните это и с Системой 360, и с той же PDP-11, где длина команды однозначно устанавливается из её первого полуслова (Система 360) / слова (PDP-11; в обоих случаях это 2 байта), а сама команда всегда состоит из 2, 4 или 6 байтов. И всё это дерьмо приходится тащить ради совместимости...

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

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

Во-первых, я не сравниваю RISC с CISC, как делают в той статье. Я сравниваю отвратительный CISC (IA-32) с хорошими CISCами (PDP-11, VAX-11, System/360,370...z/Architecture).

Во-вторых, производительность может сильно зависеть от задачи. Скажем, если тебе нужно массовое шифрование или там преобразование из UTF-8 в UTF-32 и другие весьма распространённые, но не совсем уж тривиальные стандартные операции, то в z/Architecture это выполняется одной командой -- что при прочих равных прилично быстрей чисто программной реализации. (Может, кстати, поддержку подобных вещей и в IA-32 добавили: я особо за ним не слежу.) Ну а на каких-нибудь "графических" задачах даже посредственный GPU уделает любой центральный процессор "обычной" архитектуры, хотя безнадёжно ему сольёт на "задаче общего назначения", где нет возможности массово распараллеливать потоки данных.

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

Кстати говоря, у современных ARMов от RISC мало что осталось -- по сути, лишь выполнение операций обязательно в регистрах (нет команд "регистр-память" и "память-память"). Это косвенно доказывает порочность самой идеи RISC (максимально простая система команд), если речь заходит от необходимости получить сколько-нибудь приличную производительность. Конкретно в 1980-е и в начале 1990-х RISCи имели более высокую производительность по той причине, что их можно было реализовать в рамках одной микросхемы, а CISCи туда не очень-то лезли (можно вспомнить математические сопроцессоры 8087...80487, хотя у части 80486 эти команды были таки уже реализованы в одном кристалле с основным процессором). Но по мере увеличения доступного количества транзисторов на одном кристалле это преимущество было утрачено, что, собсно, Интел и АМД и демонстрируют, реализуя высокопроизводительные процессоры даже для отвратительной системы команд, хотя и ценой большой сложности и большого потребления энергии.

и, собственно говоря, те феноменальные результаты, которые показывают процессоры Apple в сравнении с Intel и AMD как раз и демонстрируют, где больше нехорошего легаси гавна накопилось -- в x86 или ARM.

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

те феноменальные результаты, которые показывают процессоры Apple в сравнении с Intel и AMD как раз и демонстрируют,

Феноменальными у семейства M1 были прежде всего размер кэша и пропускная способность памяти. Как только конкурирующие организации тоже завели себе 100+ MB кэша и удвоили толщину канала с памятью, то результаты Apple тут же закончились.

где больше нехорошего легаси гавна накопилось -- в x86 или ARM.

И таким образом, архитектурное legacy вообще не имеет отношения к вопросу.

а вы TDP при этом сравнивали, а?

Я много каких характеристик не сравнивал. Ни техпроцесс, ни TDP, ни возможность сделать восьмисокетный сервер...

Я сравниваю отвратительный CISC (IA-32) с хорошими CISCами (PDP-11, VAX-11, System/360,370...z/Architecture).
Реальные результаты сравнения процессоров из разных эпох оставляю на вашей совести.

Я сравниваю архитектуры, а не конкретные реализации. Разницу видите? Да и с разными эпохами как-то не очень. Скажем, и PDP-11, и VAX-11, и 8086 -- это 1970-е годы, а z/Architecture -- точно такая же современность, как современные процессоры Интел и АМД.

Вот производительность как раз и получается кошмарная
Я про это, что было сказано вами в контексте "кошмарной x86 архитектуры" - будут хоть какие-то пруфы? Я вам привел бенчи где АМД отказалась от "красивой" архитектуры в пользу "ужасной" в 90х. Спустя 30 лет мы все там же, в задачах, требующих производительность, все те же "бредовые и ужасные" х86, вот только недавно Амазон стал пропихивать свои гравитоны, но о их внутренней "красоте" стоит только догадываться.

Проблема не в “сегментации” как таковой, а в том, что автор позволяет себе писать о некой абстрактной штуке, “сегментации”, которая “на аппаратном уровне как правило есть”, умалчивая, или, скорее, не осознавая, что имеет в виду давно умершее частное техническое решение в Intel 80286 1982-го года. Ну вот вы догадались о чём речь. Но не все читатели данной статьи даже родились в это время. Солидаризируюсь с выводом SIISII.

Мне кажется автор напутал с понятиями "страничная адресация" и "сегментные регистры"

сегментные регистры вполне неплохо используются для организации потоковых переменных (и это кажется входит в стандарт PE)

>>логический адрес всегда совпадает с линейным

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

главное чтобы не как в Windows когда свободно ФИЗИЧЕСКОЙ памяти 30гб, но даже еще одна вкладка хрома вылетает с out of memory :DDD

В любой системе когда процесс помирает с“Out of Memory”, речь не о RAM. Для иллюстрации и понимания этого — пара примеров:

  1. В Windows процесс не будет создан (CreateProcess обвалится), если под всю статически необходимую процессу память нет места — внимание — в pagefile.sys. Ещё раз для закрепления в уме — не в RAM, а в файле подкачки.

    Да, там есть нюансы, например, пейджинг сегментов кода и RO-данных может осуществляться из файла самой программы, при условии, что он не на тормозном носителе типа CD :) Именно это, кстати, и есть причина, почему в Windows нельзя удалить файл исполняющейся сейчас программы — он используется, чтобы не забивать pagefile.sys.

  2. Механизмами ограничений (свирепым админом, ulimit, setrlimit, etc...) процессу установлено ограничение на использование памяти. Вот пусть прям по жесткачу — RLIMIT_AS. И пусть у ОС будут хоть терабайты свободной RAM, не в меру прожорливый процесс будет помирать с диагностикой “Out of Memory”

Именно это, кстати, и есть причина, почему в Windows нельзя удалить файл исполняющейся сейчас программы — он используется, чтобы не забивать pagefile.sys.

Можно подумать что в линуксе не так. Там точно так же секции кода и ro_data мапятся из исполняемого файла в память. Но исполняющийся файл удалить тем не менее можно.

Фокус в том, что удаляется только запись в директории, само содержимое файла остается на диске до того момента пока файл не отпустят - потом и содержимое будет удалено. Почему этого не может сделать windows - непонятно.

Почему этого не может сделать windows - непонятно.

Может. Но простому пользователю (Administrator — это тоже простой пользователь в модели безопасности NT) не даёт.

Не может. В файловых системах windows нет inodes. То есть там имя файла в каталоге и само описание файла это одна и та же структура. В linux (и других юниксах) все не так. Там можно отлично держать открытым удаленный файл в то время как запись в каталоге уже указывает на новый или вообще не существует.

И это фундаментальное ограничение архитектуры NT. Дейв Катлер видно хотел все сделать не так как в unix

С юникс-системами немного по-другому, работают не с именем, т.е. ссылкой на тот или иной узел, а с самим узлом, i-node, да и в виндовс, можно также работать (требуются административные права), во всяком случае, когда я кодил в 90-х (nt3.51, nt4.0), когда все ссылки на i-node, включая отображение в память закрываются - тогда она освобождается. хотя пока процесс работает, эту иноду можно подвязать под другую файловую структуру и "восстановить".

возможно не правильно именую i-node, более 15 лет не программирую, могу лажать (память не становится лучше ;) ).

Автору - Спасибо, многое вспомнилось и можно просто ткнуть в статью, чем пытаться на пальцах коряво объяснять ;)

какая мне разница как пользователю ваша тех информация? Мне показывают что ФИЗИЧЕСКОЙ памяти свободно ДОФИГА, которую я за свои $ купил!

Почему они тогда не изменят интерфейс Диспетчера который будет говорить правду относительно вашей тех информации? в формате (ЗАНЯТО\СВОБОДНО) мне больше ничего не нужно.

У меня просто как у пользователя случается батхэд когда СВОБОДНО означает НЕ СВОБОДНА

Во-первых "свободно" != "доступно конкретному приложению", что мы видим на вашем примере с хромом. Память то свободна. То что Хром не может ее использовать - это отдельная история. Во-вторых, память которая не используется - куплена зря. Поэтому любая адекватная ОС использует всю свободную память для дискового кеша.

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

Второе "кстати" - у вас выделено 61 из 64 гб.Такое ощущение что какое-то приложение зарезервировало себе дофига памяти но не использует ее. Человеки, кто винду лучше знает - винда позволяет оверкоммит по памяти? Беглый гуглеж говорит что нет, не позволяет. Так что ищите что у вас там за приложение не умеет обращаться с памятью.

Будешь смеяться, но скорее всего сам хром и не умеет. С моделями http страниц так наворочано, что парсить их становится всё сложнее и сложнее (это вылилось в то что сейчас не только лишь все могут распарсить, а осталось два относительно валидных движка - gecko(FFox, Mozilla) и chromium(Chrome, Google) ).

А если принять всю динамику и подгрузку и подмену, то код ядра парсера должен быть очень аккуратным, а это дорого и долго, а раз в полгода надо выкатывать новую версию (привет Гуглу), вот и вместо того чтобы старый код вымыть и причесать, они новый рождают в дополнение к старому.

  1. Как же тогда запускаются программы с выключенным свопом?

  2. Только на картинке изображены Memory Mapped Files. И если их выкинуть из памяти, скажем, RAMMap — то при таком же размере файла подкачки все волшебным образом запускается… пока система снова не сотворит фигни

главное чтобы не как в Windows когда свободно

Не "свободно", а "доступно". Пункт "Кэшировано" показывает, что эти 30 GB вполне себе используются прямо сейчас в качестве прозрачного кэша файловой системы.

ФИЗИЧЕСКОЙ памяти 30гб

В современных ОС, то что вы называете "физической памятью" это на самом деле всего лишь страничный кэш для настоящей памяти, которой являются pagefile.sys и прочие file mappings и section objects.

И на скриншоте видно, что настоящая память (пункт "Выделено") как раз почти полностью выжрана.

*Кстати, тот самый Chrome именно так и "работает". Хапает память (настоящую) как не в себя, но при этом единовременно реально использует меньше половины захапанного.

Так что со сценарием нагрузки со скриншота имеет смысл увеличить размер pagefile.sys раза в полтора-два.

Вероятно, данный юзер из секты неиспользующих pagefile.

Ибо выделено у него столько же, сколько физического ОЗУ

Вероятно, данный юзер из секты неиспользующих pagefile.

Отличное наблюдение. Я уже забыл, что такое вообще бывает и даже не думал на тему.

Ибо выделено у него столько же, сколько физического ОЗУ

В собственно отключении pagefile вроде ничего особо ужасного нет. Всё зависит от поведения нагрузки. И вот Chrome как раз очень плох в этом плане.

в качестве прозрачного кэша файловой системы

Только он НЕпрозрачный и невытесняемый, а так да.

И на скриншоте видно, что настоящая память (пункт "Выделено") как раз почти полностью выжрана.

Наоборот, там видно, что половина физической памяти свободна (UPD: или может быть освобождена), но не для тебя эта роза цвела.

Почему программы типа Oracle DB требуют отключения transparent hugepages ?

Просто потому что не умеют с ними работать ещё. Ну и профит можно получить только на ооочень больших объёмах памяти (там на уровне терабайтов).

Я не претендую на полноту ответа, но это на уровне того, что я знаю об Oracle и Postgres.

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

Сам текст интересно и последовательно изложен, спасибо.

Если swap скорее вреден при достаточном количестве памяти

Кто сказал? Опять секта нестраничников?

Там в тексте написано, я поэтому и спрашиваю

Не видел, где это в теме написано, но в целом:

- в Линухе если полезло в своп, это полный писец

  • в Винде, если свопа нет, полный писец

За форматирование спс новому движку хабра, чтобы их черти жарили

Для этого можно использовать так называемый "swap" раздел или файл. Можно, но на практике не нужно. Если swap выключен, то анонимная память становится невытесняемой, что делает время обращения к ней предсказуемым.

Вот здесь это написано. И дальше там про то, что минусов у выключения swap толком нет.

в Линухе если полезло в своп, это полный писец

Но я как раз там и встречал ситуации, когда из 8 гигов бывает занято максимум 4, но при этом в swap что-то со временем сбрасывается. Зачем и почему? Причем там мелочь какая-то на считанные мегабайты, от них оперативке было бы ни холодно ни жарко. На Windows такое еще больше выражено, но там другая система работы с памятью и это к этой теме относится.

Вот здесь это написано. И дальше там про то, что минусов у выключения swap толком нет

Для Линуха да(собственно тема статьи). Для Винды нет.

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

давно хотел узнать, можно ли увидеть текущую скорость работы с памятью в МБ/с наподобие как показана загрузка CPU в % или как скорость обращения к диску?

вот нашел что-то, возможно также что memtest что то покажет

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

UFO landed and left these words here

Огромное спасибо за статью! Узнал много нового для себя. Единственное, как будто бы стоило немного рассказать про HDD и SSD. Ведь на физическом уровне мы все равно утыкаемся в данные проблемы. Про работу именно с оперативкой - все четко и ясно. Спасибо еще раз)

Планирую сделать новую статью на тему памяти в линуксе, но уже все прошлые минусы исправлю, добавлю что не добавил. В общем - новая версия этой статьи)

Sign up to leave a comment.

Articles