Re[25]: Работа - с чего начать: С++ или С#?
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 18.03.09 13:23
Оценка: +1 -1 :)
Здравствуйте, Игoрь, Вы писали:

G>>Маленький ликбез:

G>>1)Стандартный аллокатор поддерживает связный список блоков памяти, выделение нового и освобождение блока вызывает проход по списку, который имеет алгоритмическое время O(n) от количества блоков.
И>Ты сам в это веришь? Это наивная реализация 80-ых годов. Сейчас используются всякого рода оптимизации, позволяющие минимизировать время поиска и частично отказаться от блокировок кучи. Например, в windows heap создается, если мне память не изменяет, на одну кучу 128 ассоциативных однонаправленных списков, не требующих блокировок.
Эта наивная реализация во многих местах осталась и по сей день.

G>>При постоянных выделениях-освобождениях памяти получются очень большие затраты на эту простую операцию.

И>В С# в целом та же херня.
Доказательства? Может сначала статью про .NETовский JIT прочитаете. На этом сайте статьи есть.

G>>2)При выделении блока идет небольшой оверхед, который зависит от реализации, 16-32 байта кажись. Исследования исходных кодов программ показывают что средний размер объекта составляет от 32 до 128 байт, при такких размерах оверхед является очень значительным.

И>Достаточно в таск менеджере взглянуть на кол-во используемой памяти .net прогой и С++ с эквивалентной функциональностью, чтобы понять, что ты гонишь.
Покажите две программы на .net и C++ с эквивалнтной функциональностью сложнее HelloWorld, потом посмотрим кто гонит.
Кроме того цифра в таск менеждере ни о чем не говорит, просто сверните приложение, будете удивлены.

И>Кроме того, в С++ принято мелкие объекты создавать на стеке. А если нужно в динамической памяти разместить объект, то есть placement new, который позволяет разместить объект в уже выделенной памяти.

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

G>>3)Выделение памяти таким алгоритмом создет фрагментацию памяти, то есть остаются блоки невыделенной памяти малых размеров.

И>Угу, только проблема фрагментации кучи есть и в .net, кстати, как и мемори лики.
Доказательства? Опять отправляю вас читать как работает выделение памяти и сборка мусора в .NET.
Про мемори лики хочу узнать поподробнее, как их получить, потом сравните это с простотой получчения лика в unamanged коде.

G>>4)Алгоритм выделения памяти не потокобезопасный, требуется синхронизация.

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

G>>5)В программах на С++ часто делают свои аллокаторы, которые выделяют память для маленькиз объектов чтобы избежать описанно выше оверхеда как по потребляемой памяти, так и по времени этой операции

И>В С++ такое делают крайне-крайне редко. Потому что
И>а) есть стэк;
Стек заставляет копировать объекты чаще, чем нужно.

И>b) есть placement new;

Теже яйца что и кастомный аллокатор, только сбоку

И>c) на мелких объектах свет клином не сошелся — можно и без них обойтись в критичной к скорости части;

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

G>>Теперь о GC

G>>6)Выделение памяти в .NET происходит очень просто — инкремент указателя. Никаких дополнительных операций не происходитю
И>Ага, аж десять раз. Это как бог на душу положит. Может и GC запуститься с полной остановкой всех потоков. Веселуха...
Читайте как работает GC, он не может просто так взять и запуститься.

G>>7)Оверхед по выделяемой памяти равен 8 байтам на 32-битной платформе (может ошибаюсь немного, лень смотреть)

И>уже писал про мелкие объекты и про то, что общий оверхед памяти для .net программ хорошо больше цэпэпэ.
А вы вообще ветку читали перед тем как это постить?

G>>8)Кроме того что выделение памяти выполняется моментально, эта операция еще и потокобезопасна.

И>в c# выделение памяти не более потокобезопасно, чем в с++
Полный бред.

G>>9)такое распределение памяти увелиичивает cache-locality

И>стандартные аллокаторы windows тоже оптимизированы на это дело
Рад за аллокатор Windows, только зачем он нужен если можно выделять память смещением указателя. Быстрее просто нечего придумать.

G>>10)GC собирает мусор не тогжа когда захочется, а при нехватке памяти в нулевом поколении

И>по сути это и означает, что когда захочется, особенно если речь идет о более-менее больших системах
И че? сборка памяти в нулевом поколении работает быстре чем использование алоокатора на списках при выделении-освобождении того же объема памяти.

G>>11)Для нулевого поколения объем памяти — пара сотен КБ, этот кусок очень хорошо ложится в кеш процессора.

И>пофиг, в С++ частое выделение/удаление мелких объектов стараются делать на стэке.
Ну и пусть стараются.

G>>12)Единственный критический недостаток GC заключается в том, что он очень плохо работает когда кончается свободная физическая память, сборка мусора во втором поколении заставляет поднимать все страницы памяти из свопа и это может нереально тормозить.

G>>13)Но даже этот недостаток можно побороть. Можно сборку мусора во втором поколении маскировать под каую-либо длительную операцию (например сохранение или открытие файла), а при расчетах использовать рецепт описанный здесь
И>это в общем-то самообман
Самообман — думать что C++ всегда быстрее.

И>PS

И>существенное преимущество GC — не надо следить за уничтожением объектов, что облегчает программирование, позволяет использовать всякие инетересные техники программирования, вроде замыканий. Но за эти удобства мы платим скоростью исполнения и большим расходом памяти. Вот собственно и все.
Тесты будут? Или вы тоже омновываете свое мнение на просмотре пары говнопрограмм?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.