LINUX.ORG.RU

Что каждый программист должен знать о памяти


1

0

Один из разработчиков ядра, Ulrich Drepper, начал публикацию своего труда, "Что каждый программист должен знать о памяти" ("What every programmer should know about memory"), описывающий то, как взаимодействуют программное обеспечение и системная память. Несмотря на то, что эффективность работы памяти зачастую определяет эффективность работы всей программы, материалов на тему того, как избежать узких мест в ее производительности не так много. Данная работа призвана устранить этот недостаток.

Публикация разбита на семь частей, каждая из которых будет появляться с периодичностью в одну-две недели после предыдущей. Публикация производится сайтом http://lwn.net, выкладываемые части некоторое время будут доступны только подписчикам. После того как будут выложены все части, текст будет выложен в публичный доступ.

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

>>> Часть 1

После выхода всех частей, хотелось бы видеть научно-технический перевод на русский язык.

anonymous
()

Он должен знать то, что памяти никогда не бывает много.

anonymous
()
Ответ на: комментарий от anonymous

По поводу 2005 на 256 MB RAM - 3.14здёж и провокация. Неоднократно просили заставить венду это проделать. Заставлял. Что же до шарпа - мне хватило крайне простого факта из синтаксиса - там нет break в switch/case. Следовательно, язык не просто для быдлокодеров, а для просто быдла. PS: юзайте monodevelop или как оно там ;)

anonymous
()

>Желающие прочитать первую часть сейчас, и притом бесплатно

Премного благодарен. А если я немного задержусь, то сколько это будет стоить?

turtle
()

о! протрезвею - обязательно буду читать

Muromec ☆☆
()
Ответ на: комментарий от stassats

Чем меньше мы знаем то как она должна работать(кроме основ - Кнут (Knuth)) - тем лучше! Всё остальное - изврат! Поправьте меня, может я залил глаза красным?

turtle
()
Ответ на: комментарий от turtle

Само по себе значение не вредно. Лучше сформулировать так: чем меньше мы _обязаны_ знать о работе с памятью, тем лучше. Или так: чем реже требуется знание о низкоуровневой работе с памятью, тем лучше.

ostrich_algorithm
()
Ответ на: комментарий от ostrich_algorithm

>Само по себе значение не вредно. Лучше сформулировать так: чем меньше >мы _обязаны_ знать о работе с памятью, тем лучше. Или так: чем реже >требуется знание о низкоуровневой работе с памятью, тем лучше.

Или (на мой взгляд) НИЧЕГО не может быть много! Ко ВСЕМ ресурсам мы ОБЯЗАНЫ относится бережно! В том числе и к размеру кода!

PS. Извините за резкость взгляда - больная мозоль ;-)

turtle
()
Ответ на: комментарий от anonymous

> Что же до шарпа - мне хватило крайне простого факта из синтаксиса - там нет break в switch/case.

это что за глупости? там же compilation error при ОТСУТСТВИИ break или return

anonymous
()
Ответ на: комментарий от anonymous

> По поводу 256Мб каждому программисту... даже Visual Studio 2005 не запустишь. Не говоря уже о 2008.

Вот и правильно было бы. Тр***лись бы не те, кто вынужден использовать это дотнетные поделки восьмиклассников, а те, кто их пытается писать.

pv4 ★★
()
Ответ на: комментарий от pv4

>>По поводу 256Мб каждому программисту... даже Visual Studio 2005 не запустишь. Не говоря уже о 2008.

>Вот и правильно было бы. Тр***лись бы не те, кто вынужден использовать это дотнетные поделки восьмиклассников, а те, кто их пытается писать.

+1 дотнет в большую топку!

AiFiLTr0 ★★★★★
()
Ответ на: комментарий от ostrich_algorithm

> Само по себе значение не вредно. Лучше сформулировать так: чем меньше мы _обязаны_ знать о работе с памятью, тем лучше. Или так: чем реже требуется знание о низкоуровневой работе с памятью, тем лучше.

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

gaa ★★
()
Ответ на: комментарий от pv4

> По поводу 256Мб каждому программисту... даже Visual Studio 2005 не запустишь. Не говоря уже о 2008.

> Вот и правильно было бы. Тр***лись бы не те, кто вынужден использовать это дотнетные поделки восьмиклассников, а те, кто их пытается писать.

Не знаю что там с абстрактными дотнетными поделками, а вот к ОО, FF, KDE, Gnome это напрямую относится.

sv75 ★★★★★
()
Ответ на: комментарий от gaa

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

ostrich_algorithm
()
Ответ на: комментарий от frame

> Программа будет "эффективной" только для одного процессора/архитектуры и далеко не всегда затраты на подобного рода оптимизацию оправданы.

Поэтому в то время, когда Линукс на NUMA-архитектурах летал, что только свист стоял, умудрённые опытом программисты MS не занимались всякой чепухой и писали по-нормальному свой виндовс дальше. SMP, NUMA - понапридумывали тут умных слов...

mv ★★★★★
()
Ответ на: комментарий от stassats

> Порой бывает проще купить дополнительно памяти.

Лузир! Открой глаза, у тебя уже слоты все кончились и регистровая память максимального объёма стоит. Шо? "Всё так же тормозит"? Можно ещё раз, я не расслышал... =)

Gharik
()
Ответ на: комментарий от anonymous

>это что за глупости? там же compilation error при ОТСУТСТВИИ break или return

Ну-ка, ну-ка, а можно поподробнее? Я правильно понял, что если внутри switch-а у какого-то case не будет стоять break, то будет compilation error? Хренасе! А если мне НАДО, чтобы в случае такого-то case выполнился этот и ещё следующий за ним? Дублировать? Выносить отдельно? Мдя....

MYMUR ★★★★
()
Ответ на: комментарий от MYMUR

Так, вроде, там можно поставить континуе.

anonymous
()
Ответ на: комментарий от ostrich_algorithm

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

Золотые слова! И вообще, зачем знать низкоуровневые особенности?! Это и есть вред!!! Зачем писать программу которая быстро работает под, скажем Linux? Скорее всего её будут запускать на любой *NIX. Конечно, автор программы может сказать, что он верует в GPL и в Линуса Торвальдса, потому, что он Бог. Но завтра (возможно, не дай Бог) его уволят из компании, которая пишет программы под Linux, и возьмут на работу в компанию, которая пишет под, скажем Sun OS или под Windows (извините за упоминание). Там работа с памятью ВОЗМОЖНО отличается от Linux. Итак, программа запускаемая под Sun и оптимизируемая под Linux будет неважно работать (скорее всего медленнее). Моё мнение для языков C/C++: - RAM-памяти мало, поэтому по возможности пользуй stl, standart C-library; - не рассчитывай, что твои данные кэшируются, кэшируй их явно. Например с помощью hash_map и др.; - не используй глобальные переменные, если только они не singleton; - для задач реального времени НЕ используй new и malloc на этапе ПОСЛЕ инициализации системы. На этапе Create-а можно. Скорее всего и для других задач это правило верно! - наверное можно продолжить ;-)

Что касается шарпов, паскалей, джав и др. языков высокого уровня, то там и вообще нечего замарачиваться. Там только следи, когда сборщик лучше пнуть (если только есть такая возможность).

turtle
()
Ответ на: комментарий от MYMUR

Нет, неправиль. Советую вникать в вопрос сначала или снижать тон =) Просто если тебе там break не нуже логически то ты должен написать goto next; case next : понятно? потому что в большинстве случаев нужно именно break в конце, и если вдург облажался (со всеми бывает, не надо тут выпендриваться) то это поможет найти ошибку ещё при компиляции.

theos ★★★
()
Ответ на: комментарий от gaa

> gaa (*) (22.09.2007 16:30:54) > Я не против этого. Но в данный момент оно выливается в написание мегакомбайнов типа жабы и дотнета, которые _одинаково_ (плохо) делают все задачи, вместо того, чтобы использовать узкоспециализированные языки, на которые задача ложится легко и эффективно.

Вот только FF хавает память... объясняют фрагментацией.

ИМХО я отдам 2% своего CPU для работы GC чем буду ПОСТОЯННО терять память в подобное программе.

Определение: если прикладная программа написана на C / С++ без смарт-поинтеров (или что там может эмулировать GC) - это ПОДЕЛКА.

PS системные вещи эффективнее делать на С / С++.

anonymous
()
Ответ на: комментарий от faustus

dsohowto Re: Что каждый программист должен знать о памяти

Дядя Ульрих начал глядеть в ЛКМЛ (через гмэйл) и постить коменты
с патчами периодически. Так что (линукс)кернел девелопером его
можно считать, несмотря на опечатки.

> Однако, автор "How to Write Shared Libraries" плохого не напишет.
>
> http://people.redhat.com/drepper/dsohowto.pdf

Как сказать. Опытный дядя с более чем десятком лет опыта
и разработки (г)либц. Однако, что написано пером, то не
вырубишь топором. Результаты чтения тут:

http://www.google.com/search?q=dso+howto
(cегодня это ссылка номер два)
_____

olecom
()
Ответ на: комментарий от anonymous

>> gaa (*) (22.09.2007 16:30:54) > Я не против этого. Но в данный момент оно выливается в написание мегакомбайнов типа жабы и дотнета, которые _одинаково_ (плохо) делают все задачи, вместо того, чтобы использовать узкоспециализированные языки, на которые задача ложится легко и эффективно.

> Вот только FF хавает память... объясняют фрагментацией.

Огнелис тоже монстр, правда монстр незаменимый. Вот будет в konqueror imglikeopera(а может уже есть?), выкину лиса.

> ИМХО я отдам 2% своего CPU для работы GC чем буду ПОСТОЯННО терять память в подобное программе.

Так просто не откупитесь парой процентов процессорной мощности. Реальный пример нехорошей работы gc: в виртуальной машине установлено ограничение на кол-во памяти в 127мб. Программа создаёт огромную кучу маленьких объектов, заполняя всю память. когда свободная память заканчивается, начинает работать мусорщик, который ищет то, что уже не используется, дефрагментирует память и т.д.... В итоге программа повисает на ~20 минут, после чего валится с OutOfMemoryException. Это приемлимая ситуация? По-моему, нет.

> Определение: если прикладная программа написана на C / С++ без смарт-поинтеров (или что там может эмулировать GC) - это ПОДЕЛКА.

Смарт поинтер от фрагментации памяти вроде бы не спасает. Или я что-то пропустил в современных технологиях?

> PS системные вещи эффективнее делать на С / С++.

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

gaa ★★
()
Ответ на: комментарий от turtle

>Премного благодарен. А если я немного задержусь, то сколько это будет стоить?

Присоединяюсь. На всякий случай сохранил копию страницы :) Кстати, под какой лицензией этот документ?

mky ★★★★★
()
Ответ на: комментарий от MYMUR

> А если мне НАДО, чтобы в случае такого-то case выполнился этот и ещё следующий за ним?

А ты сначала полумай, что тебе сейчас НАДО, а потому кому-то в этом коде разбираться, ага?

sv75 ★★★★★
()
Ответ на: комментарий от anonymous

>Определение: если прикладная программа написана на C / С++ без смарт-поинтеров (или что там может эмулировать GC) - это ПОДЕЛКА.

Можно ещё жёстче: если прикладная программа написана на С++ на указателях (а не на ссылках) - это ПОДЕЛКА. Ещё жёстче: если программа написана с использованием свободной памяти ...

turtle
()
Ответ на: комментарий от sv75

>> А если мне НАДО, чтобы в случае такого-то case выполнился этот и ещё следующий за ним?

> А ты сначала полумай, что тебе сейчас НАДО, а потому кому-то в этом коде разбираться, ага?

Философский вопрос. Кстати, в C/C++ так принято писать и нормально народ друг друга понимает. Да и тот изврат, что будет придуман взамен множественному case, вряд ли будет уж очень читабельным.

gaa ★★
()
Ответ на: комментарий от gaa

>Смарт поинтер от фрагментации памяти вроде бы не спасает. Или я что-то пропустил в современных технологиях?

Смарт поинтер удаляет память сразу как только выходит за область видимости, поэтому он предсказуем (поставил скобочки и всё!), в отличии от сборщика мусора. Сборщик запускается КАК ПРАВИЛО только когда памяти УЖЕ нет (это как раз тот момент, когда надо-бы ускориться ;-) )! Некоторые сборщики позволяют им подсказать когда запуститься.

turtle
()

Все. Вот теперь уж точно кому нибудь да капец.

mono ★★★★★
()
Ответ на: комментарий от gaa

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

Это что за красноглазие?! Ещё как используют! С++ тем и хорош, что можно размахнуться от низкоуровнего C (почти ассемблера) до элегантных эффективных высокоуровневых абстракций.

turtle
()
Ответ на: комментарий от turtle

>> Смарт поинтер от фрагментации памяти вроде бы не спасает. Или я что-то пропустил в современных технологиях?

> Смарт поинтер удаляет память сразу как только выходит за область видимости, поэтому он предсказуем (поставил скобочки и всё!), в отличии от сборщика мусора.

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

gaa ★★
()
Ответ на: комментарий от turtle

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

> Это что за красноглазие?! Ещё как используют! С++ тем и хорош, что можно размахнуться от низкоуровнего C (почти ассемблера) до элегантных эффективных высокоуровневых абстракций.

Можно примерчик _системной_ программы на цпп? А то куда ни сунься, везде ц. Может просто не туда суюсь :)

gaa ★★
()
Ответ на: комментарий от theos

>Советую вникать в вопрос сначала

Собственно, поэтому вопрос и был задан, что захотелось "вникнуть".

MYMUR ★★★★
()
Ответ на: комментарий от gaa

> Кстати, в C/C++ так принято писать и нормально народ друг друга понимает.

По-моим ощущениям, писать так НЕ принято. А принято писать break.

sv75 ★★★★★
()
Ответ на: комментарий от gaa

>Можно примерчик _системной_ программы на цпп? А то куда ни сунься, везде ц. Может просто не туда суюсь :)

Да пожалуйста: QT, fluxbox. Кстати, примечательно, что именно графические системы. Тут во всю используют полиморфизм и наследование. На С это можно, но некрасиво ...

turtle
()
Ответ на: комментарий от sv75

>А ты сначала полумай, что тебе сейчас НАДО, а потому кому-то в этом коде разбираться, ага?

Ну и? Тот, кто будет разбираться --- он знаком с логикой работы switch или как? Не знаком? До свидания. Рано ему ещё чужой код ковырять. Знаком? Прекрасно. Значит, быстро разберётся, что break тут был не нужен. А то если видеть в каждом отсутствующем break ошибку.... пусть ещё поищет ошибку в for(A;B;C), если (ай-ай, какой кашмар!!) A, B или C вдруг окажутся пустыми....

Просто писать надо аккуратно. Например, у меня натуральный рефлекс сразу ставить закрывающую скобку. И точно такой же рефлекс набирать case BLA_BLA: break; Видимо, у создателей C# такого рефлекса не было, и им часто досаждали собственные ошибки с пропущенным break-ом, раз они пошли на такой шаг.... =\

MYMUR ★★★★
()
Ответ на: комментарий от turtle

>>Определение: если прикладная программа написана на C / С++ без смарт-поинтеров (или что там может эмулировать GC) - это ПОДЕЛКА.

>Можно ещё жёстче: если прикладная программа написана на С++ на указателях (а не на ссылках) - это ПОДЕЛКА.

Давайте уж по полной: если прикладная программа написана на C / C++ ....

MYMUR ★★★★
()
Ответ на: комментарий от MYMUR

MYMUR>Давайте уж по полной: если прикладная программа написана на C / C++ ....

Ага ;-). Тогда будет так: Если программа написана человеком...

turtle
()
Ответ на: комментарий от turtle

>> Можно примерчик _системной_ программы на цпп? А то куда ни сунься, везде ц. Может просто не туда суюсь :)

> Да пожалуйста: QT, fluxbox. Кстати, примечательно, что именно графические системы. Тут во всю используют полиморфизм и наследование. На С это можно, но некрасиво ...

То, что в Qt удобно использовать возможности цпп, я не спорю. Но давно ли QT стала системной программой? Обычная прикладная библиотека. Вот sed, awk, ls - это системные программы.

gaa ★★
()
Ответ на: комментарий от sv75

>По-моим ощущениям, писать так НЕ принято. А принято писать break.

switch (smt) {
case AAA:
case BCE:
case DFG:
...
case QWERTY:
do_something_1();
break;

case QWE:
case FGH:
case GHJ:
do_something_2();
break;

default:
do_something_3();
}

И как это сделают те, у кого "принято писать break"?
Будут писать do_something_N() в каждом case? Браво!

Или напишут if (smt == AAA || smt == BSE || ... )? Брависсимо!

MYMUR ★★★★
()
Ответ на: комментарий от turtle

>Ага ;-). Тогда будет так: Если программа написана человеком...

Если программа написана....

MYMUR ★★★★
()

Всё то, что вы здесь обсуждаете; про оптимизацию, память, дешевизну компонент, а надо ли оптимизировать программу, очень кратко и содержательно (а также поучительно) написано у Джоэля Спольски: http://www.joelonsoftware.com/items/2007/09/18.html

anonymous
()
Ответ на: комментарий от gaa

gaa>То, что в Qt удобно использовать возможности цпп, я не спорю. Но давно ли QT стала системной программой? Обычная прикладная библиотека. Вот sed, awk, ls - это системные программы.

Конечно системное ПО! Это всё то ПО, которое используется систематически ;-) всем другим ПО. stl - системное ПО (куда уж системнее), стандартная библиотека С (libc), иксы, любой оконный менеджер, библиотека разбора *.xml - файла и т.д. Хотя граница скорее условная. Тебя наверное интересует ядро OS. Ну так БЫЛА такая - BeOS. Говорят очень удобная как для программирования ПО так и в использовании. Программировать под ней не доводилось, а вот пользоваться пришлось - оч. понравилась! Умерла жаль ;-( ! Хотя думаю ядро OS не самое место плюсам. Там как раз С.

turtle
()
Ответ на: комментарий от MYMUR

> Просто писать надо аккуратно. Например, у меня натуральный рефлекс >сразу ставить закрывающую скобку. И точно такой же рефлекс набирать >case BLA_BLA: break; Видимо, у создателей C# такого рефлекса не >было, и им часто досаждали собственные ошибки с пропущенным break->ом, раз они пошли на такой шаг.... =\

Прочти и устыдись, фанатик:

http://www.citforum.ru/programming/digest/scofdebug/

----------------------------------------

... В середине декабря 1989 года AT&T произвела обновление программного обеспечения на коммутаторах 4ESS с целью увеличения производительности системы и введения быстрого процесса восстановления после ошибки. Приблизительно в 2:30 по Восточному стандартному времени (EST) 15 января 1990 года на 4ESS коммутаторе в Нью-Йорке возникла небольшая аппаратная проблема, и коммутатор начал процесс восстановления, как было описано выше. После того как Нью-Йоркский коммутатор исправил проблему, он послал сообщение IAM для уведомления соседних коммутаторов, что он готов продолжать работу. Однако обновление программ, проведенное в середине декабря, внесло в действия ошибку. Эта ошибка проявилась, когда коммутатор получил два IAM сообщения с интервалом 1/100 секунды. Некоторые данные в коммутаторе оказались искажены, и он прекратил обслуживание, перейдя к инициализации. Когда соседние узлы выходили из строя, они запускали тот же самый процесс восстановления. Поскольку все коммутаторы были одинаковы, та же последовательность событий каскадом распространялась от одного коммутатора к другому и вывела из строя всю систему.

В течение дня инженеры AT&T смогли стабилизировать сеть, уменьшив нагрузку на нее. К 23:30 EST они смогли очистить все звенья сети, и система практически вернулась к нормальному состоянию.

Во вторник, 16 января 1990 года, инженеры AT&T смогли идентифицировать и выделить ошибку, которая была отслежена до набора ошибочных кодов. Этот код активировался в ходе процедуры восстановления коммутатора. Отрывок кода, который вызвал аварию, представлен ниже41:

1.do {

2. ...

3. switch (expression){

4. case (value 0):{

5. if (logical_test){

6. ...

7. break;

8. }else {

9. ...

10. }

11. ...

12. break;

13.}

14. ...

15. }

16. ...

17. }while (expression);

В данном случае виновным оказался оператор break в строке 7. Согласно реализации, если logical_test прошел успешно, программа переходит к строке 6 для выполнения расположенных там операторов. Когда выполнение программы доходит до строки 7, оператор break заставляет программу покинуть блок оператора switch, расположенного между 3 и 15 строками, и исполнять код начиная со строки 16. Однако эта часть исполнения не входила в намерения программиста. Программист желал, чтобы оператор break в седьмой строке прерывал выполнение условного оператора if-then и чтобы после исполнения седьмой строки исполнение продолжилось со строки 11.

-------------------------------------------------------

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

Языки для того и сделаны, чтобы от машинных кодов ум за разум не заходил, и не возникало соответствующих ошибок. Создатели C# это прекрасно понимали.

ЗЫ: И ваше C/C++ таки да, г... Заслуженное, но г...

ЗЗЫ: Лисп с Хаскелем и Эрлангом таки всех зарулят. И еще Nemerle. А вы, байтогрызы, без работы останетесь, в управдомы пойдете, только вас не возьмут, за склочность и красноглазие...

waricom

anonymous
()
Ответ на: комментарий от MYMUR

Ну, ты, [skip] развел тут фигню с си-шарповским switch. Возьми и почитай документацию. Может быть, потом будет стыдно.. :)

dave ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.