Здравствуйте, lboss, Вы писали:
L>Не стоит беспокоится... L>Я так вообще сюда редко захожу, теперь буду заходить ещё реже
[msdn]
Царевна:
— Коли так оно и есть, я отказываюсь есть. Вот тябе моя, папаша, политическая месть. Вот не стану есть икру, как обычно по ведру, и на почве истощенья захвораю и помру.
(с) Филатов.
[/msdn]
Здравствуйте, WFrag, Вы писали:
L>Здравствуйте, WFrag, Вы писали:
WF> Этот подход не правилен, если ты его хочешь применить в языках без GC, в языках GC — это нормально. Пойми, разница в проектировании под GC и не под GC — не только в том, что в случае с GC он за тебя все подметать будет. Это совершенно разные идеологии, разные подходы к проектированию. Я вот тоже раньше, года 4 назад думал: "А, GC — фигня. Если писать аккуратно, внимательно следить за объектами, то никакой GC не нужен". Но это не так. WF> И если эту ситуацию нельзя красиво выразить на C++, это не значит, что это плохое проектирование. Это просто другой взгляд на проектирование. Освободи свое мышление! WF> Мне кажется, что Java и C# гораздо лучше отражают идеологию ООП, чем C++ (хотя в C# есть пара косяков с идеологией ООП).
Да, что ты в GC уперся? Я же сказал, что считаю это приятной фичей. Повторяю: я не согласен с реализацией, и ещё раз повторю с чем:
1. Плата слишком большая — 20М это очень много.
2. Плохое смешивание кода — трудно мешать GC и не GC код...
3. Слабые возможности гибкой настройки RunTime — это в частности куча ненужной работы при простых операциях (например при сканировании сети — он проме имени компа тащит ещё кучу инфы — которую я у него не просил). Плюс ещё неясность что делать при ошибках — просто упираешься в .Net и ни чего не сделаешь кроме как в unsafe выходить — всё таки можно было бы WinAPI поделить на safe и unsfe.
4. Сама организания странная — можно было бы ввести многослойность — низкий уровень / высокий уровень — а не делать всё под одну гребенку...
WF>>Ну-ну... В свое время в именно в Java как раз и отказались от RefCount. Именно из-за низкой производительности. Потому что на каждый чих с ссылкой количество ссылок пересчтывались, поскольку в Java очень принято использовать гигантское количество мелких объектов. Вообще, AFAIK, GC гораздо лучше себя ведет в случае с большим количеством мелких объектов (например, у него быстрее выделение памяти, поскольку куча не фрагментируется).
L>В Java нет inline...
WF>JIT?
Я про то что в C++ если refCount сделаны через inline — это очень классно оптимизится компилятором...
Насчет GC — помоему у тебя некоторое недопонимание — давай сравним:
Выделение памяти пока памяти много — жрем всё что есть по методу стека — это и GC и в обычном Heap одинаково. Сравнивать можно только когда памяти мало: GC идет на сборку мусора (пометка периметра, выявление ссылок, вызов очиски, дефрагментация) — Heap просто идет по помеченным на удаление блокам. Так что GC делает много больше работы чем обычный Heap — я уж не говорю про возможность управления памятью в С++ (организация пула равноразмерных блоков, например, сильно ускоряет heap). Так что GC начинает выигрывать если памяти много (с одной стороны heap начинает долго искать удалённые блоки, с другой у GC снижается число циклов хотя против GC начинает играть необходимость дефрагментации) и твоя программа её всю отжирает (иначе всё тип-топ). А как давно ты писал проги отедающие 100М?. Хотя теперь будешь — надо отдать MS должное — она сделала всё что-бы проги подходили под требования GC — сильно раздула RunTime. Я конечно несколько утрирую, но мне просто интересно с чего народ взял, что им дают бесплатный сыр?!
WF>P.S. Кстати, если не секрет, ты общался плотно с Java, .NET-ом? Ты вообще, кем работаешь?
Я програмистом работаю... в софтверной компании, за деньги...
А ты?
Здравствуйте, lboss, Вы писали:
L>Я конечно несколько утрирую, но мне просто интересно с чего народ взял, что им дают бесплатный сыр?!
Да это понятно. В общем — свои плюсы, свои минусы. Где-то выгоднее C++, где-то .NET. Это всего лишь вопрос ресурсов.
L>Я програмистом работаю... в софтверной компании, за деньги...
Я так понимаю, ты из NSoft-а?. L>А ты?
Ну как тебе сказать... Даже как-то неловко... Я вообще-то студент ФИТ-а, в той же компании (видимо) бесплатно над одним проектом работаю...
Ладно, заканчиваем. Так можно вечность бодаться, в этом вопросе все равно нет определенного ответа.
Здравствуйте, lboss, Вы писали:
L>Выделение памяти пока памяти много — жрем всё что есть по методу стека — это и GC и в обычном Heap одинаково. Сравнивать можно только когда памяти мало: GC идет на сборку мусора (пометка периметра, выявление ссылок, вызов очиски, дефрагментация) — Heap просто идет по помеченным на удаление блокам. Так что GC делает много больше работы чем обычный Heap — я уж не говорю про возможность управления памятью в С++ (организация пула равноразмерных блоков, например, сильно ускоряет heap). Так что GC начинает выигрывать если памяти много (с одной стороны heap начинает долго искать удалённые блоки, с другой у GC снижается число циклов хотя против GC начинает играть необходимость дефрагментации) и твоя программа её всю отжирает (иначе всё тип-топ). А как давно ты писал проги отедающие 100М?. Хотя теперь будешь — надо отдать MS должное — она сделала всё что-бы проги подходили под требования GC — сильно раздула RunTime. Я конечно несколько утрирую, но мне просто интересно с чего народ взял, что им дают бесплатный сыр?!
Это неправильно.
Хип работает немного хуже, чем здесь написано. Ему приходится все же искать свободный блок в списке при выделении. В стеке выделение делается за константное время. Далее идет освобождение памяти. Хип вынужден честно его выполнять и, кроме всего, выполнять относительно медленное слияние соседних блоков. В GC быстродействие сборки мусора зависит не от количества освобождаемых объектов, а от количества еще живых. В большинстве случаев сборка сметает гораздо больше объектов, чем их остается, а жто намного эффективнее честного вызова delete для каждого из умирающих.
Защищенность от фрагментации играет достаточно большую роль в разработке "долгоиграющих" приложений.
Чтобы не быть голословным, взглянем на статью Автоматическое управление памятью в .NET
Здравствуйте, Sinclair, Вы писали:
S>Это неправильно. S>Хип работает немного хуже, чем здесь написано. Ему приходится все же искать свободный блок в списке при выделении. В стеке выделение делается за константное время. Далее идет освобождение памяти. Хип вынужден честно его выполнять и, кроме всего, выполнять относительно медленное слияние соседних блоков. В GC быстродействие сборки мусора зависит не от количества освобождаемых объектов, а от количества еще живых. В большинстве случаев сборка сметает гораздо больше объектов, чем их остается, а жто намного эффективнее честного вызова delete для каждого из умирающих.
"Ему приходится все же искать свободный блок в списке при выделении" — ему не приходится — ему ни кто не мешает этого не делать — а поступать как GС — реально это возникло в те времена когда памяти было мало — и приходилось её сильно экономить. В реальных программах память выделяется достаточно одинаковых размеров (более того ещё и выравнивается) и вреда от сильной фрагментации не много. Второе замечание насчет "приходится" — он это делает ещё и потому, что это делается быстро — опять таки из-за одинаковых размеров — и вероятность найти подходящий блок высока.
Будем алгоритмы рассматривать?
1. Heap:
а. Выделение — просто сформировать заголовок.
б. При удалении надо вычислить ptr — sizeof(header) и записать туда маркер удаленного блока. Очень быстро.
в. Сборка соседних блоков — бежать по свободным блокам и если расстояние между блоками равно размеру первого увеличить его размер. (это можно делать при поиске нового блока). То же не долго.
г. При нехватке памяти бежать по всем помеченным на удаление блокам — линейный поиск — но и не так уж и долго.
2. GC
а. Выделение — просто сформировать заголовок.
б. Нехватка памяти — обход периметра, вычисление указателей, пометка живых объектов, а дальше двиганье памятью и перенастройка указателей. — Вообще говоря — что тут GC не делает того что делает Heap? Тот же маркер удаленного блока, то же определение соседних блоков. И плюс к этому движения памятью и перенастройка указателей.
Да я согласен что если начать писать что-то типа
for(size_t size = 10; size < 10000000L; ++size)
{
char * p = new char[size];
//delete[] p;
}
Heap зашьётся, но в реальности мы выделяем одни и теже классы — они одного и того же размера (и довольно похожего) так что...
S>Защищенность от фрагментации играет достаточно большую роль в разработке "долгоиграющих" приложений.
Намного большую роль в CG играет разрешение ссылок друг на друга — это да... а скорость — это не его конёк...
S>Чтобы не быть голословным, взглянем на статью Автоматическое управление памятью в .NET
Здравствуйте, lboss, Вы писали:
L> — Вообще говоря — что тут GC не делает того что делает Heap? Тот же маркер удаленного блока, то же определение соседних блоков. И плюс к этому движения памятью и перенастройка указателей.
Ты невнимательно читаешь. GC НЕ УДАЛЯЕТ ОБЪЕКТЫ! Он их сохраняет!
Вымышленный пример кода:
MyClass *mp = new MyClass();
{
MyClass (*mp1)[100000];
for (int i=0; i<100000; i++)
{
mp1[i] = new MyClass();
}
for (int j=0; j<100000; j++) // вот этого GC не делает!
{
delete mp1[j];
}
}
Теперь под GC:
MyClass *mp = new MyClass();
{
MyClass (*mp1)[100000];
for (int i=0; i<100000; i++)
{
mp1[i] = new MyClass();
}
} // в этот момент в живых остался только mp. На остальные объекты указателей нет.
Все, что нужно сделать сборщику мусора — это скопировать mp. Сто тысяч блоков памяти, выделенных нашим циклом, трогать вообще не надо. От их количества время сборки вообще не зависит.
... << RSDN@Home 1.0 beta 6a >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, lboss, Вы писали:
L>Здравствуйте, Sinclair, Вы писали:
S>>Это неправильно. S>>Хип работает немного хуже, чем здесь написано. Ему приходится все же искать свободный блок в списке при выделении. В стеке выделение делается за константное время. Далее идет освобождение памяти. Хип вынужден честно его выполнять и, кроме всего, выполнять относительно медленное слияние соседних блоков. В GC быстродействие сборки мусора зависит не от количества освобождаемых объектов, а от количества еще живых. В большинстве случаев сборка сметает гораздо больше объектов, чем их остается, а жто намного эффективнее честного вызова delete для каждого из умирающих.
L>"Ему приходится все же искать свободный блок в списке при выделении" — ему не приходится — ему ни кто не мешает этого не делать — а поступать как GС — реально это возникло в те времена когда памяти было мало — и приходилось её сильно экономить. В реальных программах память выделяется достаточно одинаковых размеров (более того ещё и выравнивается) и вреда от сильной фрагментации не много. Второе замечание насчет "приходится" — он это делает ещё и потому, что это делается быстро — опять таки из-за одинаковых размеров — и вероятность найти подходящий блок высока.
Это не так. Ты неправильно понимаешь работу хипа. Он не может выделять память инкрементально, так как размер указателя ограничен. Если каждый следующий выделенный указатель превышает предыдущий, то через какое время 32 бит не хватит, чтобы выделить новый блок?
Поэтому надо хранить информацию об уже освобожденных блоках. Они разного размера. Это значит, что необходим поиск по списку. Да, обычно он довольно-таки быстр. Но тем не менее, он происходит. В то время, как стек всего лишь возвращает текущее значение указателя на свободную память и инкрементирует его на размер.
... << RSDN@Home 1.0 beta 6a >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Это не так. Ты неправильно понимаешь работу хипа. Он не может выделять память инкрементально, так как размер указателя ограничен. Если каждый следующий выделенный указатель превышает предыдущий, то через какое время 32 бит не хватит, чтобы выделить новый блок?
Умник:
1. запусти цикл
volatile unsigned long i = 0;
while(++i);
И посмотри сколько он делается
2. Ты правда думаешь, что стоит икрементить указатель и память будет браться из воздуха
S>Поэтому надо хранить информацию об уже освобожденных блоках. Они разного размера. Это значит, что необходим поиск по списку. Да, обычно он довольно-таки быстр. Но тем не менее, он происходит. В то время, как стек всего лишь возвращает текущее значение указателя на свободную память и инкрементирует его на размер.
Ещё один бред — это решается заголовками — надо хранить только указатель на первый свободный блок.
Здравствуйте, Sinclair, Вы писали:
S>Ты невнимательно читаешь. GC НЕ УДАЛЯЕТ ОБЪЕКТЫ! Он их сохраняет! S>Вымышленный пример кода: S>
S>MyClass *mp = new MyClass();
S>{
S> MyClass (*mp1)[100000];
S> for (int i=0; i<100000; i++)
S> {
S> mp1[i] = new MyClass();
S> }
S> for (int j=0; j<100000; j++) // вот этого GC не делает!
S> {
S> delete mp1[j];
S> }
S>}
S>
S>Теперь под GC:
S>
S>MyClass *mp = new MyClass();
S>{
S> MyClass (*mp1)[100000];
S> for (int i=0; i<100000; i++)
S> {
S> mp1[i] = new MyClass();
S> }
S>} // в этот момент в живых остался только mp. На остальные объекты указателей нет.
S>
S>Все, что нужно сделать сборщику мусора — это скопировать mp. Сто тысяч блоков памяти, выделенных нашим циклом, трогать вообще не надо. От их количества время сборки вообще не зависит.
1. А как начсет вызова деструктора для
КАЖДОГО УДАЛЯЕМОГО
объекта — или ты думаешь, что delete = free?!
Так что GC делает тоже самое и намного больше:
MyClass *mp = new MyClass();
{
MyClass (*mp1)[100000];
for (int i=0; i<100000; i++)
{
mp1[i] = new MyClass();
}
//Он делает это:for (int j=0; j<100000; j++) // вот это GC делает!!!
{
MARK_AS_UNUSED(mp1[j]);
}
RESOLVE_PTR();
for (int j=0; j<100000; j++) // вот это GC делает!!!
{
if(IS_MARK_AS_UNUSED(mp1[j]))
mp1[j]->~MyClass();//Вернее Dispose но так проще сравнивать
}
DEFRAGMENT();
}
Для сравнения без GC:
MyClass *mp = new MyClass();
{
MyClass (*mp1)[100000];
for (int i=0; i<100000; i++)
{
mp1[i] = new MyClass();
}
for (int j=0; j<100000; j++)
{
mp1[j]->~MyClass();
MARK_AS_FREE(mp1[j]);
}
}
Как говорится — почувствуй разницу — и не смеши мои тапочки...
Здравствуйте, lboss, Вы писали:
L>Умник:
L>1. запусти цикл L>
L> volatile unsigned long i = 0;
L> while(++i);
L>
L>И посмотри сколько он делается
У меня — 32.206 секунды. И что? Можно объяснить мне глубокий смысл этой цифры?
L>2. Ты правда думаешь, что стоит икрементить указатель и память будет браться из воздуха
Именно так я и думаю. Имеем:
1. Блок памяти размера, скажем, M. Нет, M мало. Возьмем N.
2. Указатель P на начало блока памяти.
3. Нам надо получить блок размером X байт.
4. Возвращаем P, затем прибавляем к P X округленное до выравнивания
Все. Больше делать ничего не надо. Следующее обращение к п.4 получит следующий блок. На самом деле схема чуть-чуть посложнее, т.к. нам потребуется в будущем делать то, что ты называешь дефрагментацией. Но это все равно гарантированно делается за константное время.
L>Ещё один бред — это решается заголовками — надо хранить только указатель на первый свободный блок.
А если первый свободный блок имеет недостаточный размер? QuickHeap, который рвет всех по производительности в той статье, которую я привел, как раз частично решает эту проблему при помощи минимизации количества различных размеров. Но мне хотелось бы напомнить, что он имеет катастрофически низкий КПД использования памяти.
По поводу вызова деструкторов хотелось бы отметить, что процент классов с нетривиальными финализаторами весьма низок. И еще раз подчеркнуть, что время дефрагментации, которое якобы теряет сборщик мусора, не зависит от количества объектов, которые надо убить.
... << RSDN@Home 1.0 beta 6a >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, lboss, Вы писали:
L>Да, что ты в GC уперся? Я же сказал, что считаю это приятной фичей. Повторяю: я не согласен с реализацией, и ещё раз повторю с чем: L>1. Плата слишком большая — 20М это очень много.
Это не только за GC, не надо передёргивать.
Только mfc*.dll в каталоге \winnt\system32 занимают примерно 50 Mbytes
Каталог \winnt\mircosoft.net занимает примерно 55 Mbytes, причём там весьма много всего:
— собссно dll, причем не только UI, и даже ASP.NET
— документация в XML (только здесь 12 метров)
— конфигурация
— компиляторы C# и JS.NET
— "Temporary ASP.NET Files" (у меня — 4 метра)
Так что платишь 20метров ты не только за GC.
L>2. Плохое смешивание кода — трудно мешать GC и не GC код...
Согласен, трудно. Только редко нужно, на самом-то деле. Не мелкое приложение на .NET (примерно треть "P", тебе для сравнения) не потребовало этого ни разу, написалось за три месяца, работает стабильно, легко сопровождается.
А на тему расхода памяти... (пользуясь случаем, передаю привет AVK) Что-то давно не приводил я цены на память.
L>3. Слабые возможности гибкой настройки RunTime — это в частности куча ненужной работы при простых операциях (например при сканировании сети — он проме имени компа тащит ещё кучу инфы — которую я у него не просил).
ИМХО, неверное обобщение частной проблемы. Всё делается, написать обёртки для нужных тебе функций — полчаса работы. В сложных случаях — два часа. Если это критическое место системы (помним о premature optimizations) — не грех потратить это время и получить нужную тебе функциональность НЕ жертвуя остальными возможностями.
L>Плюс ещё неясность что делать при ошибках — просто упираешься в .Net и ни чего не сделаешь кроме как в unsafe выходить — всё таки можно было бы WinAPI поделить на safe и unsfe.
Этого не понял. Расшифруй? Ты имеешь ввиду GetLastError? Или что?
L>4. Сама организания странная — можно было бы ввести многослойность — низкий уровень / высокий уровень — а не делать всё под одну гребенку...
Организация чего? Если ты имеешь ввиду FCL — есть там довольно много косяков. Но софта без ошибок не бывает.
Еще раз повторю, не нужно делать из .NET панацею и спорить "нифига .NET не панацея". Да, .NET — не серебрянная пуля и не золотая таблетка. Просто удобная среда для определеннного класса задач. Возможно, сканнилка сети — не та задача, для которой удобно использовать .NET
L><... skip ... > Я про то что в C++ если refCount сделаны через inline — это очень классно оптимизится компилятором...
Всё это здорово, когда у тебя цельное приложение. Как только появляются компоненты, плагины, аддоны, скрипты, их версионность, сопровождение и развёртывание — находится столько проблем, что гораздо проще использовать среду, для этого предназначенную. Да ты и сам знаешь, чего говорить
Я про Delphi не понял — это к чему? Если интересует как сделан Heap — глянь в его сорцы.
Но в любом случае этот флейм уже ни о чём — делаешь просто:
1. Берешь реальный C++ проект, используя _CrtSetAllocHook — логируешь операции с памятью
2. Создаешь тесты — и смотришь что быстрее... У меня GC проигрывает... и сильно...
Извини — я болею — флейм трудно поддерживать...
O>Это не только за GC, не надо передёргивать. O>Только mfc*.dll в каталоге \winnt\system32 занимают примерно 50 Mbytes
O>Каталог \winnt\mircosoft.net занимает примерно 55 Mbytes, причём там весьма много всего: O>- собссно dll, причем не только UI, и даже ASP.NET O>- документация в XML (только здесь 12 метров) O>- конфигурация O>- компиляторы C# и JS.NET O>- "Temporary ASP.NET Files" (у меня — 4 метра)
Я про другое — почему я не могу выбирать? а если мне не надо остального? Если мне нужен только CG? Зачем такое навязывание?
L>2. Плохое смешивание кода — трудно мешать GC и не GC код... O>Согласен, трудно. Только редко нужно, на самом-то деле. Не мелкое приложение на .NET (примерно треть "P", тебе для сравнения) не потребовало этого ни разу, написалось за три месяца, работает стабильно, легко сопровождается.
Ага — только писал ты его с нуля — а если у тебя уже есть такое Г как "Р"? В нем же всё есть — и попробуй убедить кого-то на перереход в .Net. То есть MS навязывает переписывание проектов...
— меня это убило
O>А на тему расхода памяти... (пользуясь случаем, передаю привет AVK) Что-то давно не приводил я цены на память.
Ну с такой позицией надо писать на скриптах — процы тоже не очень дорогие...
L>3. Слабые возможности гибкой настройки RunTime — это в частности куча ненужной работы при простых операциях (например при сканировании сети — он проме имени компа тащит ещё кучу инфы — которую я у него не просил). O>ИМХО, неверное обобщение частной проблемы. Всё делается, написать обёртки для нужных тебе функций — полчаса работы. В сложных случаях — два часа. Если это критическое место системы (помним о premature optimizations) — не грех потратить это время и получить нужную тебе функциональность НЕ жертвуя остальными возможностями.
Кхе кхе — и заниматься правкой огромного кол-ва кода? Ты же сам спозиционировал .Net как систему для больших проектов...
L>Плюс ещё неясность что делать при ошибках — просто упираешься в .Net и ни чего не сделаешь кроме как в unsafe выходить — всё таки можно было бы WinAPI поделить на safe и unsfe. O>Этого не понял. Расшифруй? Ты имеешь ввиду GetLastError? Или что?
Нет я имею ввиду ошибки в самом .net — тут же ни чего не сделаешь...
L>4. Сама организания странная — можно было бы ввести многослойность — низкий уровень / высокий уровень — а не делать всё под одну гребенку... O>Организация чего? Если ты имеешь ввиду FCL — есть там довольно много косяков. Но софта без ошибок не бывает.
Я имею ввиду, что решение проблеммы ошибки в .Net или недостаточная производительность их решения — если бы они сделали многослойность (возможность делать тоже самое на более низком уровне) — это было бы хоть какое-то решение.
O>Еще раз повторю, не нужно делать из .NET панацею и спорить "нифига .NET не панацея". Да, .NET — не серебрянная пуля и не золотая таблетка. Просто удобная среда для определеннного класса задач. Возможно, сканнилка сети — не та задача, для которой удобно использовать .NET
Вот с этим я согласен — это я ранее писал...
O>Всё это здорово, когда у тебя цельное приложение. Как только появляются компоненты, плагины, аддоны, скрипты, их версионность, сопровождение и развёртывание — находится столько проблем, что гораздо проще использовать среду, для этого предназначенную. Да ты и сам знаешь, чего говорить
Ой не верю я в MS — тоже самое про COM и Java писалось — и что?
Всё таки есть прикол в том, что чем меньше программер понимает что происходит на низком уровне тем более плохой код он пишет. А в случае .Net кроме того он мало что может сделать с ошибкой — вон я RSDN.Home скачал — у него глюки и .Net их не спасает. А ещё меня убивает когда .Net-овская прога виснет на выходе — как это фиксать?
L>Нет я имею ввиду ошибки в самом .net — тут же ни чего не сделаешь... L>Я имею ввиду, что решение проблемы ошибки в .Net или недостаточная производительность их решения — если бы они сделали многослойность (возможность делать тоже самое на более низком уровне) — это было бы хоть какое-то решение.
Ошибки в JIT/GC? Опять же, в Java уже очень мало таких ошибок, думаю в .NET будет так же. Упирания лбом нет. Остальные ошибки можно обойти (опять же, .NET пока еще довольно сырой...).
Производительность? Есть MC++, если уж сильно приспичет. Но опять же пример — вполне конкретные приложения, RSDN@Home, WebMatrix, ... — меня вполне удовлетворяют своей производительностью (и стоимостью ), не думаю, что на C++ (например) они были бы существенно быстрее.
(Если почитать Рихтера, так он вообще говорит, что .NET может быть быстрее native-языков. В чем-то он прав.)
Еще интересно посмотреть тесты, как ведут себя GC/C++ Heap в условиях сервера. Тут уже неоднократно говорили, что GC в этом случае лучше (у C++ сильно фрагментирется куча).
L>Я имею ввиду, что решение проблеммы ошибки в .Net или недостаточная производительность их решения — если бы они сделали многослойность (возможность делать тоже самое на более низком уровне) — это было бы хоть какое-то решение.
MC++. Вполне низкий уровень.
O>>Всё это здорово, когда у тебя цельное приложение. Как только появляются компоненты, плагины, аддоны, скрипты, их версионность, сопровождение и развёртывание — находится столько проблем, что гораздо проще использовать среду, для этого предназначенную. Да ты и сам знаешь, чего говорить
L>Ой не верю я в MS — тоже самое про COM и Java писалось — и что?
COM — сложен и уродлив . Java — слишком непрактична. Хотя если глянуть на NetBeans, например... На C++ такое написать, имхо, тяжко (модульность/плагины/затраченные ресурсы), если вообще возможно... Так что надежда на .NET еще есть...
L>Всё таки есть прикол в том, что чем меньше программер понимает что происходит на низком уровне тем более плохой код он пишет.
Понимать — да. Но вот постоянно влазить в это дело — имхо не стоит, лучше от этого защититься языком/RunTime-ом (а если уж нужно нечто низкоуровневое — опять MC++!).
L>А в случае .Net кроме того он мало что может сделать с ошибкой — вон я RSDN.Home скачал — у него глюки и .Net их не спасает. А ещё меня убивает когда .Net-овская прога виснет на выходе — как это фиксать?
У меня такое ощущение (быть может слишком голословное, но по моим наблюдениям это так), что RSDN@Home писался быстро и несколько на халяву (да простят меня разработчики!), потому и глюки. И тем не менее работает. Я думаю, такой же проект на C++ при тех же потраченных ресурсах имел бы больше серьезных глюков и меньшую функциональность. Хотя это чисто умозаключительное имхо, подкрепленное парой фактов .
P.S. Напоследок процитирую m.a.g-а :
Самое интересное — никто не может сказать, чем она радикально лучше. В нашей компании все относились к .NET критически, до тех пор, пока сами не пробовали на ней написать что-либо. Буквально за пару дней человек превращался из скептика в горячего приверженца.
Здравствуйте, WFrag, Вы писали:
WF> Еще интересно посмотреть тесты, как ведут себя GC/C++ Heap в условиях сервера. Тут уже неоднократно говорили, что GC в этом случае лучше (у C++ сильно фрагментирется куча).
Тут место тонкое: теоретически в Си++ мы имеем все возможности управлять памятью наитончайшим образом, так что никаким дотнетам не догнать. Но практически в прикладных программах даже уход от стандартных new/delete редок, не говоря уж о каких-то изощренных политиках управления памятью.
Здравствуйте, Znow, Вы писали:
Z>Здравствуйте, WFrag, Вы писали:
WF>> Еще интересно посмотреть тесты, как ведут себя GC/C++ Heap в условиях сервера. Тут уже неоднократно говорили, что GC в этом случае лучше (у C++ сильно фрагментирется куча).
Z>Тут место тонкое: теоретически в Си++ мы имеем все возможности управлять памятью наитончайшим образом, так что никаким дотнетам не догнать. Но практически в прикладных программах даже уход от стандартных new/delete редок, не говоря уж о каких-то изощренных политиках управления памятью.
Ну опять же, я имею ввиду при разумных ресурсах/затратах памяти. Если это наитончайшее управление памяти будет стоить в 10 раз дороже — кому оно такое нужно (да еще если это наитончайшее управление памятью в результате и выродится в GC)?
1) Выделяем на всю память объектов размера 100 байт (например)
2) Освобождаем их ( половину, через один )
3) Пытаемся выделить объекты размера 1k
Получаем, что без дефрагментации кучи нифига мы не получим. А дефрагментация кучи — это и есть шаг к GC!
Здравствуйте, lboss, Вы писали:
L>Я про Delphi не понял — это к чему? Если интересует как сделан Heap — глянь в его сорцы.
Повторяю — там рассмотрена работа одного из самых быстрых хипов в мире. Можешь убедиться, что даже он выделяет память вовсе не за O(1). L>Но в любом случае этот флейм уже ни о чём — делаешь просто: L>1. Берешь реальный C++ проект, используя _CrtSetAllocHook — логируешь операции с памятью L>2. Создаешь тесты — и смотришь что быстрее... У меня GC проигрывает... и сильно...
Нет, все еще проще — идешь читать статью на RSDN, посвященную тестированию производительности GС vs Heap. Смотришь в результаты. Если недоволен ими, то обоснованно критикуешь методику тестов. Можешь позапускать тесты у себя.
Заканчивать действительно пора. Я сюда больше писать не буду, пока ты не прочиаешь-таки статьи и не начнешь обоснованно аргументировать свое несогласие с ними.
... << RSDN@Home 1.0 beta 6a >>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.