Cyberax wrote: > >> В винде вроде бы мегабайт. Ну пусть у нас толстая процедура, у которой >> фрейм стека весит килобайт. Получаем глубины в 1024 вызова. Нет, я >> конечно верю в то, что и числа Фибоначчи можно рекурсивно вычислять, >> но черт возьми — /зачем/? А в обычных случаях рекурсии (типа обхода >> дерева) такие глубины на практике недостижимы. > > Кстати, стек еще и расти сам умеет.
Это если ему есть куда. В однопоточной программе места, куда ему расти,
обычно хоть попой ешь. Но вот в многопоточной программе расти ему
предстоит только до следующего стека (до стека другого потока). А дотуда
может быть не так уж и далеко.
Здравствуйте, Pzz, Вы писали: Pzz>Это если считать, что программисты — люди разумные. Однако бывают и Pzz>такие, которые на стеке большие буфера заводят...
Гм. Если вернуться к контексту дискуссии, то можно вспомнить, что речь не о программистах, а о jit-компиляторе, который принимает решение о размещении некоторых объектов в стеке вместо хипа. И уж он-то вряд ли кинется килобайты выделять.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, vitaly_spb, Вы писали:
_>Павел, откровенно говоря, я лично не понимаю смысла в такой "оптимизации".
_>Ок, пусть у вас есть объект. У него 20 внутренних полей. Вы переаллоцируете основной объект
Нет. Не переаллоцирцем объект. Оставляем его на месте и переделываем ему поля.
>сохраняя для него изначальную ссылку. Но при этом все эти 20 внутренних полей устанавливаются в изначальное значение (ссылки меняются).
_>По сути — из 21 объекта вы меняете ссылки не 21 объекту, а 20. Вот такая вот "оптимизация"
Это сильно зависит от того, что там в объекте
class A
{
int first;
bool second;
double third;
// etc
B b;
}
Здесь только одна ссылка (b) и три поля, которые не есть ссылки. Так что в этом случае будет 1 из 2.
А таких маленьких классов много. Посмотри изначальный постинг, там речь шла о классах кистей (туда же и перья и т.д.)
У SolidBrush, к примеру, всего 3 поля, если верить Reflector
System.Drawing.Brush.nativeBrush : IntPtr
System.Drawing.SolidBrush.color : Color
System.Drawing.SolidBrush.immutable : Boolean
Здравствуйте, Sinclair, Вы писали:
PD>>Выделение — да. Но не сжатие кучи. А вот там сжимать пришлось бы меньше. Представь себе. что тебе нужно по ходу действия создать десяток кистей. Сейчас для каждой new, потом их всех уберет GC. В моем варианте new будет один, так что и ему придется лишь один объект убрать. S>Гм. Павел, быстродействие GC в первом приближении зависит не от количества умерших объектов, а от количества живых. Если об этом помнить, то все встанет на свои места.
Антон, ИМХО во втором приближении быстродействие GC зависит от того, сколько памяти ему придется переслать, сжимая кучу. Насколько я понимаю, он при этом не занимается интеллектуальным заполнением дыр (т.е. поиском объектов, которые аккуратно в эту дырку уложились бы), а просто сжимает все к началу. А при этом чем меньше дыр, тем лучше.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Антон, ИМХО во втором приближении быстродействие GC зависит от того, сколько памяти ему придется переслать, сжимая кучу. Насколько я понимаю, он при этом не занимается интеллектуальным заполнением дыр (т.е. поиском объектов, которые аккуратно в эту дырку уложились бы), а просто сжимает все к началу. А при этом чем меньше дыр, тем лучше.
Сжиманием кучи ГЦ в .NET занимается тотлько при сборке 2ого поколения. При сборке 0ого и 1ого поколений происходит копирование выжевших объектов в болие старшие поколение.
Те скорость работы зависит только от того сколько объектов выжило.
А сборка 2ого поколения производится очень редко.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, WolfHound, Вы писали:
WH>Сжиманием кучи ГЦ в .NET занимается тотлько при сборке 2ого поколения. При сборке 0ого и 1ого поколений происходит копирование выжевших объектов в болие старшие поколение. WH>Те скорость работы зависит только от того сколько объектов выжило. WH>А сборка 2ого поколения производится очень редко.
Так, это значит, что я что-то не так понимаю. Посмотрю вечером Рихтера.
WH>Сжиманием кучи ГЦ в .NET занимается тотлько при сборке 2ого поколения. При сборке 0ого и 1ого поколений происходит копирование выжевших объектов в болие старшие поколение. WH>Те скорость работы зависит только от того сколько объектов выжило. WH>А сборка 2ого поколения производится очень редко.
Из Рихтера (картинки опускаю)
When the CLR initializes, it selects a threshold size for generation 0, say, 256 KB. (The
exact size is subject to change.) So if allocating a new object causes generation 0 to surpass
its threshold, a garbage collection must start. Let’s say that objects A through E occupy 256
KB. When object F is allocated, a garbage collection must start. The garbage collector will
determine that objects C and E are garbage and will compact object D so that it is adjacent
to object B. The objects that survive the garbage collection (objects A, B, and D) are said to
be in generation 1. Objects in generation 1 have been examined by the garbage collector
once. The heap now looks like Figure 19-8.
Итак, произошла сборка мусора в 0 поколении. Все выжившие объекты были сдвинуты в памяти, дабы заткнуть дыры.
И далее там же
When the application attempts to allocate object T, generation 0 is full and a garbage
collection must start. This time, however, the garbage collector sees that the objects in
generation 1 are occupying so much memory that generation 1’s 2-MB threshold has been
reached. Over the several generation 0 collections, it’s likely that a number of objects in
generation 1 have become unreachable (as in our example). So this time, the garbage
collector decides to examine all the objects in generation 1 and generation 0. After both
generations have been garbage collected, the heap now looks like Figure 19-14.
На рисунке показана куча, в которой произошло сжатие для поколений 0 и 1.
Так что твое "копирование выжевших объектов в болие старшие поколение" и есть их перемещение в памяти.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, WolfHound, Вы писали:
PD>Итак, произошла сборка мусора в 0 поколении. Все выжившие объекты были сдвинуты в памяти, дабы заткнуть дыры.
Нет. Они были перенесены в совсем другую область памяти.
PD>When the application attempts to allocate object T, generation 0 is full and a garbage PD>collection must start. This time, however, the garbage collector sees that the objects in PD>generation 1 are occupying so much memory that generation 1’s 2-MB threshold has been PD>reached. Over the several generation 0 collections, it’s likely that a number of objects in PD>generation 1 have become unreachable (as in our example). So this time, the garbage PD>collector decides to examine all the objects in generation 1 and generation 0. After both PD>generations have been garbage collected, the heap now looks like Figure 19-14.
PD>На рисунке показана куча, в которой произошло сжатие для поколений 0 и 1.
PD>Так что твое "копирование выжевших объектов в болие старшие поколение" и есть их перемещение в памяти.
Я надеюсь, ты не считаешь, что сложность перемещения в памяти как-то связана с расстоянием?
Все абсолтно верно. Если мы в цикле делаем Brush b = new Brush(), то при достижении порога GC обнаружит ровно 1 живой Brush. Именно он и будет передвинут в поколение 1. Область, ранее занятая миллионами мертвых Brush будет просто объявлена пустой (за O(1)) и в ней будет выделен новый Brush(), который мы запросили. Количество мертвых объектов при этом не влияет вообще ни на что.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, McSeem2, Вы писали:
MS>Здравствуйте, vitaly_spb, Вы писали:
_>>То есть ты по 100-бальной шкале вес объекта готов оценить? Мне кажется, GC это может сделать не хуже.
MS>Читай внимательнее. GC не может этого сделать в принципе, поскольку он знает только о managed ресурсах, объем которых близок к нулю. А вот что там кроется в unmanaged — он не знает и знать не может. И нет никакой возможности передать ему это знание.
Заведи глобальный счетчик дорогих объектов. Как только этот счетчик превысит некоторое пороговое значения -- вызывай GC (в конструкторе класса).
Здравствуйте, n0name2, Вы писали: N>не совсем. копировать их ненадо, но, все-таки нужно проанализировать граф ссылок и чем больше мертвых и живых обектов тем это сложнее.
Пардон, лично мне казалось, что в графе ссылок обходятся только живые объекты. Я что, ошибаюсь?
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
PD>>Итак, произошла сборка мусора в 0 поколении. Все выжившие объекты были сдвинуты в памяти, дабы заткнуть дыры. S>Нет. Они были перенесены в совсем другую область памяти.
Ну тогда я не знаю, кому верить — тебе или Рихтеру. Он там картинки рисует и ясно показывает, что куда перемещается. Ни о каких совсем других областях памяти там и речи нет. Или это относится к 1.x, а в 2.0 иначе ?
S>Я надеюсь, ты не считаешь, что сложность перемещения в памяти как-то связана с расстоянием?
S>Все абсолтно верно. Если мы в цикле делаем Brush b = new Brush(), то при достижении порога GC обнаружит ровно 1 живой Brush. Именно он и будет передвинут в поколение 1. Область, ранее занятая миллионами мертвых Brush будет просто объявлена пустой (за O(1)) и в ней будет выделен новый Brush(), который мы запросили. Количество мертвых объектов при этом не влияет вообще ни на что.
Не совсем так. В этом примере да. А вот если у тебя будут
ЖМЖМЖМЖМ...
т.е живой, за ним мертвый, опять живой и т.д, т.е 500 тыс живых, а между ними по одному мертвому (я утрирую, конечно, но ты же сам миллион задал , то сжатие сведется к 500,000 пересылкам небольших объектов. А это цикл над rep movs, и он будет работать ИМХО намного медленнее, чем один rep movs непрерывного блока суммарного размера всех живых. Впрочем, последнее только ИМХО, про rep scasd я не забыл
Здравствуйте, n0name2, Вы писали:
N>если это сервер, то поняимя "закрыть приложение" не существует — он практически всегда расчитан на то что он работает месяцами без остановки (хотя, конечно, под виндой если недельку продержится и то хорошо
Такое ощущение, что у тебя в своё время не сложилась любовь с виндой. Типа кто-то из вас кому-то не дала
N>при закрытии программы OS сама закроет все сокеты, файлы и т.д. и т.п., освободит всю память даже если ее не подобрал ЖЦ и т.д. без всяких финалайзеров.
Системные ресурсы да, а всяческие доморощенные?
N>try/finally — вот единственно верный и гарантированный способ своевременного закрытия ресурсов.
Точно. И как раз с этим в шарпе дела обстоят гораздо лучше чем в джаве.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Системные ресурсы да, а всяческие доморощенные?
это какие??
N>>try/finally — вот единственно верный и гарантированный способ своевременного закрытия ресурсов. IT>Точно. И как раз с этим в шарпе дела обстоят гораздо лучше чем в джаве.
PD>Нет. Не переаллоцирцем объект. Оставляем его на месте и переделываем ему поля.
Да, сорри, неправильно выразился
PD>Это сильно зависит от того, что там в объекте
Да, бесспорно.
PD>class A PD>{ PD> int first; PD> bool second; PD> double third; PD> // etc PD> B b; PD>}
PD>Здесь только одна ссылка (b) и три поля, которые не есть ссылки. Так что в этом случае будет 1 из 2.
Ну здесь конкретно вы экономите 1 переаллокацию (в данном случае вроде я то говорю?) — основного объекта. Это не много.
...Ei incumbit probatio, qui dicit, non qui negat...
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Для обучения — сразу не надо. Но все же программист на С++ должен понимать. что там ниже делается. Более того, ИМХО это вообще верно — чтобы качественно программировать на уровне N, надо понимать, что делается на уровне N-1. Уметь самому программировать на уровне N-1 не обязательно.
Я бы сказал так. Если технология спроектирована хорошо, то нание уровня N-1 не обязательно. Хотя обычно оно бывает полезно. В общем, N-1 — это скорее знания для экспертов, ну, или для продвинутых программистов. И то при условии, что это N-1 не начинает владеть мыслью программиста и определять проектные решения. А как показывает практика не все кто залез на N-1 могут адекватно оценить происходящиее.
... << RSDN@Home 1.2.0 alpha rev. 620>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.