Re[13]: Память и .Net
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.04.06 21:34
Оценка: 8 (3) :)))
Здравствуйте, Pavel Dvorkin, Вы писали:

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



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

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

PD>Они у всех ограничены. Все знать нельзя — не DOS времена.


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

PD>Настоятельно советую купить. Я серьезно говорю. У меня такое впечатление, что ты (и не только ты, скорее вы все) то ли не хотите, то ли времени нет, то ли еще что-то — но не знаете и не понимаете базовых механизмов функционирования ОС.


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

Со своей стороны вижу у тебя огромные пробелы в области понимания того как работает ЖЦ. И неверную оценку того насколько страшен свопинг для десктоп-приложений. Первое устраняется чтением статей и блогов по организации ЖЦ (не надо про Рихтера, ты его то понял не верно, а в нем о физическом устройстве ЖЦ очень не много сказано).

Второе — это чистая фобия. Экстраполяция проблем разных Мозил на другие приложения.

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


Твои заявления посмешнее будут. И главное, многие их за чистую монету моут принять.

PD>Попробую объяснить.


Ты бы понять попробовал. А то обясняешь другим, а сам...

...
PD>Мне ничего не стоит сделать Commited Bytes (в Task Manager называется VM Size) для своей програмы большим, чем размер RAM. При этом часть будет выделена в RAM, часть в файлах (свопе, MMF)

Запомни эти свои слова. Они тебе помогут понять то что ускользает от твоего взора.

PD>А вот Working Set — это совсем другое дело. Это те страницы, которые сейчас в RAM. Это то, что твоя программа сейчас забрала себе.


Ага. Для среднего С++-приложения это так и есть. Но вот для дотнет приложения это не совсем так. Оно всегда забирает памяти больше чем ему надо по минимуму. Собственно говоря так поступает почти любое приложение, но в дотнете это очень ярко выражено. Делается это правда не всегда, а только тогда когда в системе есть много свободной памяти (физической).

Улавливашь куда я клоню?

PD>Все процессы начинают работу с фиксированного Working Set (значений под руками нет). Далее они могут запрашивать все больше и больше памяти, VM Size будет у них расти (только они сами могут его потом уменьшить, освободив память) а вот будет ли при этом увеличиваться Working Set — зависит от ситуации в машине. Если памяти RAM свободной много, то будет. Более того, система может даже дать больше, чем максимум (см. SetProcessWorkingSetSize). Если же памяти мало, то система будет вытеснять страницы, а не давать новые.


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

Рельно если система сама начала отнимать физические странциы (а не пометками заниматься), то мы имеем ситуацию когда "ОС села на своп". Это как раз тот случай когда при переключении к очередному приложению мы слшышим мирное жужание винта. Работать в таких условиях очень неприятно и нужно срочно бежать за новой памятью. Собственно под ХРющей в 64 (да и в 128) метрах если не выгружать ничего такая ситуация наступает очень быстро.

PD>Теперь о минимизации. Разумеется, система отдает предпочтение активному приложению. И вот его минимизировали. Поскольку ты явно заявил, что не будешь с ним работать сейчас (правда это или нет — другой вопрос), то система усекает его Working Set , отнимая у него страницы.


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

Есть два случая когда память выделена, но не исползуется. Первый память закомичена но не использована по назначению. Второй в памяти размещены данные которые используются очень редко. Со втрорым все понятно, но с первым!

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

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

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

Более того, ЖЦ вообще работает эффективно только если в куче есть некоторый (и довольно значительный) объем памяти. Таковы уж алгоритмы сборки мусора.

Вот и выходит, что очень не малая часть памяти управляемого процесса — это банально неиспользуемая память. Отнимать ее не дорого если это делается не часто.

PD>А их куда девать ? Зависит от того, попадут ли они в список простаивающих или модифицированных. Если это страницы кода, то в первый (скорее всего), если данных — во второй (опять же скорее всего). Простаивающие страницы — кандидаты на выделение их другому процессу (после обнуления), модифицированные надо прежде того записать на диск , а потом уж давать другим.


Вот вот. Только незанятую память тоже нет смысла своповать. Ее ведь даже перечитывать не прийдется.

PD>Так чот уменьшить Working Set можно мгновенно практически — просто объявить эти страницы более не принадлежащими процессу, и все. Никакой записи на диск при этом вообще не произойдет.


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

Ведь же все просто... памяти в системе море... ЖЦ это видет и вместо того чтобы собрать мусор принимает решение увеличить ворксэт. Более того, чтобы делать это шустро он не просто занимает память, а делает это с запасом. Точнее это делается сегментами виртальной памяти по 16 метров и комитами по необходимости (но довольно большими кусками). Причем память будучи занятой не спешит освобождаться так как скорее всего ее еще раз запросят.

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

PD>Теперь сам можешь понять, что происходит. Минимизировали приложение. Уменьшился резко Working Set. А дальше что будет — зависит от a) много ли RAM и b) насколько агрессивно новый процесс (с которым теперь начали работать) запрашивает память и как давно с ним не работали.


Намного больше зависит от того как само приложение начнет востанавливать ворксет после активизации. Если оно сбросило ворксет до 5 метров и в системе мало свободной памяти, то приложение может и не начать набирать ворксет.

Так например, ворксет теста с гридом возрастает до 40-60 метров когда в системе свободно 900 метров памяти (из 2 Гб) и практически не привышает 30 метров когда в системе объем занятой памяти превышает объем оперативки (без учета свопа). Мои 40 процессов в основном держутся в рамках 30-15 метров. Если памяти станет меньше, то система отест еще. Но до момента пока система не сядет на своп скорость переключения на любой из процессов будет практически молниеносной (не заметной для человека). Вот сейчас я переключился на проивольный тест и никаких тормозов. Переключение на давно не используемую студию тоже к свопу не привело. А между тем ТаскМенеджер показывает 1.56 гига при 1 Гб установленном в системе.

PD>Если RAM много, а преемник не агрессивный, то отложенную запись будут откладывать . Некуда спешить — в системе тихо и мирно, всем памяти хватает.


Ага. И не забываем, что неиспользованную памяь вообще никуда девать не нужно.

PD>У меня на машине этот эффект проявляется, к примеру на Mozilla. Она у меня запущена всегда и я с ней почти не работаю, могу час-два к ней не обращаться. Если запустить некий процесс, активно отъедающий память, а потом переключиться на Мозиллу — тормоза очень заметны.


Боюсь Мозила тут не сильно виновата, но как многие С++-приложение оно почти всегда поднимает 90% своего ворксета при активизации. В сочетании с кончиной памяти в системе ты и видишь своп.

PD>Так что чудес не бывает. Суммируя, могу сказать- если процесс захватил 60 Мб Working Set и эти данные не R/O, то их записывать на диск будут (разве что процесс убьют, тогда, мб, и не будут). Но, конечно, не немедленно, а когда потребуется. И если таких процессов много (а минимизация, как сам понимаешь, отнюдь не гарантирует, что процесс не будет ничего делать, это лишь в большинстве случаев так), то свопинг будет хороший. Но размазанный по времени, так что ощутит юзер тормоза или нет — от многих факторов зависит.


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

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

По этому одно и то же приложение будучи запущенное на машине с 2 Гб памяти и при отсуствии программ-конкурентов легко демонстрирует 60-и метровый ворксет и довольствуется 15 метрами на машине с 500-ами метрами и в более тесном окружении. А на машине со 128 метрами она вообще возможно ужмется в 10 метров или менее.

Да, несомненно расход памяти и у дотнета, и у новых контролов больше чем у доисторических ListView и жлобском С-коде не использующем даже динамической памяти. Но и писать "бережливый" код в сотни раз сложнее и неудобнее. Результат же при этом получается куда более убогим и на много позже.

С точки зрения же нормального пользователя разницы особой нет. Ну, если конечно его не душит жаба при виде цифири 60 Мб в таскменеджере на его новой машине с 2 Гб оперативки.

PD>Поэтому , кстати, ASP.NET пользуется большой популярностью, а WinForms — нет.


Во как? Забавно. А откуда статистика? Я что-то вижу, что все больше и больше дескнопного софта пишется на дотнете. У меня добрая половина процессов уже желтенькие в ПроцессЭксплорер. Утилиты все сплош ирядом на нем написаны. Даже бэкап на сервере и то на нем. А уж о создании ГУИ для разных учетных и управленческих систем и говорить не приходится. На С++ его пишут уже куда реже.

PD> Для ASP.NET процесс-то, по существу, один — aspnet_wp.exe. Даже если там пять сайтов крутится и пользователей из Интернета тысяча. А вот если все приложения на рабочей станции перевести на .Net — будет тихий ужас. Если простенький пример Влада ухитрился иметь 60 Мб Working Set (хоть убей, не понимаю, как такого можно добиться!


Как видишь Влад запустил 40 экземляров того же приложения на машине с вдвое меньшим объемом памяти (да еще и ноутбуке с хреновым винтом супротив AMD 3500+ со Strip-ом на двух 7000-тысячниках). И никаких тормозов и свопинга предрекаемых тобой не произошло. А ведь казлось бы ты почти доказал обратное!

PD> Если бы от меня потребовали такое на Win32 написать — отказался бы, не знаю, как это можно сделать — то при десятке таких приложений будет примерно то, как работа Windows 95 на 4 Мб. Не пробовал ? MS тогда заявила, что будет работать (3.1 прекрасно работала). Я и попробовал


Я пробовл. Windows 95 на 4 метрах с сетью практически не работали. Дум на свопе это было что-то... Входишь в комнату... трррр... отсвоповали комнатку... бежим до следующей двери... Правда без сети можно было ворд загрузить, но жить было все равно не здорово. 4 метра это для 3.1. А Windows 95 бегать начинали от 8 метров. И то чуть по больше программка и хана. А уж чтобы загрузить 90 процессов как это у меня происходит сейчас когда я пишу эти строки, такого я даже вообразить не мог.

Сейчас же я сижу с гигом и казалось бы не столь экономной ХРюшей и спокойно запускаю 90 более половины из которых менеджед-процессы.

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


Золотые слова. Вот прочитай их и пойди разберись в том, что ты пыташся обсуждать. А то ведь право вводишь в заблуждение людей по чем зря. Ну, нельзя на базе общих знаний о виртуальной памяти обсуждать ЖЦ.

PD>И последнее. ИМХО у тебя сложилось впечатление, что я противник .Net. Вовсе нет. В целом я ее существование только приветствую, и отдаю ей должное. Хорошая система.


Да, оно и видно. Ты еще ни одного ее хая не пропустил.

PD> Но не надо ее возможности преувеличивать.


А кто это делает? Можно примеры?

PD> Поэтому я смотрю на вещи трезво.


Ой ли...


PS

Ниже приведены скриншоты снятые в разные стадии запуска приложений:
Память перед началом теста.
Первый запушенный тест.
Тот же тест, но после долгой и упоной прокрутки данных. Как видно жрет сильно меньше чем на машине с 2 Гб памяти (тот жрал за 60 метров).
А вот информацию о менеджед-кучах получаенная в то же время. Особо стоит обратить внимание на общий размер закомиченой памяти под управляемые кучи. Он сильно меньше чем зарезервированный и чем ворксет.
Этот скриншот получет после минмизации приложения, его востановаления и некоторых тырканий.
А вот уже загружены 30 тестов. :)
А вот уже 40 плюс общий вид экрана.
А это другие управляемые процессы. К сожалению влезни не все. 40 тестов не даеют это сделать. За кадром остались еще Рефлектор и т.п.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.