Здравствуйте, COFF, Вы писали:
BZ>>я их и решаю на C++. когда это необходимо. а остальное пишу на хаскеле. учитывая, что >90% кода не нуждается в ассемблерной эффективности, писать всё на С++ — это всё равно что всюду таскать с собой ружьё на случай нападения медведя из ЕР
COF>Вообще, изначально вопрос стоял так — стоит ли учить C++ или C#? Я так понимаю, что все-таки C++?
я ему ответил — смотря что делать собираешься. если готов лет 5 ходить в подмастерьях и затем заниматься какими-то узконишевыми вещами — можно рискнуть
Здравствуйте, NikeByNike, Вы писали:
NBN>C++ очень универсальный язык Он позволяет писать так как тебе нужно. В частности обеспечить все гарантии по чему хочешь, чем я, кстати, на днях воспользовался.
асм ещё универсальней. подумай, почему с 80-х годов им перестали пользоваться
Здравствуйте, hattab, Вы писали:
H>Для избавления от фрагментации памяти примеются специальные аллокаторы/менеджеры с пулами. Например в Delphi, c версии 2006 идет FastMM: H>
Description:
H> A fast replacement memory manager for CodeGear Delphi Win32 applications that
H> scales well under multi-threaded usage, is not prone to memory fragmentation,
H> and supports shared memory without the use of external .DLL files.
ага. и как можно устранить дефрагментацию памяти, а не просто в description это вписать — не подскажешь?
Здравствуйте, Хвост, Вы писали:
Х>Здравствуйте, gandjustas, Вы писали: G>>>>Если не верите, то попробуйте написать алгоритм решения задачи: "вывести на экран все строки текстового файла, в которых более трех слов, отсортированные по алфавиту". G>>Можете запостить сюда код решения на C++
Х>
Здравствуйте, MxKazan, Вы писали:
MK>Здравствуйте, hattab, Вы писали:
H>>3 раза на один вызов это иногда? Несколько последовательных вызовов сразу задирают тактовую частоту с 600 до 1700, при том, что при аналогичных действиях из нативного клиента частота поднимается максимум до 800. Тут нужно пояснить, что вся тяжелая работа (линейный скаллинг картинки) делается в нативном сервере (он запущен локально), клиентская часть лишь формирует запрос и получает ответ т.е. ее работа минимальна. MK>Ну мало ли что там делает это один вызов. Ты не на число запусков сборщика смотри, а на общий перформанс. При этом я ничего не обещаю, просто хочу сказать, что не стоит так сильно заморачиваться почему происходит вызов GC. В конце концов тот же rpc-xml может это сам явно делать по каким-то своим умозаключениям. У меня вот в WPF'ной проге, окна иной раз не собираются по 10-20 минут. Можно ли быть уверенным, что моя прога в сто раз быстрее твоей?
я не знаю насчёт net, но в ахскеле и по слузам в яве тоже двухпоколенный сборщик мусора. так он делает малую сборку через каждые 256кб выделенной памяти и никому это не мешает. так что ваозможно тут проблема только в прокладке
Здравствуйте, minorlogic, Вы писали:
M>Здравствуйте, gandjustas, Вы писали:
G>>Такая ситуация существует и на практике. Множественные операции выделения-освобождения памяти происходят гораздо бытсрее в коде на .NET, чем в коде на C++.
M>Большая часть "выделения-освобождения памяти" на С++ не затрачивает никаких ресурсов, как может быть быстрее ?
потому, что malloc/free на каждый глобальный объект может быть медленней, чем последовательное выделение памяти и затем gc, который за один раз собирает весь мусор
Здравствуйте, hattab, Вы писали:
H>Большое количество вызовов GC это прямой урон перформансу, он же не просто так дергается, он собирает чего-то. К тому же счетчик %Time In GC совсем не нулевой, да еще и на таком коротком отрезке времени (чему я был сильно удивлен). Я сейчас не говорю о каких-то цифрах, я об общем поведении.
а причём тут короткий отрезок? малые gc достаточно равномерно по ходу выполнения распределены, если бы большие gc с такой счастотой выделялись, то >90% времени только на них бы уходило
Здравствуйте, BulatZiganshin, Вы писали:
H>>Для избавления от фрагментации памяти примеются специальные аллокаторы/менеджеры с пулами. Например в Delphi, c версии 2006 идет FastMM: H>>
Description:
H>> A fast replacement memory manager for CodeGear Delphi Win32 applications that
H>> scales well under multi-threaded usage, is not prone to memory fragmentation,
H>> and supports shared memory without the use of external .DLL files.
BZ>ага. и как можно устранить дефрагментацию памяти, а не просто в description это вписать — не подскажешь?
Собственно, я уже написал -- пулами. В гугле описание работы FastMM можно поискать, если интересно. В дельфийских демках есть приложение Usage Tracker позволяющее отслеживать состояние существующих пулов с оценкой эффективности использования (кстати, модуль трекинга можно подключить к своему софту, при необходимости).
Здравствуйте, BulatZiganshin, Вы писали:
H>>Большое количество вызовов GC это прямой урон перформансу, он же не просто так дергается, он собирает чего-то. К тому же счетчик %Time In GC совсем не нулевой, да еще и на таком коротком отрезке времени (чему я был сильно удивлен). Я сейчас не говорю о каких-то цифрах, я об общем поведении.
BZ>а причём тут короткий отрезок? малые gc достаточно равномерно по ходу выполнения распределены, если бы большие gc с такой счастотой выделялись, то >90% времени только на них бы уходило
Я о коротком отрезке к тому говорю, что МС описывает счетчик %Time In GC не, как среднюю величину за отрезок времени, а с момента последнего цикла GC, коих за кратковременный вызов 3 штуки.
Здравствуйте, minorlogic, Вы писали:
M>Здравствуйте, gandjustas, Вы писали:
D>>>Кто сказал, что GC ГАРАНТИРУЕТ выделение памяти не более чем три раза больше чем в данный момент используется системой? G>>Этого не гарантирует даже аллокатор ОС, в принципе этого не может гарантировать никто.
M>Рекомендую ознакомиться с алгоритмами алокаторов более подробно.
А с ними достаточно подробно знаком, сам писал аллокаторы на ассемблере и несколько разных для С++
Здравствуйте, hattab, Вы писали:
BZ>>ага. и как можно устранить дефрагментацию памяти, а не просто в description это вписать — не подскажешь?
H>Собственно, я уже написал -- пулами.
это не гарантирует пропадания фрагментации. представь выделение миллиона 7-байтовых ячеек, освобожддение каждой второй из них и затем выделение миллиона 8-байтовых
Здравствуйте, gandjustas, Вы писали:
D>>>>Кто сказал, что GC ГАРАНТИРУЕТ выделение памяти не более чем три раза больше чем в данный момент используется системой? G>>>Этого не гарантирует даже аллокатор ОС, в принципе этого не может гарантировать никто.
M>>Рекомендую ознакомиться с алгоритмами алокаторов более подробно. G>А с ними достаточно подробно знаком, сам писал аллокаторы на ассемблере и несколько разных для С++
вот то-то и оно, что C++ почитай описание GC. ведь это очень просто — если последний большой GC нашёл 10 мб реальных объектов, то следующий GC можно сделать когда общий объём распределённой памяти будет 20 мб или даже 11 мб. это и даёт гарантии
Здравствуйте, minorlogic, Вы писали:
M>Здравствуйте, gandjustas, Вы писали:
G>>Здравствуйте, minorlogic, Вы писали:
M>>>Здравствуйте, gandjustas, Вы писали:
G>>>>Такая ситуация существует и на практике. Множественные операции выделения-освобождения памяти происходят гораздо бытсрее в коде на .NET, чем в коде на C++.
M>>>Большая часть "выделения-освобождения памяти" на С++ не затрачивает никаких ресурсов, как может быть быстрее ? G>> G>>Да ну? G>>Вым наверное стоит изучить как аллокаторы и GC работают.
M>Вы такими фразами или шутите или демонстрируете свое невежество.
Маленький ликбез:
1)Стандартный аллокатор поддерживает связный список блоков памяти, выделение нового и освобождение блока вызывает проход по списку, который имеет алгоритмическое время O(n) от количества блоков.
При постоянных выделениях-освобождениях памяти получются очень большие затраты на эту простую операцию.
2)При выделении блока идет небольшой оверхед, который зависит от реализации, 16-32 байта кажись. Исследования исходных кодов программ показывают что средний размер объекта составляет от 32 до 128 байт, при такких размерах оверхед является очень значительным.
3)Выделение памяти таким алгоритмом создет фрагментацию памяти, то есть остаются блоки невыделенной памяти малых размеров.
4)Алгоритм выделения памяти не потокобезопасный, требуется синхронизация.
5)В программах на С++ часто делают свои аллокаторы, которые выделяют память для маленькиз объектов чтобы избежать описанно выше оверхеда как по потребляемой памяти, так и по времени этой операции
Теперь о GC
6)Выделение памяти в .NET происходит очень просто — инкремент указателя. Никаких дополнительных операций не происходитю
7)Оверхед по выделяемой памяти равен 8 байтам на 32-битной платформе (может ошибаюсь немного, лень смотреть)
8)Кроме того что выделение памяти выполняется моментально, эта операция еще и потокобезопасна.
9)такое распределение памяти увелиичивает cache-locality
10)GC собирает мусор не тогжа когда захочется, а при нехватке памяти в нулевом поколении
11)Для нулевого поколения объем памяти — пара сотен КБ, этот кусок очень хорошо ложится в кеш процессора.
12)Единственный критический недостаток GC заключается в том, что он очень плохо работает когда кончается свободная физическая память, сборка мусора во втором поколении заставляет поднимать все страницы памяти из свопа и это может нереально тормозить.
13)Но даже этот недостаток можно побороть. Можно сборку мусора во втором поколении маскировать под каую-либо длительную операцию (например сохранение или открытие файла), а при расчетах использовать рецепт описанный здесь
Здравствуйте, BulatZiganshin, Вы писали:
BZ>>>ага. и как можно устранить дефрагментацию памяти, а не просто в description это вписать — не подскажешь?
H>>Собственно, я уже написал -- пулами.
BZ>это не гарантирует пропадания фрагментации. представь выделение миллиона 7-байтовых ячеек, освобожддение каждой второй из них и затем выделение миллиона 8-байтовых
Это слишком просто Пул это блок определенного размера, в котором выделение памяти происходит так же порциями определенного размера: 12, 20, 28, 36, 44 (шаг меняется с увеличением размеров на которые ориентирован пул), есть еще и отдельные пулы для средних и крупных блоков. В твоем примере будут выделяться блоки из первого пула по 12 байт, и ни какой фрагментации. Эффективность использования пулов можно контролировать тем самым трекингом, и в случае необходимости внести коррективы в алгоритм. Надо заметить, что лично мне ни разу не приходилось затачивать алгоритмы под работу менеджера памяти.
Здравствуйте, hattab, Вы писали:
H>Здравствуйте, BulatZiganshin, Вы писали:
BZ>>>>ага. и как можно устранить дефрагментацию памяти, а не просто в description это вписать — не подскажешь?
H>>>Собственно, я уже написал -- пулами.
BZ>>это не гарантирует пропадания фрагментации. представь выделение миллиона 7-байтовых ячеек, освобожддение каждой второй из них и затем выделение миллиона 8-байтовых
H>Это слишком просто Пул это блок определенного размера, в котором выделение памяти происходит так же порциями определенного размера: 12, 20, 28, 36, 44 (шаг меняется с увеличением размеров на которые ориентирован пул), есть еще и отдельные пулы для средних и крупных блоков. В твоем примере будут выделяться блоки из первого пула по 12 байт, и ни какой фрагментации. Эффективность использования пулов можно контролировать тем самым трекингом, и в случае необходимости внести коррективы в алгоритм. Надо заметить, что лично мне ни разу не приходилось затачивать алгоритмы под работу менеджера памяти.
Только общее увеличение потребления памяти получим.
А кто-то еще ругается что .NET много памяти жрет.
Здравствуйте, gandjustas, Вы писали:
H>>Это слишком просто Пул это блок определенного размера, в котором выделение памяти происходит так же порциями определенного размера: 12, 20, 28, 36, 44 (шаг меняется с увеличением размеров на которые ориентирован пул), есть еще и отдельные пулы для средних и крупных блоков. В твоем примере будут выделяться блоки из первого пула по 12 байт, и ни какой фрагментации. Эффективность использования пулов можно контролировать тем самым трекингом, и в случае необходимости внести коррективы в алгоритм. Надо заметить, что лично мне ни разу не приходилось затачивать алгоритмы под работу менеджера памяти.
G>Только общее увеличение потребления памяти получим. G>А кто-то еще ругается что .NET много памяти жрет.
Конечно получим, куда же мы денемся. Только оверхед сильно меньше, чем у .Net . Это я про общий случай, и по реальным приложениям это видно.
Здравствуйте, BulatZiganshin, Вы писали:
NBN>>C++ очень универсальный язык Он позволяет писать так как тебе нужно. В частности обеспечить все гарантии по чему хочешь, чем я, кстати, на днях воспользовался.
BZ>асм ещё универсальней. подумай, почему с 80-х годов им перестали пользоваться
Здравствуйте, BulatZiganshin, Вы писали:
M>>Большая часть "выделения-освобождения памяти" на С++ не затрачивает никаких ресурсов, как может быть быстрее ?
BZ>потому, что malloc/free на каждый глобальный объект может быть медленней, чем последовательное выделение памяти и затем gc, который за один раз собирает весь мусор
В сумме — может быть и быстрее, у GC есть свои плюсы
Однако сам должен понимать, что управляемых аллокаторов есть свои многочисленные плюсы, в том числе равномерность работы
Здравствуйте, NikeByNike, Вы писали:
NBN>>>C++ очень универсальный язык Он позволяет писать так как тебе нужно. В частности обеспечить все гарантии по чему хочешь, чем я, кстати, на днях воспользовался.
BZ>>асм ещё универсальней. подумай, почему с 80-х годов им перестали пользоваться
NBN>Потому что есть не менее эффективный С++, а что?
не было в 80-х годах ни C++, ни эффективных оптимизирующих компиляторов. тем не менее полчему-то люди обходились пессимизирующими С-компляторами. садись, опять двойка