Фрагмент (очень неполный) читает нечто по протоколу superset of http
Комментарии в тексте мои.
Внимание! я не критикую автора. Я просто хочу обратить внимание
на то как safe код фактически рушит систему — код работал на клиенте
и возникла потребность перенсти его на сервер. Сервер не сказать
чтобы умер — просто перестал "серверить".
class ReaderThread extends Thread
{
InputStream input_stream = null;
Socket socket = null;
ByteBuffer readBuffer = new ByteBuffer();
ByteBuffer line = new ByteBuffer();
....
public void run ()
{
....
// Читаем посимвольно - набиваем буфер.
// сюда мы попадаем не для каждого IP адресаwhile( (ch = input_stream.read()) != -1 )
{
....
if(конец строки и еще кое что)
....
// Пеночка №1: чтобы сделать нечто полезное с текстовыми (ASCII)
// данными их надо в строку widechar загнать.
// Не барское это дело с bytes работать.
// Реаллокация буфера №1 - кол-во байт +2N.
String header_line = new String( line.get() );
// Пеночка №2: делаем еще одну строку потому как нам надо
// регистронезависимый парсинг делать.
// Реаллокация буфера №2 - кол-во байт +2N+2N.
header_line = header_line.toUpperCase().substring( 0, len - 2 );
// Теперь собсвенно вызываем startsWith - для чего и делалась вся
// бодяга выше.if( header_line.startsWith( HttpHeader.HTTP_CONTENT_LENGTH ) )
{
// Щаз будем парсить.
// Аллокация объекта - сколько ест - то нам не ведомо.
StringTokenizer v = new StringTokenizer(header_line, ": ");
// Теперича значить толкаем на стек try frame
// потому как нужно ловить NumberFormatException в Integer.parseInttry{
v.nextToken();
v.nextToken(" ");
ContentLen = Integer.parseInt( v.nextToken() );
}catch(Exception e3){}
}
}
}
}
}
}
Итого загрузка 1мб файла вызывает аллокацию 5мб памяти. Вот серверок-то и дохнет....
100 тредов и "шоб ви жили на один page file"
Резюме: Наличие высокоуровневых языков с GC и библиотек это конечно здорово, но!
результат который вот реально получился тот же примерно что и поймать GPF в С++.
Для нахождения где оно и как оно клинит сервер ушел один день — ровно столько сколько
бы вызвало устранение GPF.
Еще раз ничего личного ни про Java ни про другие фреймворки.
Просто разработка надежного кода занимает ровно то же самое время что с что без.
Глубокое заблуждение что если managed code то типа надежная система автоматом.
Здравствуйте, c-smile, Вы писали:
CS>Итого загрузка 1мб файла вызывает аллокацию 5мб памяти. Вот серверок-то и дохнет.... CS>100 тредов и "шоб ви жили на один page file"
CS>Резюме: Наличие высокоуровневых языков с GC и библиотек это конечно здорово, но! CS>результат который вот реально получился тот же примерно что и поймать GPF в С++. CS>Для нахождения где оно и как оно клинит сервер ушел один день — ровно столько сколько CS>бы вызвало устранение GPF.
CS>Еще раз ничего личного ни про Java ни про другие фреймворки. CS>Просто разработка надежного кода занимает ровно то же самое время что с что без. CS>Глубокое заблуждение что если managed code то типа надежная система автоматом.
Тут есть нюанс: система не выдержала стресс-тест, но в комфортных условиях работала бы себе на здоровье.
Кстати говоря, родить такую же фигню на unmanaged — без проблем; точно так же будет жить в комфорте и так же не выдержит стресс.
А вот код с расстрелами памяти — это уже как повезёт, ибо UB.
Возможно, управляемые языки в большей степени попустительствуют написанию расточительных алгоритмов, чем неуправляемые (где внимание программиста приковано к проблемам памяти, и шанс заметить глупость такого рода больше).
В том же С встал бы выбор: или написать конвейер для посимвольной разборки, или нагородить кучу malloc'ов. Думаю, что лень-матушка его остановила бы. А в С++ — без проблем: строку раз, строку два, вектор строк три... И эта штука будет очень прозрачна для понимания (в отличие от чисто потоковой версии) и столь же прожорлива.
CS>Вот такой вот показательный пример,
CS>Комментарии в тексте мои. CS>Внимание! я не критикую автора. Я просто хочу обратить внимание CS>на то как safe код фактически рушит систему — код работал на клиенте CS>и возникла потребность перенсти его на сервер. Сервер не сказать CS>чтобы умер — просто перестал "серверить".
Вообще то, перенос клиентского кода на сервер ни к чему хорошему не приведет(скорее всего), не важно, на чем и как написан код, дело не в managed/unmanaged, а в совершенно разных требованиях предъявляемых к клиентскому м серверному коду.
Немножко странный пример, сродни: взяли иномарку(не повышенной проходимости) и поехали по русской деревне. Ай-ай она застряла на бездорожъе...
CS>Итого загрузка 1мб файла вызывает аллокацию 5мб памяти. Вот серверок-то и дохнет.... CS>100 тредов и "шоб ви жили на один page file"
100 тредов — это уже операционке не слишком то хорошо, тут хотя б тред пул можно поюзать на сервере, в сочетании с вызовом сборки после обработки нского числа обращений клиентов, хотя опять же надо эксперементировать.
CS>Глубокое заблуждение что если managed code то типа надежная система автоматом.
Автоматом надежных систем не бывает, вроде это и так понятно.
Возвратимся к машинам: дорогая иномарка не избавляет нас от необходимости уметь водить и соблюдать правила, она избавляет от излишнего гемора с постоянными ремонтами мелких и средних поломок, и дает дополнительный комфорт при использовании.
CS>Внимание! я не критикую автора. Я просто хочу обратить внимание CS>на то как safe код фактически рушит систему — код работал на клиенте CS>и возникла потребность перенсти его на сервер. Сервер не сказать CS>чтобы умер — просто перестал "серверить".
Ага, при этом если бы человек начал писать данный код оптимально, потратив в 2-3 раза времени больше (с учетом отладки и поиска ошибок), то получил бы нагоняй от менеджера за то что занимается gold plating-ом и срывает сроки.
Мораль имхо можно вынести из этой истории одну: каждый код имеет свой scope использования, следовательно не стоит надеятся что код написанный для взаимодействия с пользователем будет также хорошо работать с real-time системами... хотя вроде бы это и так понятно
CS>Резюме: Наличие высокоуровневых языков с GC и библиотек это конечно здорово, но! CS>результат который вот реально получился тот же примерно что и поймать GPF в С++. CS>Для нахождения где оно и как оно клинит сервер ушел один день — ровно столько сколько CS>бы вызвало устранение GPF.
Наличией высокоуровневых библиотек это здорово, потому что сокращает время разработки, позволяет разрабатывать более сложные системы, меньше выполняя закатов солнца вручную, уменьшает количество ошибок.
НО! системы с автоматическим управлением памятью имеют свои ньюансы, которые нужно учитывать при разработке.
Также, нужно четко прописывать scope применения кода.
А уж о том что Sting immutable и о том как правильно их готовить написана целая куча книжек.
CS>Просто разработка надежного кода занимает ровно то же самое время что с что без.
ну не стоит так однозначно! на некоторых задачах быстрее и удобней. на некоторых наоборот.
например в одной из книжек по оптимизации Java автор писал как раз сервер, где основной оптимизацией был уход от String и переход на байты. Быстрее стало в результате на несколько порядков.. но код выглядел...
Смысл2: уровень сложности задачи требует соответствующего уровня разработчика. Опытный разработчик напишет большую и сложную систему на Java/С# быстрее чем например на С, неопытный: на С — вообще не напишет, а на Java\C# напишет чего нить страшное и еле работающее.
Хотя с другой стороны низкий порог вхождения в язык конечно означает более низкий уровень качества по индустрии в целом, но с другой стороны в большинстве случаев и такого низкого уровня качества хватает.
CS>Глубокое заблуждение что если managed code то типа надежная система автоматом.
Хм, а где вы такое утверждение слышали? я вот в первый раз его встретил в вашем сообщении
CS>Вот такой вот показательный пример,
CS>Фрагмент (очень неполный) читает нечто по протоколу superset of http
CS>Комментарии в тексте мои. CS>Внимание! я не критикую автора. Я просто хочу обратить внимание CS>на то как safe код фактически рушит систему — код работал на клиенте CS>и возникла потребность перенсти его на сервер. Сервер не сказать CS>чтобы умер — просто перестал "серверить".
CS>
CS>class ReaderThread extends Thread {
<...>
CS> public void run () {
<...>
CS> }
CS>}
CS>
CS>Итого загрузка 1мб файла вызывает аллокацию 5мб памяти. Вот серверок-то и дохнет.... CS>100 тредов и "шоб ви жили на один page file"
Аллокация пустого объекта без методов в памяти Java занимает порядка 8 байт (вместе с RTTI). Если не прав — пусть поправят, но я где-то встретил именно такую цифру и запомнил.
Что касается приведённого кода, то он не оптимален с нескольких точек зрения:
* поток не может быть использован повторно и уничтожается GC при завершении метода run();
* в теле метода run() порождаются новые объекты и не самым качественным образом;
* нет реакции не только на NumberFormatException в Integer.parseInt (что можно было бы объяснить ненужностью этого), но и на ВСЕ(без исключения!) исключения: (catch(Exception e3){})
Для сервера этот код однозначно не годится, так как потребует для своего обслуживания слишком много процессорного времени. Для персоналки — вполне подходит.
CS>Резюме: Наличие высокоуровневых языков с GC и библиотек это конечно здорово, но! CS>результат который вот реально получился тот же примерно что и поймать GPF в С++. Для нахождения где оно и как оно клинит сервер ушел один день — ровно столько сколько бы вызвало устранение GPF.
Как бы Вам объяснить.
Этот код, как бы он плох не был, не может вызвать GPF и отказ операционной системы, но вполне может привести к временному DoS (отказ в обслуживании), вызванному исчерпанием свободной памяти при массовых запросах на обслуживание. При этом в отличие от систем, написанных на C/C++, краха системы не произойдёт, она лишь остановится на время работы сборщика мусора и рекуперации файла подкачки. Код вполне надёжен, если не признать угрозу DoS.
CS>Просто разработка надежного кода занимает ровно то же самое время что с что без.
Вы не правы.
Всегда разработка надёжного кода требует дополнительного времени.
Чтобы оптимизировать код для сервера, нужно применить совершенно другие техники программирования:
* пулинг потоков обработки запросов;
* повторное использование объектов;
* повышение надёжности синхронизации и защиты объектов;
* выявить узкие места производительности и устранить "бутылочные горлышки" для потоков данных;
* и т.д., и т.п.
Так как критичность работы сервера имеет гораздо важное значение, чем работа персоналки, серверному коду уделяется большее внимание, чем десктопному. СS>Глубокое заблуждение что если managed code то типа надежная система автоматом.
Управляемый код автоматом решает лишь половину проблем надёжности систем.
Этот код плох. И для клиента и для сервера. По любому 5 мб на один это извиняюсь ... Другого слова у меня нет.
Наличие String.startsWidth конечно радует в "удобной" библиотеке, но
лично меня радует больше наличие "unsafe" strncmpi() которая одна только в приведенном
примере убирает + 2N + 2N требуемой памяти. .
Простую strncmpi можно было бы и написать для данного конкретного контекста руками (три строки), но
мы имеем следующий мифический посыл :
"Наличией высокоуровневых библиотек ... сокращает время разработки, позволяет разрабатывать более сложные системы, меньше выполняя закатов солнца вручную, уменьшает количество ошибок." (с) savaDAN
т.е. писать strncmpi не судьба. Платим временем не на первом этапе, но на втором, что хуже в разы.
Далее:
Этот код, как бы он плох не был, не может вызвать GPF и отказ операционной системы, но вполне может привести к временному DoS (отказ в обслуживании), вызванному исчерпанием свободной памяти при массовых запросах на обслуживание.
(с) iZEN
Смею утверждать следующее: GPF в данном конкретном случае лучше. Он заставляет что-то делать сразу и показывает место где именно это произошло. Сейчас оно молча вешает сервак и заставляет верещать load balancer. При этом никто не понимал что оно и почему оно. Все же вроде работает... Пришлось написать достаточное количество кода для логов, останавливать живой сервер, перезапускать и т.д.
В итоге (работающая система) имеем соизмеримое время разработки что для Java что для C.
Далее:
Вообще то, перенос клиентского кода на сервер ни к чему хорошему не приведет(скорее всего), не важно, на чем и как написан код, дело не в managed/unmanaged, а в совершенно разных требованиях предъявляемых к клиентскому м серверному коду.
(С) Nickolay Ch.
Смею утверждать следущее: если код написан правильно то ему все равно где работать — на сервере или на клиенте — он просто будет работать.
Согласен что "дело не в managed/unmanaged". Все дело в мифах "память больше не ресурс", "наличие высокоуровневых библиотек" и пр. эзотерике. Просто эти мифы сильно понижают планку требований к разработчикам. Особенно в сознании менеджмента который в свою очередь если покупается на такое посещает ту же группу детского сада.
Прошу обратить внимание — я не говорю о том что уровень конкретных разарабтсиков низкий — я говорю о том что мифы создают условия когда профессионалы *вынуждены* писать такое.
Тут на форуме был показательный пример про "Шустрики..."
Графический код написанный с использованием стандартной билиотеки и рекомендованных средств удобного языка
потребовал "недюженной работы мозга" профессионала. В результате по затратам получилось времени больше чем на голимом С и в лоб. Я об этом.
Здравствуйте, vladserge, Вы писали:
V>Здравствуйте, c-smile, Вы писали:
V>Как я с Вами согласен. V>И подобная дичь повсеместно, даже (о ужас!) в базовых библиотеках (JDK) и примерах их использования! V>
Угу, вот конфетки из дистрибутива PersonalJava от Sun
// Щаз, пацаны, мы покажем как писать надежный метод надежной библиотеки.
// Вот типа шоб враги, значить, нашу унутренню minSize (типа Dimension)
// грязными руками (омытыми водами Ганга), значить, не похакали мы ея
// типа скопируем шоб, значить, не напрягать мозг созданием
// immutable Dimension класса. Ну типа он же у нас уже есть, фигли тада напрягаться?public synchronized Dimension getPreferredSize(int rows, int cols) {
return new Dimension(minSize);
}
// "AWT есть но не работает!"
// "Та що ви говорите? От дасада... А зато душа в ней гарна, сил нет..."
// ...
// "Не... в то место моя щира душа не поместится...."
CS>Вот такой вот показательный пример,
CS>Фрагмент (очень неполный) читает нечто по протоколу superset of http
... CS>Итого загрузка 1мб файла вызывает аллокацию 5мб памяти. Вот серверок-то и дохнет.... CS>100 тредов и "шоб ви жили на один page file"
Интересно, но там же чтение по строкам. Каждая отдельная строка не больше нескольких десятков байт. Строка испльзуется и сразу выбрасывается, и память сразу становится garbage collectible. Выделение памяти в GC происходит быстро. А в данном случае выделенная память даже не переходит во следующее поколение — GC при первом же проходе её собирает. Поэтому 5мб — это что называется reference set, а не working set.
Коротко живужие объекты — это как раз то, на что затачивается GC. Использовать их в managed коде (будь то Java или .NET) совсем не зазорно. Я бы даже сказал, что другого выбора там вобщем то и нет, так как на стеке объекты создавать нельзя.
Смотрю, я на этот код и ведь ничего особенно криминального в нём не вижу. Ну, используется в нём в пять раз больше памяти, чем в оптимальном варианте, и что? Объекты все короткоживущие. Кроме нагрузки на GC никакого ужерба они не приносят.
Потом мне кажется ты неадыкватно реагируешь на подобные вещи. По сути дела, у вас на сервере обнаружился bottleneck, который вы нашли и пофиксили. Я уверен, что это не первый и не последний. Писать код, чтобы никаких bottleneck'ов не было невозможно. Причем сразу сказать, где этот bottleneck будет, невозможно. Мы сначала пишем код, потом профилируем, потом оптимизируем. Стандартная схема. Я не вижу, как твой пример является чем-то из ряда вон выходящим.
CS>Еще раз ничего личного ни про Java ни про другие фреймворки. CS>Просто разработка надежного кода занимает ровно то же самое время что с что без. CS>Глубокое заблуждение что если managed code то типа надежная система автоматом.
Как бы согласен и одновременно не согласен. Естественно, managed code не значит, что система получится надёжной автоматом. Однако, если говорить об уровне абстракции, в варианте "с" она выше, чем в варианте "без". А при более высоком уровне абстракции код писать всё таки легче и надёжнее (вне зависимости от языка программирования). Другое дело, что отдельные места могут потребовать оптимизации. И тогда мы можем в этих конкретных местах уровень абстракции понизить, чтобы добиться требуемой производительности.
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, c-smile, Вы писали:
CS>>Вот такой вот показательный пример,
CS>>Фрагмент (очень неполный) читает нечто по протоколу superset of http A>... CS>>Итого загрузка 1мб файла вызывает аллокацию 5мб памяти. Вот серверок-то и дохнет.... CS>>100 тредов и "шоб ви жили на один page file"
A>Интересно, но там же чтение по строкам. Каждая отдельная строка не больше нескольких десятков байт. Строка испльзуется и сразу выбрасывается, и память сразу становится garbage collectible. Выделение памяти в GC происходит быстро. А в данном случае выделенная память даже не переходит во следующее поколение — GC при первом же проходе её собирает. Поэтому 5мб — это что называется reference set, а не working set.
Во! Got one more: "GC он умный"
Обрати внимание там стоит такая штука:
class ReaderThread extends Thread {
public void run ()
{
}
}
продолжать надо?
A>Коротко живужие объекты — это как раз то, на что затачивается GC. Использовать их в managed коде (будь то Java или .NET) совсем не зазорно. Я бы даже сказал, что другого выбора там вобщем то и нет, так как на стеке объекты создавать нельзя.
Согласен. Только бы еще флажок бы где у того new ....
new (кылянусь-shortliving, threadlocal-зуб-даю)
Если без приколов то на практике поимели в результате тестов следующее
Execution time:
1 thread per machine — 2 секунды в run().
3 threads per machine — 8.5 секунды в run() для каждой thread (sic!).
Дальше идет суровая экспонента.
На самом деле там еще есть такого рода штуки.
А сервер уходит в глубокий GC c context switching. А внешне все класс — лампады моргают.
Здравствуйте, c-smile, Вы писали:
CS>Во! Got one more: "GC он умный"
CS>Обрати внимание там стоит такая штука:
CS>
CS>class ReaderThread extends Thread {
CS> public void run ()
CS> {
CS> }
CS>}
CS>
CS>продолжать надо?
Может быть в этом и проблема? Создаёте поток на каждый запрос. Это не сильно помогает scalability. Вот цитата из Improving .NET Application Performance and Scalability:
Threading Guidelines
This section discusses guidelines that you can use to help improve threading
efficiency in ASP.NET. The guidelines include the following:
— Tune the thread pool by using the formula to reduce contention.
— Consider minIoThreads and minWorkerThreads for burst load.
— Do not create threads on a per-request basis.
— Avoid blocking threads.
A>>Коротко живужие объекты — это как раз то, на что затачивается GC. Использовать их в managed коде (будь то Java или .NET) совсем не зазорно. Я бы даже сказал, что другого выбора там вобщем то и нет, так как на стеке объекты создавать нельзя.
CS>Согласен. Только бы еще флажок бы где у того new .... CS>new (кылянусь-shortliving, threadlocal-зуб-даю)
Зачем? Для этого у GC есть поколения.
CS>Если без приколов то на практике поимели в результате тестов следующее CS>Execution time: CS>1 thread per machine — 2 секунды в run(). CS>3 threads per machine — 8.5 секунды в run() для каждой thread (sic!). CS>Дальше идет суровая экспонента. CS>На самом деле там еще есть такого рода штуки.
Даже 2 секунды в run() — это много.
CS>А сервер уходит в глубокий GC c context switching. А внешне все класс — лампады моргают.
Да, я ничего против не имею. Смотреть сколько времени серверное приложение проводит в GC — это первое дело. Если много, то искать, какой @$@#$ там выделяет. Если слишком часто собираются разные поколения, то искать, какой #@$%# выделяет и держит память.
Только вот код, который ты показал — это типичный метод программирования в управляемых средах. За свой опыт я понял, что очень часто совсем не представляешь, сколько же памяти потребляет та или иная операция в .NET. Если можешь оценить на уровне О-больших, то это уже хорошо. Необходимость профилировать выделение памяти в managed code встаёт гораздо чаще чем в native. В этом есть интересный парадокс. Казалось бы, с появлением GC проблем с памятью быть должно меньше. А получается, что появляется нужда отслеживать перевыделение, которое в средах без GC является второстепенной задачей.
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, c-smile, Вы писали:
CS>>Во! Got one more: "GC он умный"
CS>>Обрати внимание там стоит такая штука:
CS>>
CS>>class ReaderThread extends Thread {
CS>> public void run ()
CS>> {
CS>> }
CS>>}
CS>>
CS>>продолжать надо?
A>Может быть в этом и проблема? Создаёте поток на каждый запрос. Это не сильно помогает scalability. Вот цитата из Improving .NET Application Performance and Scalability: A>
A>Threading Guidelines
A>This section discusses guidelines that you can use to help improve threading
A>efficiency in ASP.NET. The guidelines include the following:
A>- Tune the thread pool by using the formula to reduce contention.
A>- Consider minIoThreads and minWorkerThreads for burst load.
A>- Do not create threads on a per-request basis.
A>- Avoid blocking threads.
Нет проблема не в этом. (Понятно что thread pool это way to go)
Проблема в том что среди десяти threads появляется одна в которой
выполняется этот вот кусок. И все. Всем привет.
GC начинает останавливать все потоки. Когда они *все* остановились
тогда чистится мусор. Затем вся эта бодяга весело перезапускается.
Тут же выпадая в следующий осадок. Потому как тот IP на котором
работает приведенный фрагмент сидит на жирной трубе.
Как ты сам понимаешь выяснение причины в такого рода ситуациях —
шаманство чистой воды. Там где у тебя бы вывалилось not-enough-memory
этот виртуальный машин будет тужится но жить.
"Та нехай би вин вже помер,'га?"
A>>>Коротко живужие объекты — это как раз то, на что затачивается GC. Использовать их в managed коде (будь то Java или .NET) совсем не зазорно. Я бы даже сказал, что другого выбора там вобщем то и нет, так как на стеке объекты создавать нельзя.
CS>>Согласен. Только бы еще флажок бы где у того new .... CS>>new (кылянусь-shortliving, threadlocal-зуб-даю)
A>Зачем? Для этого у GC есть поколения.
Есть поколения и что? Не надо останавливать потоки?
Такого чуда имхо еще нет. В Java есть но в специфических продуктах.
В .NET по моему только в 2.0 должно появиться.
CS>>Если без приколов то на практике поимели в результате тестов следующее CS>>Execution time: CS>>1 thread per machine — 2 секунды в run(). CS>>3 threads per machine — 8.5 секунды в run() для каждой thread (sic!). CS>>Дальше идет суровая экспонента. CS>>На самом деле там еще есть такого рода штуки.
A>Даже 2 секунды в run() — это много.
Это очень хорошо для данной задачи.
A>Только вот код, который ты показал — это типичный метод программирования в управляемых средах.
Именно это я и говорю. Не мудрствуя лукаво берем типовое решение и получаем абздольц на ровном месте.
A>За свой опыт я понял, что очень часто совсем не представляешь, сколько же памяти потребляет та или иная операция в .NET. Если можешь оценить на уровне О-больших, то это уже хорошо. Необходимость профилировать выделение памяти в managed code встаёт гораздо чаще чем в native. В этом есть интересный парадокс. Казалось бы, с появлением GC проблем с памятью быть должно меньше. А получается, что появляется нужда отслеживать перевыделение, которое в средах без GC является второстепенной задачей.
Момент истины. Что и требовалось доказать.
И не надо говорить что программирование в managed environment это для домохозяек.
ИМХО Дело не в Java. Я видел огромное количество серверного неэффективного и ненадежного кода и на С, и на С++. Тут скорее проблема не в языке, а "в головах", то есть людях, пишущих такое.
Но в данном случае ИМХО это Ваша ошибка — не нужно было тащить клиентский код в серверный. Требования к клиентскому коду всегда гораздо мягче, чем к серверному. И никто в здравом уме не будет писать клиента с учетом серверных требований — дороговато выходит. Например, если я знаю, что клиент не будет держать больше 5~10 соединений, то видимо буду создавать по потоку на соединение, где обработка будет синхронной. Зачем мне усложнять себе жизнь и возиться с асинхронностью, следить за возможной дефрагментацией кучи, за скростью выделения памяти?...и т.д. и т.п. Конечно, я не говорю о том, что при написании клиента нужно на все плюнуть и писать спустя рукава, но и писать с учетом серверное специфики тоже не стоит
Здравствуйте, Игoрь, Вы писали:
И>И никто в здравом уме не будет писать клиента с учетом серверных требований — дороговато выходит. Например, если я знаю, что клиент не будет держать больше 5~10 соединений, то видимо буду создавать по потоку на соединение, где обработка будет синхронной.
Правда никто не будет, что ли?
Меня мама с детства учила, что программист должен уметь считать "ноль-один-много". Со скольких соединений начиная станем заморачиваться с асинхронностью? сколько кода уже будет к тому времени написано?
И>Зачем мне усложнять себе жизнь и возиться с асинхронностью, следить за возможной дефрагментацией кучи, за скростью выделения памяти?...и т.д. и т.п.
Вероятно, чтобы карму не испортить. Упростить поддержку, иначе говоря.
savaDAN,
> Опытный разработчик напишет большую и сложную систему на Java/С# быстрее чем например на С
Вот так вот сразу, без конкретизации, о какой именно системе идет речь?.. Немного информации о разработчике тоже бы не повредило, кроме того, что у него есть опыт...
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Игoрь, Вы писали:
И>Здравствуйте, c-smile, Вы писали:
И>ИМХО Дело не в Java. Я видел огромное количество серверного неэффективного и ненадежного кода и на С, и на С++. Тут скорее проблема не в языке, а "в головах", то есть людях, пишущих такое.
И>Но в данном случае ИМХО это Ваша ошибка — не нужно было тащить клиентский код в серверный. Требования к клиентскому коду всегда гораздо мягче, чем к серверному. И никто в здравом уме не будет писать клиента с учетом серверных требований — дороговато выходит.
почему всеравно писать приходится и серверный и клиентский код. не проще один раз написать и если оно заработает на сервере то разве небудет работать на клиенте?
И>Например, если я знаю, что клиент не будет держать больше 5~10 соединений, то видимо буду создавать по потоку на соединение, где обработка будет синхронной. Зачем мне усложнять себе жизнь и
CS>Смею утверждать следущее: если код написан правильно то ему все равно где работать — на сервере или на клиенте — он просто будет работать. CS>Согласен что "дело не в managed/unmanaged". Все дело в мифах "память больше не ресурс", "наличие высокоуровневых библиотек" и пр. эзотерике.
Смею утвержадать, что код должен писаться исходя из задачи, абсолютнов не бывает, уже не раз писал.
Здравствуйте, vnp, Вы писали:
vnp>Правда никто не будет, что ли? vnp>Меня мама с детства учила, что программист должен уметь считать "ноль-один-много".
Повезло Вам с мамой. vnp>Со скольких соединений начиная станем заморачиваться с асинхронностью? сколько кода уже будет к тому времени написано?
Я не очень люблю рассуждать о сферическом коне в вакууме. Но для типичного клиентского приложения 10 соединений это верхний предел (понятно, что бывают и исключения). А принцип выбора у меня простой. Анализирую требования к приложению и специфику его использования. На основании этой информации делаю оценку средней и пиковой нагрузок. А затем пытаюсь подобрать такую модель, которая способна будет выдержать нагрузку где-то на порядок больше. Скажем, для нашего коня в вакууме в среднем будет где-то 3~4 соединения, а пик ~10. В таком случае поток на соединение вполне катит. Понятно, что для высокопроизводительных серверов нужно сразу выжимать максимум и сделать с запасом на порядок не получится.
Вообще не понимаю о чем Вы спорите, специфика клиентских и серверных приложений серьезно отличается.
И>>Зачем мне усложнять себе жизнь и возиться с асинхронностью, следить за возможной дефрагментацией кучи, за скростью выделения памяти?...и т.д. и т.п. vnp>Вероятно, чтобы карму не испортить.
А Вас мама не учила, что карма, еще бубен — не наши термины?
vnp>Упростить поддержку, иначе говоря.
Эээ, может я не понял... Вы хотите сказать, что всякие асинхронные навороты, свой распределитель памяти и другие виды оптимизации, присущие серверам, упрощают поддержку? Да Вы еще месяцы будете вылавливать там баги.
Когда-то я учавствовал в одном проекте, где главной целью поставили универсальность и обобщенность интерфейсов. Когда я спрашивал, а нафига это? Мне отвечали: "А вдруг кому-то захочется вот так сделать." Ох как я тогда наматюкался и наплевался... После этого я для себя решил, что все хорошо в меру, если нужно спроектировать подводную лодку, то не стоит в нее закладывать возможность летать — ничего хорошего из этого не выйдет, получим очередного "ужа с ежом". Поэтому, если проектируем клиента, то не стоит в него закладывать возможность в дальнейшем стать сервером.
Здравствуйте, vladserge, Вы писали:
V>Здравствуйте, Игoрь, Вы писали:
И>>Здравствуйте, c-smile, Вы писали:
И>>ИМХО Дело не в Java. Я видел огромное количество серверного неэффективного и ненадежного кода и на С, и на С++. Тут скорее проблема не в языке, а "в головах", то есть людях, пишущих такое.
И>>Но в данном случае ИМХО это Ваша ошибка — не нужно было тащить клиентский код в серверный. Требования к клиентскому коду всегда гораздо мягче, чем к серверному. И никто в здравом уме не будет писать клиента с учетом серверных требований — дороговато выходит.
V>почему всеравно писать приходится и серверный и клиентский код. не проще один раз написать и если оно заработает на сервере то разве небудет работать на клиенте?
Вообще-то я говорил о другой ситуации — перенос кода с клиентской части на серверную. Что касается Вашего случая... тяжело вот так обобщенно ответить, все зависит от требований. Лично мне ни разу не приходилось что-то подобное делать. Если Вы знаете такого рода open source проекты, киньте ссылки я бы с удовольствием посмотрел. Достаточно часто сервер затачивается под конкретную ОС для достижения лучшей производительности, в то время как клиентов стараются делать кроссплатформенными...
И>>Например, если я знаю, что клиент не будет держать больше 5~10 соединений, то видимо буду создавать по потоку на соединение, где обработка будет синхронной. Зачем мне усложнять себе жизнь и
V>типа, нафига головой думать, мне не за это плотют
Думать нужно, но не стоит пытаться делать каждую фичу супер навороченной — это никому не нужно и никто не оценит, только позже поимеете проблем на этапе тестирования и сопровождения.
Здравствуйте, Nickolay Ch, Вы писали:
CS>>Смею утверждать следущее: если код написан правильно то ему все равно где работать — на сервере или на клиенте — он просто будет работать. CS>>Согласен что "дело не в managed/unmanaged". Все дело в мифах "память больше не ресурс", "наличие высокоуровневых библиотек" и пр. эзотерике. NC>Смею утвержадать, что код должен писаться исходя из задачи, абсолютнов не бывает, уже не раз писал.
Извиняюсь но как минимум код должен разрабатываться с применением инженерной совести.
А специфика задачи...
Ну вот пример мой htmlayout — это UI компонента чистой воды, ведь так?
Пришли господа-товарищи и сказали хотим на сервере из html pdf делать.
И делают. Делов было на три дня для них.
Абсолютов, да — не бывает и также объять необъятное сложно.
Писать эффективный код экономически целесообразно. Но это песня для отдельного
топика — когда, кем и где.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Вот так вот сразу, без конкретизации, о какой именно системе идет речь?.. Немного информации о разработчике тоже бы не повредило, кроме того, что у него есть опыт...
С почти сабсэт от C#, так что ерунду говоришь. Тут достаточно информации о том что система большая и сложная.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
CS>Угу, вот конфетки из дистрибутива PersonalJava от Sun
CS>
CS> // Щаз, пацаны, мы покажем как писать надежный метод надежной библиотеки.
CS> // Вот типа шоб враги, значить, нашу унутренню minSize (типа Dimension)
CS> // грязными руками (омытыми водами Ганга), значить, не похакали мы ея
CS> // типа скопируем шоб, значить, не напрягать мозг созданием
CS> // immutable Dimension класса. Ну типа он же у нас уже есть, фигли тада напрягаться?
CS> public synchronized Dimension getPreferredSize(int rows, int cols) {
CS> return new Dimension(minSize);
CS> }
CS> // "AWT есть но не работает!"
CS> // "Та що ви говорите? От дасада... А зато душа в ней гарна, сил нет..."
CS> // ...
CS> // "Не... в то место моя щира душа не поместится...."
CS>
Изумительный пример мировозрения битовыжимателей. Типа не потимально!!! Объект лишний создают!!! Поибивалбы...
В условиях Явы это единственно верный выход. Типы то опчти все ссылочные. Так что отдать внутенний объект == послать на... всю инкапсуляцию.
Медленно говоришь? Ну, что же подождем Явы 6 (1.6) и проверим насколько это медленно и кто был прав. Думаю, прав был тот кто написал этогт код, так проблемы производительности вызванные подобными решениями дожен решать компилтор, а плевать на инкапсуляцию все же не стоит.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Павел Кузнецов, Вы писали:
ПК>>Вот так вот сразу, без конкретизации, о какой именно системе идет речь?.. Немного информации о разработчике тоже бы не повредило, кроме того, что у него есть опыт...
VD>С почти сабсэт от C#, так что ерунду говоришь. Тут достаточно информации о том что система большая и сложная.
Ну здрастье, Настя!
Это умозаключение произошло в результате
"Пописал на С++... долго думал",
я так понимаю.
Или давай тогда колись как эта мысль тебе в голову пришла.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, c-smile, Вы писали:
CS>>Угу, вот конфетки из дистрибутива PersonalJava от Sun
CS>>
CS>> // "AWT есть но не работает!"
CS>> // "Та що ви говорите? От дасада... А зато душа в ней гарна, сил нет..."
CS>> // ...
CS>> // "Не... в то место моя щира душа не поместится...."
CS>>
VD>Изумительный пример мировозрения битовыжимателей. Типа не потимально!!! Объект лишний создают!!! Поибивалбы...
"Машина была как настоящая но не ехала"
VD>В условиях Явы это единственно верный выход. Типы то опчти все ссылочные. Так что отдать внутенний объект == послать на... всю инкапсуляцию.
А что нельзя ссылочный объект сделать read-only для снаружи?
VD>Медленно говоришь? Ну, что же подождем Явы 6 (1.6) ...
Влад, я уже этот форум читаю года четыре. И вот это твой оптимизм "подождем светлого будущего..."
просто перманентно греет душу.
Здравствуйте, c-smile, Вы писали:
CS>Ну здрастье, Настя!
Так ты девочка !
CS>Или давай тогда колись как эта мысль тебе в голову пришла.
Да как бы писал на обоих не по одному году.
По большому счету кроме препроцессора у С особо уникального ничено не увидел. Все остальное или 1 в один повтояется или чуть по другому, но без особых проблем. Шарп в ансэфе — это почти чистый С. Ну, разве что с пребабахами для интеграции с управляемыми данными.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, c-smile, Вы писали:
CS>А что нельзя ссылочный объект сделать read-only для снаружи?
Объект нельзя. Можно класс проектировать как анмьютебл. Но иногда ведь и чужими классами приходится пользоваться, а иногда бывают и другие соображения.
Приведенный тобой паттерн довольно распространент.
VD>>Медленно говоришь? Ну, что же подождем Явы 6 (1.6) ...
CS> Влад, я уже этот форум читаю года четыре. И вот это твой оптимизм "подождем светлого будущего..." CS>просто перманентно греет душу.
Выделение памяти в стеке
C++ дает программистам выбор между размещением объектов в куче или в стеке. Размещение в стеке эффективнее: выделение памяти дешевле, освобождение совсем ничего не стоит, а язык предоставляет поддержку при разметке сроков жизни объектов, снижая риск забыть освободить объект. С другой стороны, в C++ нужно быть очень внимательным при публикации или совместном использовании ссылок на размещенные в стеке объекты, поскольку они автоматически освобождаются при раскрутке фрейма стека, что приводит к появлению "висячих" указателей.
Еще одно достоинство размещения в стеке состоит в том, что оно куда лучше работает с кешем. На современных процессорах стоимость промаха мимо кеша весьма существенна, так что если язык и runtime могут помочь программе достичь лучшей локальности данных, производительность также повысится. Вершина стека в кеше практически всегда "горячая", а вершина кучи – "холодная" (поскольку с момента последнего использования памяти, скорее всего, прошло немало времени). В результате размещение объекта в куче скорее приведет к большему числу промахов мимо Кеша, чем размещение объекта в стеке.
Что еще хуже, промах мимо кеша при размещении объекта в куче приводит к весьма грязной работе с памятью. При выделении памяти из кучи содержание этой памяти является мусором – битами, оставшимися с момента последнего использования памяти. При выделении не хранящегося в кеше блока памяти из кучи, исполнение приостановится на время переноса содержимого этой памяти в кеш. Затем эти значения будут немедленно переписаны нулями или другими исходными значениями. Все это вместе означает большой объем напрасной работы с памятью (некоторые процессоры, например, Azul Vega, аппаратно ускоряют выделение памяти из кучи). Escape-анализ
Язык Java не предлагает никакого способа явно разместить объект в стеке, но это не мешает JVM при случае использовать размещение в стеке. JVM могут использовать технику, именуемую escape-анализом (escape analysis), который может определить, что определенные объекты остаются прикованными к определенному потоку на весь срок жизни, и что этот срок жизни ограничен сроком жизни данного фрейма стека. Такие объекты можно безопасно размещать в стеке вместо кучи. Даже лучше, в случае мелких объектов, JVM может полностью избавиться от выделения памяти и просто размещать поля объектов в регистрах.
Листинг 2 показывает пример применения escape-анализа. Метод Component.getLocation() создает защитную копию поля location, так что вызывающая сторона не может случайно изменить текущее расположение компонента. Вызов getDistanceFrom() сперва получает местоположение другого компонента (что включает создание объекта), а затем использует поля x и y объекта, возвращаемого getLocation(), для вычисления расстояния между двумя экземплярами компонентов. Листинг 2.
public class Point
{
private int x, y;
public Point(int x, int y)
{
this.x = x; this.y = y;
}
public Point(Point p) { this(p.x, p.y); }
public int getX() { return x; }
public int getY() { return y; }
public void setX(int newValue) { x = newValue; }
public void setY(int newValue) { y = newValue; }
}
public class Component
{
private Point location;
public Point getLocation() { return new Point(location); }
public double getDistanceFrom(Component other)
{
Point otherLocation = other.getLocation();
int deltaX = otherLocation.getX() - location.getX();
int deltaY = otherLocation.getY() - location.getY();
return Math.sqrt(deltaX*deltaX + deltaY*deltaY);
}
}
Метод getLocation() не знает, что вызывающая сторона собирается делать с возвращаемым им Point; она может удерживать ссылку на него, например, поместив ее в коллекцию, так что getLocation() написан в безопасной манере. Но в этом примере getDistanceFrom() не собирается модифицировать получаемые объекты или запоминать ссылки на них. Он просто собирается ненадолго задействовать Point, а затем избавиться от него, что в данном случае выглядит как разбазаривание ресурсов.
Хорошая JVM может разобраться в происходящем и избавиться от размещения защитной копии. Сначала вместо вызова getLocation() будет подставлено (inlined) тело этого метода, то же будет сделано с вызовами getX() и getY(), в результате чего getDistanceFrom() станет выглядеть так, как показано в листинге 3. Листинг 3.
public double getDistanceFrom(Component other)
{
Point otherLocation = new Point(other.x, other.y);
int deltaX = otherLocation.x - location.x;
int deltaY = otherLocation.y - location.y;
return Math.sqrt(deltaX*deltaX + deltaY*deltaY);
}
Здесь escape-анализ может показать, что объект, создаваемый в первой строке, никогда не покинет своего базового блока и что getDistanceFrom() никогда не изменяет состояние компонента other (под "покинет" имеется в виду то, что ссылка на него не хранится в куче и не передается неизвестному коду, который может удерживать копию). При том, что Point действительно используется только в одном потоке и его время жизни, как известно, ограничено базовым блоком, в котором он размещен, он может быть либо размещен в стеке, либо полностью соптимизирован, как показано в листинге 4. Листинг 4.
public double getDistanceFrom(Component other)
{
int tempX = other.x, tempY = other.y;
int deltaX = tempX - location.x;
int deltaY = tempY - location.y;
return Math.sqrt(deltaX*deltaX + deltaY*deltaY);
}
В результате мы получаем точно такую же производительность, как если бы все поля были публичными, но с сохранением безопасности, предоставляемой инкапсуляцией и защитным копированием (и остальными техниками безопасного программирования). Escape-анализ в Mustang
Escape-анализ – это оптимизация, о которой говорилось уже давно, и вот, наконец, она здесь – текущие версии Mustang (Java SE 6) могут выполнять escape-анализ и конвертировать выделение памяти в куче в выделение памяти в стеке (или просто избавляться от выделения памяти) там, где это возможно. Использование escape-анализа для устранения некоторых распределений памяти приводит к еще большему ускорению работы с памятью, снижению расхода памяти и уменьшению количества промахов мимо кеша. Кроме того, это снижает нагрузку на сборщик мусора и позволяет реже производить сборку. Заключение
JVM удивительно хорошо делают вещи, которые раньше были полностью отданы на откуп разработчику. Позволяя JVM выбирать между выделением памяти в куче и в стеке, можно получить преимущества производительности выделения памяти в стеке, не заставляя программиста мучаться с выбором.
Brian Goetz
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
> <...> JVM могут использовать технику, именуемую escape-анализом (escape analysis), который может определить, что определенные объекты остаются прикованными к определенному потоку на весь срок жизни, и что этот срок жизни ограничен сроком жизни данного фрейма стека <...>
Это все, конечно, здорово, но пока что даже в области значительно более проработанной, а именно GC, автоматика достаточно серьезно отстает от грамотного ручного управления памятью, если в первом случае не дать очень существенный запас по памяти.
runtime performance of the best-performing garbage collector is competitive with explicit memory management when given enough memory. In particular, when garbage collection has five times as much memory as required, its runtime performance matches or slightly exceeds that of explicit memory management. However, garbage collection’s performance degrades substantially when it must use smaller heaps. With three times as much memory, it runs 17% slower on average, and with twice as much memory, it runs 70% slower. Garbage collection also is more susceptible to paging when physical memory is scarce. In such conditions, all of the garbage collectors we examine here suffer order-of-magnitude performance penalties relative to explicit memory management.
И это сравнение с достаточно старым алгоритмом Lea, а не с чем-нибудь новым типа Hoard, в присутствии множества параллельных потоков исполнения, как было в случае, описанном c-smile...
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, c-smile, Вы писали:
CS>Здравствуйте, ie, Вы писали:
ie>>Смотрел код индусов... много думал. ie>>Вот Ваш пост из той же оперы.
CS>Имею другое мнение здесь присутвующих: CS>
CS>Только вот код, который ты показал — это типичный метод программирования в управляемых средах.
ИМХО, это типичное мнение людей до конца непонимающих назначение управляемых сред. Неужели у Вас есть мнение, что приведенный код — это эталон управляемого кода?
Чем этот самый escape analysys лучше проверенного веками const?
Когда закончится это программирование на кофейной гущще когда
скорость выполнения программы зависит от положения Сатурна в момент исполнения?
public class Component
{
private Point location;
public const Point getLocation() { return location; }
public double getDistanceFrom(const Component other)
{
const Point otherLocation = other.getLocation();
int deltaX = otherLocation.getX() - location.getX();
int deltaY = otherLocation.getY() - location.getY();
return Math.sqrt(deltaX*deltaX + deltaY*deltaY);
}
}
Здравствуйте, ie, Вы писали:
ie>Здравствуйте, c-smile, Вы писали:
CS>>Здравствуйте, ie, Вы писали:
ie>>>Смотрел код индусов... много думал. ie>>>Вот Ваш пост из той же оперы.
CS>>Имею другое мнение здесь присутвующих: CS>>
CS>>Только вот код, который ты показал — это типичный метод программирования в управляемых средах.
ie>ИМХО, это типичное мнение людей до конца непонимающих назначение управляемых сред. Неужели у Вас есть мнение, что приведенный код — это эталон управляемого кода?
Свое мнение я уже изложил.
Это вот родной код фирмы Sun:
public synchronized Dimension getPreferredSize(int rows, int cols)
{
return new Dimension(minSize);
}
Вопрос: означенная фирма до конца ли понимает "назначение управляемых сред"? Как думаешь?
ПыСы: Там еще кстати замечательное такое слово synchronized используется. "Для знатоков штучка".
Здравствуйте, Сергей Губанов, Вы писали:
СГ>Просто в Java нет value-типов. Отсюда все эти оверхедные но вынужденно необходимые new, new, new... на каждый чих.
Просто в Java есть примитивные типы. "Отсюда все эти оверхедные но вынужденно необходимые new, new, new... на каждый чих."
>> Опытный разработчик напишет большую и сложную систему на Java/С# быстрее чем например на С ПК>Вот так вот сразу, без конкретизации, о какой именно системе идет речь?.. Немного информации о разработчике тоже бы не повредило, кроме того, что у него есть опыт...
опытный и талантлиовый разработчик напишет большую и сложную систему на любом языке, однако, тот же С#\Java ему поможет следующим (по сравнению с С):
1. классы — легче проектировать
2. управление памятью — меньше багов
3. большая стандартная библиотека — меньше кода писать.
т.е. усилий все таки придется потратить меньше.
А вообще квотированную вами фразу желательно рассматривать в общем контексте моего ответа господину c-smile-у.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Это все, конечно, здорово, но пока что даже в области значительно более проработанной, а именно GC, автоматика достаточно серьезно отстает от грамотного ручного управления памятью, если в первом случае не дать очень существенный запас по памяти.
Все относительно. Если не брать ручных оптимизаций для конкретных случаев (вроде пулов), то стандартные хипы ОС обычно проигрыват ЖЦ. Причем проигрыш этот не линейный. Чем больше фрагментируется куча, тем больше этот проигрыш.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, c-smile, Вы писали:
CS>Зачем все эти пляски с бубном?
CS>Чем этот самый escape analysys лучше проверенного веками const?
Хотя бы тем, что не заставляет клепать лишние конструкции ради оптимизации. Да сложность в общем-то не в самом анализе, а в переписывании кода.
К тому же const в С++ очень условная вещь. На него можно начьхать. А управляемых средах этот const пришлось бы распростронять на всю виртуальную машину. А это задача не тривиальная.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
CS>Извиняюсь но как минимум код должен разрабатываться с применением инженерной совести. CS>А специфика задачи...
Ну вот опять совесть полезла. Что такое совестьЮ тогда давайте пофлеймим, только уж лучше в Священных войнах.
Писать надо так, как целесообразней, сиречь, так, что быстрее привелет нас к результатую. Целесообразность целиком зависит от задачи.
Здравствуйте, savaDAN, Вы писали:
DAN>опытный и талантлиовый разработчик напишет большую и сложную систему на любом языке, однако, тот же С#\Java ему поможет следующим (по сравнению с С): DAN>1. классы — легче проектировать
В чем легче? Почему легче? именно опытному разработчику... DAN>2. управление памятью — меньше багов
Т.е. лики памяти опытного разработчика будут заботливо подчищены GC... Гм. не такой уж и опытный этот разработчик раз у него прога ликает. DAN>3. большая стандартная библиотека — меньше кода писать.
Т.е. надо писать на шарпах/жабе потому что там библиотека стандартная больше? Гм. нет ведь библиотеки на все случаи жизни... Где то больше, где то меньше... К примеру я игру разрабатываю. 3D шутер с навороченной графикой. Чем мне в этом поможет стандартная библиотека?
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
читал?
DAN>>2. управление памятью — меньше багов CC>Т.е. лики памяти опытного разработчика будут заботливо подчищены GC...
Про типобезопсность слышал?
CC> Гм. не такой уж и опытный этот разработчик раз у него прога ликает.
Это не такой он опытный елси верит, что у него нет ликов.
DAN>>3. большая стандартная библиотека — меньше кода писать. CC>Т.е. надо писать на шарпах/жабе потому что там библиотека стандартная больше? Гм. нет ведь библиотеки на все случаи жизни... Где то больше, где то меньше... К примеру я игру разрабатываю. 3D шутер с навороченной графикой. Чем мне в этом поможет стандартная библиотека?
Дык в любой программе есть куча объвязочного кода. Та же работа с ХМЛ. Тот же ГУИ. Но конечно для игр скорее будет интересна не библиотека, а компонентная модель и динамичность дотнета. Он может заменить и скрипты, и плагины и много чего еще. Прибавив сюда генерацию кода в рантайме и получаем тучу приемуществ.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Nickolay Ch, Вы писали:
CS>>Извиняюсь но как минимум код должен разрабатываться с применением инженерной совести. CS>>А специфика задачи...
NC>Ну вот опять совесть полезла. Что такое совестьЮ тогда давайте пофлеймим, только уж лучше в Священных войнах. NC>Писать надо так, как целесообразней, сиречь, так, что быстрее привелет нас к результатую. Целесообразность целиком зависит от задачи.
"как целесообразней" это как раз и есть часть этой самой совести.
Целесообразность включает в себя решения от глобальных проблем оптимального выбора инструмента/технологии
до целесообразности того или иного подхода на уровне конкретной функции.
Собственно весь этот топик и есть один большой разговор про целесообразность.
Идея состоит в том что как правило решение современной вычислительной задачи
(программы) не сильно зависит от того на чем — есть ли там managed framework или там unmanaged stdlib.
И то и то имеет тонны всяко разных классов и методов в конце концов. (Последнее кстати примерно на порядок больше всякого
имеет чем framework).
Постулирую: качество получаемой системы зависит от того знает ли менеджмент о том что какую
бы технологию они волевым порядком ни взяли а разработка все равно займет 9 месяцев
Выбор технологии дело сугубо техническое. При любом раскладе — уровень требования к исполнителям — одинаковый и не зависит
от того на чем писать.
Т.е. все эти трескучие лозунги это "желудок у котенка меньше наперстка". Следовать им нецелесообразно.
(чего-то то меня пробило на глобальные умозаключения, извиняюсь)
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, CreatorCray, Вы писали:
DAN>>>1. классы — легче проектировать CC>>В чем легче? Почему легче? именно опытному разработчику... VD>Вот это
читал?
читал. вот только в чем заключается это самое "легче" — там не написано.
Есть там кста одна хорошая фраза: "этот язык определяет способ их программистского мышления."
так вот, вы мыслите на уровне абстракций а я на уровне того, как именно оно будет выполняться.
Потому как работаю я с платформозависимым кодом. И большинство его должно выполняться быстро и ресурсы освобождать немедленно как только они перестали быть нужны. В любом языке с GC мне надо будет теребить этот самый GC ручками чтобы он не ковырял в носу а сразу убивал мусор.
Кстати о сборщике — глядя на янус я склоняюсь к мнению что не такая уж и умная это штука. База у меня всего то 137 метров а янус при работе умудряется отжирать 87 мб working set и 669 virtual... и при этом откровенно подтормаживать при переходе от ветки к ветке...
DAN>>>2. управление памятью — меньше багов CC>>Т.е. лики памяти опытного разработчика будут заботливо подчищены GC... VD>Про типобезопсность слышал?
слышал. для меня она выглядит как очень строгая проверка на этапе компиляции... И покуда кажется больше мешающей чем полезной.
Кстати никак не получается найти развернутое определение, что же именно включается в этот термин. Не поможете ссылкой?
CC>> Гм. не такой уж и опытный этот разработчик раз у него прога ликает. VD>Это не такой он опытный елси верит, что у него нет ликов.
Верить что лики есть и писать без ликов — все же разные вещи. Разумеется в "любой программе есть ошибки" (с) не помню.
Но у профи ИМХО таких ляпов как лик быть не должно.
VD>Та же работа с ХМЛ.
парсер пишется за короткое время на С++ и имеет нужную функциональность и большую скорость и удобство нежели вызов стандатной библы. VD>Тот же ГУИ.
уууу... посмотрите на ку4... Что из его ГУИ следует делать на библах .нета? VD>Но конечно для игр скорее будет интересна не библиотека, а компонентная модель и динамичность дотнета.
Как геймдевелопер могу сказать — что то пока никаких удобств не видно...
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Влад уже ответил, но не будем прятаться за спины титанов , кину и свои 5 копеек...
DAN>>1. классы — легче проектировать CC>В чем легче? Почему легче? именно опытному разработчику...
1. Классы это более высокий уровень абстракции. Чем более высоким уровнем абстракции вы манипулируете, тем больший кусок вы можете удержать и обработать в памяти (в голове). Собсно чем больше проект, тем это более важно.
Опытный разработчик имеет теже самые функциональные ограничения что и неопытный: в голове одновременно не более 7 предметов.
2. Классы это не только ценный мех, но и всякие другие приятные рюшки (хором): инкапсуляция и полиморфизм. Что позволяет писать систему более устойчивую к багам, что в свою очередь немало сокращает время разработки в целом.
DAN>>2. управление памятью — меньше багов CC>Т.е. лики памяти опытного разработчика будут заботливо подчищены GC... Гм. не такой уж и опытный этот разработчик раз у него прога ликает.
Не об этом речь. Баги делают все и опытные и неопытные. Просто у опытных меньше ляповых багов, и они их быстрее находят.
А речь вот о чем: в больших приложениях управление памятью геморрой еще тот — всякие там смартпоинтеры, которые толком не поддерживаются компилером, следовательно опять же больше ошибок которые крайне геморойно дебагировать и фиксить.
С другой стороны смею вас заверить, память отлично течет и системах с GC (особенно этим грешит VB6), но багов из за этого на порядок меньше, и искать и исправлять их тоже значительно проще.
DAN>>3. большая стандартная библиотека — меньше кода писать. CC>Т.е. надо писать на шарпах/жабе потому что там библиотека стандартная больше? Гм. нет ведь библиотеки на все случаи жизни... Где то больше, где то меньше... К примеру я игру разрабатываю. 3D шутер с навороченной графикой. Чем мне в этом поможет стандартная библиотека?
Как минимум автоматическая поддержка wide strings, коллекции, ввод\вывод, работа с временем/датами и пр. пр. пр.
Здравствуйте, savaDAN, Вы писали:
DAN>А речь вот о чем: в больших приложениях управление памятью геморрой еще тот — всякие там смартпоинтеры, которые толком не поддерживаются компилером, следовательно опять же больше ошибок которые крайне геморойно дебагировать и фиксить.
А можно вот об выделенном поподробнее?
И что ты считаешь большим приложением (больше 100 тысяч строк, 200, 500,...)?
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, c-smile, Вы писали:
CS>Проблема в том что среди десяти threads появляется одна в которой CS>выполняется этот вот кусок. И все. Всем привет. CS>GC начинает останавливать все потоки. Когда они *все* остановились CS>тогда чистится мусор. Затем вся эта бодяга весело перезапускается. CS>Тут же выпадая в следующий осадок. Потому как тот IP на котором CS>работает приведенный фрагмент сидит на жирной трубе.
A>>Зачем? Для этого у GC есть поколения.
CS>Есть поколения и что? Не надо останавливать потоки? CS>Такого чуда имхо еще нет. В Java есть но в специфических продуктах.
afair, в 1.5 есть конкурентные сборщики не только для "молодого" поколения (который "parallel"), но и для tenured (сборщик "concurent"). Он останавливает потоки не на всё время сборки мусора.
Можно попробовать молодое поколение побольше сделать. Вы какие крутилки у ВМ крутили?
DAN>>А речь вот о чем: в больших приложениях управление памятью геморрой еще тот — всякие там смартпоинтеры, которые толком не поддерживаются компилером, следовательно опять же больше ошибок которые крайне геморойно дебагировать и фиксить.
E>А можно вот об выделенном поподробнее?
что именно подробней? E>И что ты считаешь большим приложением (больше 100 тысяч строк, 200, 500,...)?
500+.
Хотя под "большим" я имел ввиду скорее сложное, а сложность ессно не только от размера зависит.
Здравствуйте, savaDAN, Вы писали:
DAN>>>А речь вот о чем: в больших приложениях управление памятью геморрой еще тот — всякие там смартпоинтеры, которые толком не поддерживаются компилером, следовательно опять же больше ошибок которые крайне геморойно дебагировать и фиксить.
E>>А можно вот об выделенном поподробнее? DAN>что именно подробней?
Какие-такие смартпоинтеры, которые толком не поддерживаются компилятором.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, CreatorCray, Вы писали:
CC>Есть там кста одна хорошая фраза: "этот язык определяет способ их программистского мышления." так вот, вы мыслите на уровне абстракций а я на уровне того, как именно оно будет выполняться.
Видил я код игр... (некоторое время назат я работал в этой сфере) печальное зрелище. А самое противное что это все можно было написать гораздо чище и правильнее при то без потери эффективности.
А все по тому что господа оптимизаторы оптимизируют все подряд и за деревьями леса не видят. CC>Потому как работаю я с платформозависимым кодом. И большинство его должно выполняться быстро и ресурсы освобождать немедленно как только они перестали быть нужны. В любом языке с GC мне надо будет теребить этот самый GC ручками чтобы он не ковырял в носу а сразу убивал мусор.
Сразу это когда? CC>Кстати о сборщике — глядя на янус я склоняюсь к мнению что не такая уж и умная это штука. База у меня всего то 137 метров а янус при работе умудряется отжирать 87 мб working set и 669 virtual... и при этом откровенно подтормаживать при переходе от ветки к ветке...
Сколько можно повторять: В янусе тормозить Jet. Самый что не наесть анменеджет код.
VD>>Но конечно для игр скорее будет интересна не библиотека, а компонентная модель и динамичность дотнета. CC>Как геймдевелопер могу сказать — что то пока никаких удобств не видно...
Просто по тому что ты не знаешь .НЕТ.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
E>Какие-такие смартпоинтеры, которые толком не поддерживаются компилятором.
Ну например о которых Джэф Элджер в С++ библиотека программиста пишут.
ИМХО, сказать что эти сущности полностью поддерживаются компилятором (в том смысле что не позволят программисту допустить ошибку с управлением памятью) — нельзя.
Я уж не говорю о всяких вещах типа "кто создает память?", "кто удаляет память?", что _вообще_ не поддерживается компилером, только соглашениями и архитектурой. опять лишний источник ошибок для программиста и лишняя работа тестерам.
savaDAN wrote:
> E>Какие-такие смартпоинтеры, которые толком не поддерживаются > компилятором. > Ну например о которых Джэф Элджер в С++ библиотека программиста пишут. > ИМХО, сказать что эти сущности полностью поддерживаются компилятором > (в том смысле что не позволят программисту допустить ошибку с > управлением памятью) — нельзя.
А как эти понятия относятся? Или все что поддерживает компилятор
магически становится безопасным?
> Я уж не говорю о всяких вещах типа "кто создает память?", "кто удаляет > память?", что _вообще_ не поддерживается
С вопросами типа "кто создает память" нужно куда-нибудь в SU.CPP.CHAINIK
идти, чтоб хотя бы терминологию выучить.
> компилером, только соглашениями и архитектурой. опять лишний источник > ошибок для программиста и лишняя работа тестерам.
Здравствуйте, savaDAN, Вы писали:
DAN>Я уж не говорю о всяких вещах типа "кто создает память?", "кто удаляет память?", что _вообще_ не поддерживается компилером, только соглашениями и архитектурой. опять лишний источник ошибок для программиста и лишняя работа тестерам.
C>А как эти понятия относятся? Или все что поддерживает компилятор C>магически становится безопасным?
There is no silver bullet, но чем больше помогает компилер тем лучше. Или вы и с этим несогласны?
ИМХО так мы скатимся до спора о том, что не стоит обращать внимания на warning-и компилера раз от него помощи никакой...
C>С вопросами типа "кто создает память" нужно куда-нибудь в SU.CPP.CHAINIK C>идти, чтоб хотя бы терминологию выучить.
Ну-ну, так может быть вы мне расскажите как эта проблема решается в приложении состоящего из солянки разных сторонних библиотек, часть которых придерживается стратегии "дай мне буфер, я верну тебе результат в нем", часть "я тебе сама верну буфер, ты главное его не забудь удалить", а часть вообще имеет свое подобие GC и хочет чтобы с памятью работали исключительно через него? чего-то я такого в SU.CPP.CHAINIK не встречал.
А теперь еще добавьте к этому необходимость таскать подобные буфера через несколько либ внутренних...
С другой стороны смею вас заверить, память отлично течет и системах с GC (особенно этим грешит VB6), но багов из за этого на порядок меньше, и искать и исправлять их тоже значительно проще.
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, VladD2, Вы писали:
VD>>Здравствуйте, CreatorCray, Вы писали:
DAN>>>>1. классы — легче проектировать CC>>>В чем легче? Почему легче? именно опытному разработчику... VD>>Вот это
читал? CC>читал. вот только в чем заключается это самое "легче" — там не написано.
Правильно. Там написано почемы ты этого не поймешь пока не познакомился и не перейдешь "на ты" со средством которое хочешь сравнить.
CC>Есть там кста одна хорошая фраза: "этот язык определяет способ их программистского мышления." CC>так вот, вы мыслите на уровне абстракций а я на уровне того, как именно оно будет выполняться.
Изумительное замечание.
CC>Потому как работаю я с платформозависимым кодом. И большинство его должно выполняться быстро и ресурсы освобождать немедленно как только они перестали быть нужны.
А вот тут ты ошибашся. Мы, ну, те что мыслят абстракциями, можем работать с разными задачами. И в зависимости от задачи будетм определять приоритеты.
CC>В любом языке с GC мне надо будет теребить этот самый GC ручками чтобы он не ковырял в носу а сразу убивал мусор.
Это очердное заблуждение. Связано оно как раз с тем, что ты не полностью понимашь как работает ЖЦ в современных рантаймах.
CC>Кстати о сборщике — глядя на янус я склоняюсь к мнению что не такая уж и умная это штука.
Господи, откуда же берется эта толпа оценщиков?
Ты проводил измерения? Ты выянял, что не так в Янусе?
Так что же ты судишь о том в чем не имешь ни малейшего представления?
Короче, или воспользуйся поиском, или давай спорить на любую сумму начиная от $1000, о том что в Янусе ЖЦ не имеет никакого отношения к торомазам. Тогда я найду в себе силы еще раз описать все что я повторял уже 100 раз.
CC> База у меня всего то 137 метров а янус при работе умудряется отжирать 87 мб working set и 669 virtual... и при этом откровенно подтормаживать при переходе от ветки к ветке...
Докагадайся с трех раз что происходит при переходе от ветке. В качестве намека... погляди что при этом изменяется.
VD>>Про типобезопсность слышал? CC>слышал. для меня она выглядит как очень строгая проверка на этапе компиляции... И покуда кажется больше мешающей чем полезной.
Могу только посочувствовать.
CC>Кстати никак не получается найти развернутое определение, что же именно включается в этот термин. Не поможете ссылкой?
У профи, по-моему, должно быть понимание, что в не типобезопасных языках избавиться от утечек памяти и вообще от проблем с ее интерпретацией можно только путем нехилого тестирования. И то полной гарантии не будет. И это при том, что вопрос о том что нужно стараться делать контроль за ресурсами автоматически даже не обсуждается.
VD>>Та же работа с ХМЛ. CC>парсер пишется за короткое время на С++ и имеет нужную функциональность и большую скорость и удобство нежели вызов стандатной библы.
Языком. Попробуй на досуге написать хотя бы интерпретатор XPath. А ведь ХМЛ — это куда более сложная технология.
VD>>Тот же ГУИ. CC>уууу... посмотрите на ку4... Что из его ГУИ следует делать на библах .нета?
Потому такой и ибогий. Две менюшки и командная строка.
А ты вот погляди на ГУИ у ArenaWars. Игра явно не того калибра, что Ку4, а ГУИ на порядки лучше.
VD>>Но конечно для игр скорее будет интересна не библиотека, а компонентная модель и динамичность дотнета. CC>Как геймдевелопер могу сказать — что то пока никаких удобств не видно...
А ты что-то уже пробовал разрабатывать?
Да, и пока ты не начнешь думать о тех самых абстракциях, дотнет тебе вообще интересен не будет.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, eao197, Вы писали:
E>А можно вот об выделенном поподробнее?
Смартпоинтеры — это дополнительные усилия. Забыть его использовать, или использовать неверно тоже можно. А это все забивает голову. И там где программист свободный от ручного управления памятью (РУП) может тратить все свою умственную энергию на решение основной задачи программист с ручным управлением помятью (ПРУП) часть своих мозгов отводит на фоновую борьбу с этой сложностю.
Конечно ПРУП говорит окружающим (да и думает так сам), что он не затрачивает на РУП усилий. Но на самом деле он постоянно забивает РУП-ом свою голову и на основную задачу сил остается меньше.
А таких кусков далеко не один. Есть еще указатели, множество заменителей массивов, заменителей делегатов, эмуляции паттернов и т.п. В итоге на решение основной задаче ПРУП начинает отводить уже совсем незначительный объем своей гловы.
Однако ПРУП думает, что это просто задача у него очень сложная. Причем это за одно начинает развивать в нем комплекс крутого программера. "Глядите какую сложную задачу я смог решить!" А на самом деле задача то не такая уж и сложная.
Скрипты и управляемые среды снимают эти проблемы. Многие ПРУП замечают результат, но объясняют его какиме-то волшебными силами, а не банальным снятием с себя необходимости тратить время на совервшенно не нужную работу.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Во-первых, я спрашивал про смарт-поинтеры, которые прохо поддерживаются компиляторами. Поскольку в реальной жизни я таких смартпоинтеров не видел.
Во-вторых, я наблюдал, как освободившиеся от необходимости контроля памяти программисты успешно забывали освобождать другие ресурсы. В частности, конекшены к БД. Поиском чего полностью занимали свое освободившееся время. Просто за счет того, что вместе с контролем за памятью у них отобрали идиому RAII.
В-третьих, в языках, где нет явных указателей, а есть только ссылки, есть очень тонкие баги, связанные с копированием ссылки вместо клонирования объекта. На поиски которых так же уходит освободившееся после контроля памяти время.
Да и про то, что не нужные ссылки необходимо занулять, так же часто забывают.
Так что, имхо, сменили шило на мыло
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, WolfHound, Вы писали:
WH>Сразу это когда?
Как только в нем пропадает необходимость.
WH>Сколько можно повторять: В янусе тормозить Jet. Самый что не наесть анменеджет код.
И память тоже он жрет?
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, savaDAN, Вы писали:
DAN>Влад уже ответил, но не будем прятаться за спины титанов , кину и свои 5 копеек...
DAN>>>1. классы — легче проектировать CC>>В чем легче? Почему легче? именно опытному разработчику... DAN>1. Классы это более высокий уровень абстракции. Чем более высоким уровнем абстракции вы манипулируете, тем больший кусок вы можете удержать и обработать в памяти (в голове). Собсно чем больше проект, тем это более важно. DAN>2. Классы это не только ценный мех, но и всякие другие приятные рюшки (хором): инкапсуляция и полиморфизм. Что позволяет писать систему более устойчивую к багам, что в свою очередь немало сокращает время разработки в целом.
Брр.. А разве классы только с .нет появились? Дык это я тогда уже оказывается лет 6 (за деньги) на дотнете пишу
И наш теперешний движок тоже на дотнете написан? там жеж классов — море
DAN>>>3. большая стандартная библиотека — меньше кода писать. CC>>Т.е. надо писать на шарпах/жабе потому что там библиотека стандартная больше? Гм. нет ведь библиотеки на все случаи жизни... Где то больше, где то меньше... К примеру я игру разрабатываю. 3D шутер с навороченной графикой. Чем мне в этом поможет стандартная библиотека? DAN>Как минимум автоматическая поддержка wide strings, коллекции, ввод\вывод, работа с временем/датами и пр. пр. пр.
std::wstring, контейнеры STL, СВОЙ ввод\вывод (кроссплатформенность надо), время-дата в понимании "день-месяц-год-час-минута" большой роли не играет. в отличие от hires таймеров и проч.
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, VladD2, Вы писали:
VD>Правильно. Там написано почемы ты этого не поймешь пока не познакомился и не перейдешь "на ты" со средством которое хочешь сравнить.
резонно. в таком случае по этой тематике откланиваюсь до поры до времени.
VD>Изумительное замечание.
мда. коряво я там выразился...
VD>А вот тут ты ошибашся. Мы, ну, те что мыслят абстракциями, можем работать с разными задачами. И в зависимости от задачи будетм определять приоритеты.
Задача: портировать код игры под GameCube. Тут абстракции уже не нужны — тут надо брать мануал по девайсу и вдумчиво искать в нем как же впихнуть гигагерцы и гигабайты в мегагерцы и мегабайты. И чтоб скорость при этом не потерять...
CC>>В любом языке с GC мне надо будет теребить этот самый GC ручками чтобы он не ковырял в носу а сразу убивал мусор. VD>Это очердное заблуждение. Связано оно как раз с тем, что ты не полностью понимашь как работает ЖЦ в современных рантаймах.
AFAIK убиение ненужного происходит не сразу после pointer = NULL; а тогда, когда сработает некая логика в GC...
Если не так — поясни как именно...
VD>Могу только посочувствовать.
Не стоит. Я прекрасно себя чуствую с небезопасным С++ который для решения моих задач подходит как нельзя лучше.
CC>>Кстати никак не получается найти развернутое определение, что же именно включается в этот термин. Не поможете ссылкой? VD>http://en.wikipedia.org/wiki/Type_safety VD>http://en.wikipedia.org/wiki/Datatype
Пасиб, но там то же самое что я уже находил. Из сего делаю вывод что я правильно понимал этот термин.
CC>>Верить что лики есть и писать без ликов — все же разные вещи. Разумеется в "любой программе есть ошибки" (с) не помню. CC>>Но у профи ИМХО таких ляпов как лик быть не должно.
VD>У профи, по-моему, должно быть понимание, что в не типобезопасных языках избавиться от утечек памяти и вообще от проблем с ее интерпретацией можно только путем нехилого тестирования. И то полной гарантии не будет. И это при том, что вопрос о том что нужно стараться делать контроль за ресурсами автоматически даже не обсуждается.
VD>А ты вот погляди на ГУИ у ArenaWars. Игра явно не того калибра, что Ку4, а ГУИ на порядки лучше.
Здоровая сильно зараза чтоб из дома тянуть...
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
CC>Брр.. А разве классы только с .нет появились? Дык это я тогда уже оказывается лет 6 (за деньги) на дотнете пишу CC>И наш теперешний движок тоже на дотнете написан? там жеж классов — море
Стоп! Внимательно читаем мой оригинальный пост, в котором написано что с чем сравнивается. Или что С, что С++ все едино?
Блин, синдром какой-то: если увидел в названии языка букву "С" сразу считаем что это С++ и бросаемся на его защиту
Здравствуйте, CreatorCray, Вы писали:
CC>Задача: портировать код игры под GameCube. Тут абстракции уже не нужны — тут надо брать мануал по девайсу и вдумчиво искать в нем как же впихнуть гигагерцы и гигабайты в мегагерцы и мегабайты. И чтоб скорость при этом не потерять...
Согласись это не совсем тоже самое что разработка ПО с нуля. Это именно портирование и оптимизация под конретное железо.
CC>AFAIK убиение ненужного происходит не сразу после pointer = NULL; а тогда, когда сработает некая логика в GC...
Убиения не просходит вообще RTFM (извинясь за грубость).
Логика ЖЦ ищет живые объекты, а не мертвые.
CC>Если не так — поясни как именно...
VD>>Могу только посочувствовать. CC>Не стоит. Я прекрасно себя чуствую с небезопасным С++ который для решения моих задач подходит как нельзя лучше.
Я тоже так думал.
Почитай мои сообщения до 2002 года.
CC>>>Кстати никак не получается найти развернутое определение, что же именно включается в этот термин. Не поможете ссылкой? VD>>http://en.wikipedia.org/wiki/Type_safety VD>>http://en.wikipedia.org/wiki/Datatype CC>Пасиб, но там то же самое что я уже находил. Из сего делаю вывод что я правильно понимал этот термин.
Тогда странно что ты не понимшь, как типобезопасность уменьшает лики и исключает UB.
VD>>А ты вот погляди на ГУИ у ArenaWars. Игра явно не того калибра, что Ку4, а ГУИ на порядки лучше. CC>Здоровая сильно зараза чтоб из дома тянуть...
Стяни с работы.
Естати, о Ку4 жрет 700 метров (из гига). Вылетела пару раз. Хотя конечно красиво.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, eao197, Вы писали:
E>Во-вторых, я наблюдал, как освободившиеся от необходимости контроля памяти программисты успешно забывали освобождать другие ресурсы. В частности, конекшены к БД.
А ты уверен, что они до этого их освобождали?
E> Поиском чего полностью занимали свое освободившееся время. Просто за счет того, что вместе с контролем за памятью у них отобрали идиому RAII.
Это сказка. Никакой RAII не спосает от ручного контроля памяти. Это огромный груз. А вот какраз конроль реусурсов ОС при наличии IDispose и using проблем не вызывает. Тот же RAII вид сбоку.
Эта тема обсуждалась сто раз и я не понимаю почему в 101-ый снова повтояются они и те же высасанные из пальсца аргументы.
Ладно. Еще раз. В кратце.
Итак, ресусты можно разделить на 3 типа:
1. Общего доступа. При их занятии блокируется тот или иной ресурс и их лики приводят к неверному фукнционированию программы. Пример такого ресурса файл открываемый для четения или записи.
2. Приватные ресурсы. Их потеря не критична. По крйней мере в современых ОС вроде потомков NT или *никсов. К тамим ресурсам относятся большинство ресурсов вроде хэндлов картинок, ГДИ-ресурсов, соеденений с БД и т.п. Проблемы могут возникнуть только при сильном перерасходвании таких ресуросов.
3. Память в языках без ЖЦ. Это самый частый случай в программировании. Средняя программа оперирует еденицами ресурсов ОС, и тысячами, а то и миллионами блоками памяти.
В С++ все эти 3 типа ресурсов обычно не различаются. Это все "ресурсы" и управление ими производится по общей схеме.
В управляемых средах все несколько иначе. Ресусы треьего класса ресурсами не являются, по понятным причинам. Так что управление ресурсами сводится к контролю очень небольшого числа ресусров ОС.
Ресусры из п. 2 хотя и желательно контролировать вручную, но можно и оставить на откуп финализатору ЖЦ. Для этого нужно всего лишь написать финализатор (синтаксис как у деструктора в С++). Если объект хранящий ресус временный (а именно так случается в 99% случаев), то он будет подобнан сборщиком мусора нулевого поколение, азначит проживет не многим дольше процедуры в которой он был занят. Так что потеря ресурсов этого класса может привести только к очень незначительному повышению требований к памяти или ресурсам. Те же драйверы БД могут при нехватке соеденений просто инициировать сборку мусора.
Ресусры п. 1 требуют ручного контроля. Но особых проблем не возникает и с ними, так как их лики очень быстро становятся заметны. Ведь из файла до его освобождения никто не сможет читать.
Прибавим сюда using с IDispose-ом и вспомним, о том, что RAII автоматически в программах не появляется. fopen\CreateFile ведь никто не отменял. Да и есть множество того же ВыньАПИ не имеющего готовых оберток. Так что не грамотный программист может забыть закрыть файл и там, и там.
Что же мы получаем? В управляемых языках мы получаем практически полное отсуствие необходимости контролировать 99% ресурсов программы, так как это память которой управляет ЖЦ, и имеем средства для контроля ресусрсов ОС. При этом только незначительный процент ресурсов действительно критичен для приложения и то потери ресурсов этого класса обычно легко выявляются.
В неуправляемых языках мы точно так же надеемся на разумность программиста в области контроля ресусров ОС, но ко всему прочему мы еще заставляем его вручную контролировать и управление памятью.
Мой вывод однозначен. Эти притензии высасоны из пальца.
Я согласен, что было бы не плохо иметь и автоматическое управление памтью, и автоматическое управление ресурсами. Но если выбирать из того что есть сегодны я не задумываясь выберу ЖЦ и юсинг.
E>В-третьих, в языках, где нет явных указателей, а есть только ссылки, есть очень тонкие баги, связанные с копированием ссылки вместо клонирования объекта. На поиски которых так же уходит освободившееся после контроля памяти время.
Да? И что же ты говоришь что на Руби у тебя ошибок меньше?
Это сказка вызванная тем что очень хочется найти проблему там где ее нет.
А правда в том, что поиск ошибок связанных с типами и управлением памятью нманого сложнее чем других. К тому же работает банальная арифметика. Если к общей совокупности ошибок без учета ошибок типизации и управления памятью добавить еще и их, то количество ошибок увеличится.
Правда еще и втом, что конкретно C# специально проектировался так чтобы уменьшить количество мест где вообще можно допустить ошибку. Так что не нужно придумывать.
E>Да и про то, что не нужные ссылки необходимо занулять, так же часто забывают.
Это еще одна сказка. Интересно откуда они вообще берутся?
1. Объекты обычно выстраиваются в деревья и умирают целыми группами.
2. В одтнете при записи без отладчика JIT строит таблицу достижимости так, что если объект больше не испльзуется, то ссылка считается недействительной (хотя переменная можеть быть еще видна в области видимости).
E>Так что, имхо, сменили шило на мыло
Ты придумал себе мифы которыми пыташся убедить себя в чем то.
Не нужно рассказывать сказки. Скажи честно что тебе просто хочется чтобы то чем ты не занимашся имело какие-то недостатки.
В общем, ну нежно придумывать. Попробуй и все миф пройдут сами собой.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Согласись это не совсем тоже самое что разработка ПО с нуля. Это именно портирование и оптимизация под конретное железо.
Соглашусь пожалуй. пример я выбрал не самый удачный
CC>>AFAIK убиение ненужного происходит не сразу после pointer = NULL; а тогда, когда сработает некая логика в GC... VD>Убиения не просходит вообще RTFM (извинясь за грубость). VD>Логика ЖЦ ищет живые объекты, а не мертвые.
ну, я так "образно" выразился про освобождение выделенной памяти.
VD>Это долгая история. Вот тут я уже пытался ответить на этот вопрос:
Ок, почитаю на досуге
CC>>Пасиб, но там то же самое что я уже находил. Из сего делаю вывод что я правильно понимал этот термин. VD>Тогда странно что ты не понимшь, как типобезопасность уменьшает лики и исключает UB.
Ну, я еще согласен что с ней проще искать собственные ашипки и очепятки. Но панацеей это не является и я вижу больше неудобств чем преимуществ. Вижу есессно для себя.
Ладно, наверное хватит копья ломать...
VD>Стяни с работы.
если не забуду опять
VD>Естати, о Ку4 жрет 700 метров (из гига). Вылетела пару раз. Хотя конечно красиво.
Я дома играл на 512-ти... Не фонтан конечно... Но не вылетала покуда ни разу.
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, savaDAN, Вы писали:
CC>>Брр.. А разве классы только с .нет появились? Дык это я тогда уже оказывается лет 6 (за деньги) на дотнете пишу CC>>И наш теперешний движок тоже на дотнете написан? там жеж классов — море DAN>Стоп! Внимательно читаем мой оригинальный пост, в котором написано что с чем сравнивается. Или что С, что С++ все едино? DAN>Блин, синдром какой-то: если увидел в названии языка букву "С" сразу считаем что это С++ и бросаемся на его защиту
Тьфу блин. Что то я про .нет в последнее время много спорил — вот и клемануло что речь про .нет
сорри
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, CreatorCray, Вы писали:
CC>Ну, я еще согласен что с ней проще искать собственные ашипки и очепятки. Но панацеей это не является
А панацей нет в принципе. В природе нет.
CC>и я вижу больше неудобств чем преимуществ.
Это с непривычки. Когда появились Фортран, С и Паскаль народ долгое время упиравшися в работу максимум на уровне ассемблеров, а в основном машинных кодов, тоже не весь сразу оценил приемущество языков высокого уровня. По началу тоже не видили приемуществ. Точнее считали что недостатки (тормоза ведь какие?!) перевешивали.
Я вот тоже после плюсов долго не искал как память реинерпретировать. Потом понял, что это во мне дурные манеры играют. И понял, что можно жить без реинтерпретации памяти. Оказалось, что это очень даже весело и удобно.
CC> Вижу есессно для себя. CC>Ладно, наверное хватит копья ломать...
Ага.
VD>>Естати, о Ку4 жрет 700 метров (из гига). Вылетела пару раз. Хотя конечно красиво. CC>Я дома играл на 512-ти... Не фонтан конечно... Но не вылетала покуда ни разу.
Ну, я его до конца прошел. Если сидеть много часов подряд, то вылетает зараза.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Давай сначала определим позиции. Я не считаю сборку мусора злом. Это действительно удобно, если не считать того, что GC может запуститься когда ему заблогорассудится.
Не нравится мне другое. В языках типа Java, Python и Ruby мне дали сборку мусора, но рабрали у меня RAII. В результате, если мне нужно закрыть какой-то ресурс, то я должен вручную вызывать close. Если же в моем коде возможно исключение, то я должен еще и перестраховываться и вызывать close либо в catch, либо в finally. Что не удобно, черевато ошибками и тяжело отлаживается.
Добавленный в C# unsing уже упрощает работу с ресурсами. Но это не RAII. Нормально сделан RAII в сочетании со сборкой мусора в языке D. Да только D пока в таком состоянии, что очень стремно на нем проекты делать.
E>>Во-вторых, я наблюдал, как освободившиеся от необходимости контроля памяти программисты успешно забывали освобождать другие ресурсы. В частности, конекшены к БД.
VD>А ты уверен, что они до этого их освобождали?
Уверен. Нормальна C++ библиотека закрывает все ресурсы в деструкторах. Возьми, например, обычный std::ifstream или std::ofstream. Или библиотеку OTL. Деструкторы чистят за собой все ресурсы.
Есть, конечно и "не нормальные" C++ библиотеки, которые RAII не используют. Тот же ACE, например, во многих классах RAII не предоставляет. Но, во-первых, никто не заставляет тебя использовать эти библиотеки. А, во-вторых, отказ от RAII в C++ вызван или неграмотностью разработчиков (и от их продуктов лучше держаться подальше), либо архитектурными решениями, которые предлагают адекватную замену RAII. Например, в той же ACE вместо автоматического закрытия хендлов в деструкторах предлагается использовать паттерны Reactor, Event_Handler и обработчик handle_close. Для приложений, на которые расчитана ACE, это даже удобнее.
E>> Поиском чего полностью занимали свое освободившееся время. Просто за счет того, что вместе с контролем за памятью у них отобрали идиому RAII.
VD>Это сказка. Никакой RAII не спосает от ручного контроля памяти.
Не нужно мне сказки расказывать. Это ты студентам можешь подобные голословные утверждения делать.
Я уже очень давно для управления памятью RAII механизмы использую (всякие auto_ptr, smart_ref и пр). Утечки памяти у меня -- это боОольшая редкость. Но ты, конечно же, можешь не верить.
В качестве примера еще можно библиотеку Qt привести. Там большинство объектов через new создается. А вызов delete -- крайне редкая операция. И никаких проблем нет, потому что работа с памятью продумана: все объекты объеденены в иерархии родитель-потомок. И при уничтожении родителя все потомки уничтожаются автоматически.
Даже в C-шном Apache похожая идея используется с memory pool-ами. Разве Apache можно причислить к приложениям с хроническими memory leak-ами?
VD> Это огромный груз. А вот какраз конроль реусурсов ОС при наличии IDispose и using проблем не вызывает. Тот же RAII вид сбоку.
Насколько я понял, usign -- это не совсем RAII. Например, как с помошью using разрешить такую ситуацию:
class Some_Actor
{
private :
//! Указатели на потоки, которые реально будут использоваться.
std::istream * in_;
std::ostream * out_;
//! Потоки, на случай работы с файлами, а не со стандартным вводом/выводом.
std::ifstream file_in_;
std::ofstream file_out_;
public :
Some_Actor()
// По умолчанию будем работать со стандартным вводом/выводом.
: in_( &std::cin )
, out_( &std::cout )
{}
// Стартовать работу. Если какой-то из указателей не равен 0, то вместо
// соответствующего потока нужно использовать указанный файл.void start( const char * in_file_name, const char * out_file_name )
{
if( in_file_name )
{
file_in_.open( in_file_name );
in_ = &file_in_;
}
if( out_file_name )
{
file_out_.open( out_file_name );
out_ = &file_out_;
}
...
}
...
};
Все. Дальше мне уже не важно, будут ли объекты Some_Actor создаваться на стеке или в хипе. Или вообще быть статическими объектами. Не важно, какой из них с каким файлом работает. Как только Some_Actor разрушается, все открытые им файлы закрываются. Без малейшего участия с моей стороны.
VD>Итак, ресусты можно разделить на 3 типа: VD>1. Общего доступа. При их занятии блокируется тот или иной ресурс и их лики приводят к неверному фукнционированию программы. Пример такого ресурса файл открываемый для четения или записи.
Сюда же еще и mutex-ы можно добавить. И коннекшены к БД.
Кстати, std::ofstream, открытый для чтения/записи не блокирует файл и позволяет открыть тот же файл для изменения еще раз. Как той же программе, так и любой другой.
VD>2. Приватные ресурсы. Их потеря не критична. По крйней мере в современых ОС вроде потомков NT или *никсов. К тамим ресурсам относятся большинство ресурсов вроде хэндлов картинок, ГДИ-ресурсов, соеденений с БД и т.п. Проблемы могут возникнуть только при сильном перерасходвании таких ресуросов.
Ну ты крут. Т.е., если в приложении есть небольшая утечка ресурсов, то это не баг -- это фича
Я как-то в pcre++ баг нашел с утечкой памяти. Всего одна операция за собой результаты матчинга regexp-а не удаляла. Да и результаты те были -- мелочь пузатая, что-то около 100 байт. После месяца работы сервера, в котором эта операция использовалась, расход памяти шел уже на сотни мегабайт. Операция эта вызывалась слишком часто.
VD>3. Память в языках без ЖЦ. Это самый частый случай в программировании. Средняя программа оперирует еденицами ресурсов ОС, и тысячами, а то и миллионами блоками памяти.
Давай для объективности скажем, что в языках без ЖЦ огромное количество объектов создается на стеке и автоматически разрушается при выходе из области видимости. Работа с такими объектами вообще никаких проблем не вызывает.
VD>В С++ все эти 3 типа ресурсов обычно не различаются. Это все "ресурсы" и управление ими производится по общей схеме.
Что есть благо.
VD>В управляемых средах все несколько иначе. Ресусы треьего класса ресурсами не являются, по понятным причинам. Так что управление ресурсами сводится к контролю очень небольшого числа ресусров ОС.
И не забывать обнулять ссылки на дочерние объекты в вершинах иерархий.
VD>Ресусры из п. 2 хотя и желательно контролировать вручную, но можно и оставить на откуп финализатору ЖЦ. Для этого нужно всего лишь написать финализатор (синтаксис как у деструктора в С++). Если объект хранящий ресус временный (а именно так случается в 99% случаев), то он будет подобнан сборщиком мусора нулевого поколение, азначит проживет не многим дольше процедуры в которой он был занят. Так что потеря ресурсов этого класса может привести только к очень незначительному повышению требований к памяти или ресурсам. Те же драйверы БД могут при нехватке соеденений просто инициировать сборку мусора.
В Java раньше очень настоятельно не рекомендовали использовать финализаторы для освобождения подобных ресурсов. В Ruby финализаторы вообще нигде не упоминаются (хотя я не знаю, может они и есть).
А твой пример с драйвером БД, который инициирует сборку мусора при нехватке коннекшенов -- это сильно. Представим себе: многопоточное приложение с багом по освобождению коннекшена. Какие-то потоки генерят тысячи объектов. Один поток исчерпывает ресурсы и при очередном connection запускается GC. Все приложение замирает. И так периодически. Но наиболее часто в момент пиковой нагрузки, когда коннекшены запрашиваются с большой скоростью. Веселуха, короче.
VD>Прибавим сюда using с IDispose-ом и вспомним, о том, что RAII автоматически в программах не появляется.
Берешь ОО библиотеку и получаешь RAII автоматически и часто бесплатно.
VD> fopen\CreateFile ведь никто не отменял.
Уже давно отменили. Потоками ввода-вывода, например.
VD> Да и есть множество того же ВыньАПИ не имеющего готовых оберток. Так что не грамотный программист может забыть закрыть файл и там, и там.
Это проблемы тех, кто использует ВыньАПИ вместо Qt, FOX или wxWidgets.
Даже если приходится обращаться к специфическим особенностям OC (которые везде, а не только в Windows, не инкапсулированы в ОО библиотеки) проще потратить пару часов на написание обертки вокруг native-вызовов, чем потом тратить дни и недели на отладку. Те, кто в C++ этим не пользовался уже давно ушли в сторону Java, а сейчас пойдут еще и в сторону C#.
VD>Что же мы получаем? В управляемых языках мы получаем практически полное отсуствие необходимости контролировать 99% ресурсов программы, так как это память которой управляет ЖЦ, и имеем средства для контроля ресусрсов ОС. При этом только незначительный процент ресурсов действительно критичен для приложения и то потери ресурсов этого класса обычно легко выявляются.
VD>В неуправляемых языках мы точно так же надеемся на разумность программиста в области контроля ресусров ОС, но ко всему прочему мы еще заставляем его вручную контролировать и управление памятью.
VD>Мой вывод однозначен. Эти притензии высасоны из пальца.
Ну что же, у нас свобода сновидений. Ты можешь верить во что угодно.
VD>Я согласен, что было бы не плохо иметь и автоматическое управление памтью, и автоматическое управление ресурсами. Но если выбирать из того что есть сегодны я не задумываясь выберу ЖЦ и юсинг.
А я бы выбрал GC и RAII. Жалко, что это есть, AFAIK, только в D.
E>>В-третьих, в языках, где нет явных указателей, а есть только ссылки, есть очень тонкие баги, связанные с копированием ссылки вместо клонирования объекта. На поиски которых так же уходит освободившееся после контроля памяти время.
VD>Да? И что же ты говоришь что на Руби у тебя ошибок меньше?
Вот что-то я не помню, где бы я такое говорил. Я говорил, что на Ruby у меня код меньше получается. Это есть.
По статистике, когда-то приведенной Gaperton-ом, количество ошибок на одинаковый объем строк является постоянной величиной и не зависит от языка программирования. Поэтому уменьшение объема кода косвенно приводит к уменьшению количества ошибок.
А вот о том, что при сокрашении объема кода серьезность остающихся в коде ошибок уменьшается -- об этом речи не было. Как раз проблема с копированием ссылки, а не клонированием объекта -- это очень серьезная ошибка (аналога которой в C++ так сразу и не вспомнишь). Я на днях потратил полчаса на то, чтобы понять, почему у меня чужая информация в мой Hash попадает. Оказалось потому, что я не сделал копирование Hash-а, а скопировал ссылку на него. И в Java, в свое время, я на такие грабли наступал. А вот в C++ такой ошибки бы в принципе не было.
VD>А правда в том, что поиск ошибок связанных с типами и управлением памятью нманого сложнее чем других. К тому же работает банальная арифметика. Если к общей совокупности ошибок без учета ошибок типизации
А откуда берутся ошибки типизации? От грязных хаков, которые тянутся из C и которые тем же WinAPI стимулируются. Переход на нормальный C++ (с шаблонами, ссылками, dynamic_cast-ами) и ОО библиотеки сильно упрощает жизнь.
VD> и управления памятью добавить еще и их, то количество ошибок увеличится.
VD>Правда еще и втом, что конкретно C# специально проектировался так чтобы уменьшить количество мест где вообще можно допустить ошибку. Так что не нужно придумывать.
Правда еще и в том, что языками с GC является не только C#. Есть еще более мейнстримовая Java. Есть еще динамические языки. Когда я говорил о проблемах в языках со сборкой мусора, я говорил о собирательном образе. Ты же все к C# приводишь.
Если C# удобнее других языков с GC, то слава богу. Значит развитие идет в правильном направлении. Только мне кажется, что в области управления ресурсами D ушел еще дальше.
E>>Да и про то, что не нужные ссылки необходимо занулять, так же часто забывают.
VD>Это еще одна сказка. Интересно откуда они вообще берутся?
На alphaworks.ibm.com, кажется, была статья "Memory Leaks in Java" -- там хорошо основные причины излагались.
VD>1. Объекты обычно выстраиваются в деревья и умирают целыми группами.
Или не умирают, если вершина дерева остается живой.
E>>Так что, имхо, сменили шило на мыло
VD>Ты придумал себе мифы которыми пыташся убедить себя в чем то.
Ничуть не бывало. Я рассказал только то, с чем сам в Java столкнулся.
VD>В общем, ну нежно придумывать. Попробуй и все миф пройдут сами собой.
Пробую сейчас с Ruby. RAII не хватает, хотя там и можно применять приемы a-la C#-вский using.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Кстати, о птичках. Управление неуправляемыми ресурсами из управляемого кода — та еще песня
Особенно это касается взаимодействия нескольких Disposable-объектов.
Пример номер 1:
Мы создаем объект StreamReader. В него передаем, соответственно, объект Stream.
При этом закрывать стрим до закрытия ридера нехорошо.
Поэтому интуитивно хочется написать вот такой код:
using(Stream myStream = new FileInfo("...").OpenRead())
{
using (StreamReader sr = new StreamReader(myStream)
{
...
}
}
Все хорошо, кроме случая, когда мы отдаем ридер куда-то наружу. Тут уже юзингом не обойдешься. К счастью, Dispose в StreamReader реализован корректно — он сам закрывает стрим. Поэтому работает и вот такой код:
using(TextReader tr = GetReader())
{
...
} // здесь будет закрыт и поток. private TextReader GetReader()
{
return new StreamReader(new FileStream("..."));
}
Полное счастье и все такое.
Но! Есть и другие примеры. Вот, в частности, популярный класс System.Drawing.Image. Он оборудован методом загрузки из потока (Image.FromStream(Stream)). Что характерно, поток тоже нельзя закрывать в течение времени жизни картинки (неожиданно, правда? хотя, если подумать, то все логично — зачем читать всю картинку: вдруг понадобится только заголовок). Как же быть? Ура, Image тоже реализует Disposable, и можем ождать, что все будет своевременно закрыто. Увы, не тут то было. Как минимум в FW 2.0 RC, диспоз имаджа не приводит к отпусканию потока. Что помогает возникновению трудноуловимых глюков. А я-то удивлялся, почему в сэмплах МС сначала грузит файл в MemoryStream, и грузит картинку уже из него:
using (Image img = GetImage())
{
...
} // Упс! Файл еще заблокирован!
private Image GetImage()
{
return Image.FromStream(new FileStream("myimg.gif"));
}
// Вот как приходится делать:private Image SafeGetImage()
{
using(Stream imgStream = new FileStream("myimg.gif"))
{
byte[] buf = new byte[imgStream.Length];
imgStream.Read(buf, 0, buf.Length);
return Image.FromStream(new MemoryStream(buf));
}
}
В чем мораль? А в том, что для пользования IDisposable — просто гениальная находка. А вот его корректная реализация не всякой мелкой корпорации по зубам. Особенно в условиях передачи владения.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, eao197, Вы писали:
E>Добавленный в C# unsing уже упрощает работу с ресурсами. Но это не RAII. Нормально сделан RAII в сочетании со сборкой мусора в языке D. Да только D пока в таком состоянии, что очень стремно на нем проекты делать.
Мне вот интересно. Может все же поиписать на том самом C#, а потом уже выражать мнение о необходимости.
Пойми, в начале знакомства с Шарпом я тоже выражал сожаление о том, что в языке нет деструкторов. Слово RAII мне не было знакомо, но не суть.
Так вот я тоже сокрушался, что мол зря они не сделали специальный тип объекта который по сути является структорой, но для него вызвается деструктор при выходе из области видимости.
Ну, и что? А все просто. Прошло время. Я понял почему это не сделно. И понял, что по большому счету это моя фобия, так как в сочетании с принятыми в дотнете правилами работы с ресурсами проблем с контролем ресурсов просто не наблюдается.
Проблема введения деструкторов в язык с вязана с тонкостями работы дотнета. В отличии от С++ в дотнете было принято решение избавиться от такой штуки как копирубщие конструкторы и деструкторы. Точнее не превносить их в архитектуру. Сделано это было для того, чтобы любой объект можно было бы копировать скажем так memmove-ом, т.е. побайтно. За одно это резко урощает реализацию массивов и т.п. и делает семантику массивов вэлью-типов очень близкой к семантике ссылочных массивов.
Все это повзволяет с одной стороны реализовать эффективную автоматику в управлении памяти, а с другой сделать язки вроде Шарпа максимально простыми и понятными.
Расчет же был совсем простым. После того как память исключается из списка ресусрсов которые нужно контролировать программисту, количество ресурсов получается смехотворно малым. Их ничего не стоит проконтролировать вручную. Юсинг снимает послений аргумент лени.
Далее для контроля ресурсов применяется довольно простой набор првил. Он позволяет в большинстве случаев вообще избавиться от контроля. В результате даже совсем не опытный программист может писать программы на Шарпе и не испытывать никаких проблем в контроле ресурсов.
Что же собственно еще может быть лучше? Неопытный орел получает хотя и отложенную, но автоматику. Опытный юсинг. Вместе они получают снижение затрат на контроль ресурсов практически до нулевого уровня.
VD>>А ты уверен, что они до этого их освобождали?
E>Уверен. Нормальна C++ библиотека закрывает все ресурсы в деструкторах.
Да? А С или АПИ? А если объект из нормальной С++-библиотеки создан через new или того хуже через malloc?
E> Возьми, например, обычный std::ifstream или std::ofstream. Или библиотеку OTL. Деструкторы чистят за собой все ресурсы.
Видимо их там море. Один файловый хэндл. Кстати, в управляемых ОС это тоже будет управляемым ресурсом (ну, да это так отступление).
Незаметить не закрытый хэндл ты не сможешь. Да и файлов обычно открывается очень не много. В итоге промазать с закрытием файла ну, очень не просто.
E>Есть, конечно и "не нормальные" C++ библиотеки, которые RAII не используют. Тот же ACE, например, во многих классах RAII не предоставляет. Но, во-первых, никто не заставляет тебя использовать эти библиотеки.
того как серьезного программиста я так и не смог убедить создать оберкти и не управлять памятью вручную. Смог только отговорить от испольования goto для очистки ресурвов.
E> А, во-вторых, отказ от RAII в C++ вызван или неграмотностью разработчиков (и от их продуктов лучше держаться подальше), либо архитектурными решениями, которые предлагают адекватную замену RAII.
Ну, вот юсинг как раз адекватная замета.
E> Например, в той же ACE вместо автоматического закрытия хендлов в деструкторах предлагается использовать паттерны Reactor, Event_Handler и обработчик handle_close. Для приложений, на которые расчитана ACE, это даже удобнее.
А в дотнете большинство библиотек вообще не требует думать о файлах. Ну, и?
E>>> Поиском чего полностью занимали свое освободившееся время. Просто за счет того, что вместе с контролем за памятью у них отобрали идиому RAII.
VD>>Это сказка. Никакой RAII не спосает от ручного контроля памяти.
E>Не нужно мне сказки расказывать. Это ты студентам можешь подобные голословные утверждения делать.
Это ты их мне рассказывашь.
E>Я уже очень давно для управления памятью RAII механизмы использую (всякие auto_ptr, smart_ref и пр). Утечки памяти у меня -- это боОольшая редкость. Но ты, конечно же, можешь не верить.
А я тебе даже верю. Ты же ведь сам признашся, что они у тебя есть. Я просто уверен, что редкость это намного меньшая чем у меня в прграммах. И уверен, что на борьбу за эту редкость ты тратишь нехилые усилия.
E>В качестве примера еще можно библиотеку Qt привести. Там большинство объектов через new создается. А вызов delete -- крайне редкая операция. И никаких проблем нет,
Редкая? Значит есть...
E>потому что работа с памятью продумана: все объекты объеденены в иерархии родитель-потомок. И при уничтожении родителя все потомки уничтожаются автоматически.
И сколько времени было затрачено на создание этой стратегии, а потом на отслеживание следование ей?
А сколько случаев не вписались в идею дерева, и потребовали ручной обработки?
E>Даже в C-шном Apache похожая идея используется с memory pool-ами. Разве Apache можно причислить к приложениям с хроническими memory leak-ами?
А вот в Апиче люди попытались создать свой ЖЦ для локальной задачи. Это как раз разуное решение. Жаль не универсальное и слежение за его соблюдением опять таки лежит на программисте.
E>Насколько я понял, usign -- это не совсем RAII. Например, как с помошью using разрешить такую ситуацию: E>
E>class Some_Actor
E> {
E> private :
E> //! Указатели на потоки, которые реально будут использоваться.
E> std::istream * in_;
E> std::ostream * out_;
E> //! Потоки, на случай работы с файлами, а не со стандартным вводом/выводом.
E> std::ifstream file_in_;
E> std::ofstream file_out_;
E> public :
E> Some_Actor()
E> // По умолчанию будем работать со стандартным вводом/выводом.
E> : in_( &std::cin )
E> , out_( &std::cout )
E> {}
E> // Стартовать работу. Если какой-то из указателей не равен 0, то вместо
E> // соответствующего потока нужно использовать указанный файл.
E> void start( const char * in_file_name, const char * out_file_name )
E> {
E> if( in_file_name )
E> {
E> file_in_.open( in_file_name );
E> in_ = &file_in_;
E> }
E> if( out_file_name )
E> {
E> file_out_.open( out_file_name );
E> out_ = &file_out_;
E> }
E> ...
E> }
E> ...
E> };
E>
Дело в том, что так просто стараются не писать. А если пишут, то делают общий IDisposeble в Dispose которого освобождают ссылки.
А посутпают обычно так:
1. Читают все данные в рамках start и хранят тольк результат. А то и вооще ничего не хранят.
2. Организуется пул ресурсов и для отдельных операций используются временные ресурсы которые можно освобождать или юсингом или оставить на отуп ЖЦ.
3. Делается итератор в котором все прозрачно. Юсинг в итераторе автоматом приводит к реализации освобождения ресурсов в Dispose-е итератора.
Другими словами просто не занимаются такой фигней как явным хранением ссылок на ресурсы. Это вообще полезно, так как позволяет блокировать ресурсы на минимальное время.
VD>>Итак, ресусты можно разделить на 3 типа: VD>>1. Общего доступа. При их занятии блокируется тот или иной ресурс и их лики приводят к неверному фукнционированию программы. Пример такого ресурса файл открываемый для четения или записи.
E>Сюда же еще и mutex-ы можно добавить.
Отнюдь. Мютексы реализованы внутри платформы и в Шарпе для них есть отдельный синтаксис lock(имяОбъекта). Он принципиально распространяется на область видимости, так что считай что исползуется твой любимый RAII.
E> И коннекшены к БД.
Вовсе нет. Подключение к БД не критичный ресурс. Это ресурс из п. 2. К тому же в дотнете подключения управляются пулами. Это позволяет запрашивать их при каждом обращении к БД и контролировать юсингами или просто бросать на произвол ЖЦ.
E>Кстати, std::ofstream, открытый для чтения/записи не блокирует файл и позволяет открыть тот же файл для изменения еще раз. Как той же программе, так и любой другой.
Вот это как раз и есть п. 1. И ошибки с ним ловятся на раз. Файл ведь заблокирован.
VD>>2. Приватные ресурсы. Их потеря не критична. По крйней мере в современых ОС вроде потомков NT или *никсов. К тамим ресурсам относятся большинство ресурсов вроде хэндлов картинок, ГДИ-ресурсов, соеденений с БД и т.п. Проблемы могут возникнуть только при сильном перерасходвании таких ресуросов.
E>Ну ты крут. Т.е., если в приложении есть небольшая утечка ресурсов, то это не баг -- это фича
Э... Это не С++. Утечки нет. Просто освобождение происходит не по стэку, а с небольшой задержкой. Ну, например, произошла отрисовка и когда процессор освободился происходит сбор нулевого поколения при котором все ресусры и очищаются.
E>Я как-то в pcre++ баг нашел с утечкой памяти. Всего одна операция за собой результаты матчинга regexp-а не удаляла. Да и результаты те были -- мелочь пузатая, что-то около 100 байт. После месяца работы сервера, в котором эта операция использовалась, расход памяти шел уже на сотни мегабайт. Операция эта вызывалась слишком часто.
Не нужно переносить маргинальный опыт плюсов на управляемые среды.
Утечек просто не будет. А память как ты помнишь вообще не рерсурс. Она контролируется автоматом. Все что не занято — свободно.
VD>>3. Память в языках без ЖЦ. Это самый частый случай в программировании. Средняя программа оперирует еденицами ресурсов ОС, и тысячами, а то и миллионами блоками памяти.
E>Давай для объективности скажем, что в языках без ЖЦ огромное количество объектов создается на стеке и автоматически разрушается при выходе из области видимости. Работа с такими объектами вообще никаких проблем не вызывает.
Дык вэлью-типы никто не отменял. Но в ОО-приложении без динамически созданных экземпляров обычно не обходится. В нормальном ОО-приложении количество памяти которую нужно контролировать просто огромно.
VD>>В С++ все эти 3 типа ресурсов обычно не различаются. Это все "ресурсы" и управление ими производится по общей схеме.
E>Что есть благо.
Что есть невероятное зло, так как память является ресурсом который нужно все время контролировать. А это самый огромный ресурс.
VD>>В управляемых средах все несколько иначе. Ресусы треьего класса ресурсами не являются, по понятным причинам. Так что управление ресурсами сводится к контролю очень небольшого числа ресусров ОС.
E>И не забывать обнулять ссылки на дочерние объекты в вершинах иерархий.
То что это чушь я уже говорил и объяснял почему. Так что любой способный читать и думаь разберется. По этому опускаю эту реплику.
E>В Java раньше очень настоятельно не рекомендовали использовать финализаторы для освобождения подобных ресурсов. В Ruby финализаторы вообще нигде не упоминаются (хотя я не знаю, может они и есть).
Я рад за них.
E>А твой пример с драйвером БД, который инициирует сборку мусора при нехватке коннекшенов -- это сильно. Представим себе: многопоточное приложение с багом по освобождению коннекшена. Какие-то потоки генерят тысячи объектов. Один поток исчерпывает ресурсы и при очередном connection запускается GC. Все приложение замирает. И так периодически. Но наиболее часто в момент пиковой нагрузки, когда коннекшены запрашиваются с большой скоростью. Веселуха, короче.
Почему замирают? Сборка мусора — это молниеносная операция. К тому же до этого почти никогда не доходит. Это как бы последняя защита от гипотетической проблемы. Соеденения с БД управляется пулом и просто нет необходимости его прикапывать на долго. По этому есди даже не использовать юсинг, оно умирает при первой сборке нулевого поколения. А они в любом нормальном приложении обычно как из пулемета происходят. Нулевое поколение это как бы стэк донета.
VD>>Прибавим сюда using с IDispose-ом и вспомним, о том, что RAII автоматически в программах не появляется.
E>Берешь ОО библиотеку и получаешь RAII автоматически и часто бесплатно.
В программе на С++ очень редко обходится без общения с С-АПИ. А это значит, что мест где прийдется хотя бы прикручивать обертку к вручную управляемому ресурсу более чем достаточно. Плюс не сегда владение ресурсом можно описать деревом.
Ну, и главное — это геморрой. Ведь политику владения объектом нужно продумывать и отслеживать. А что если циглическая ссылка? Или еще что...
VD>> fopen\CreateFile ведь никто не отменял.
E>Уже давно отменили. Потоками ввода-вывода, например.
я тебе тоже показывал.
VD>> Да и есть множество того же ВыньАПИ не имеющего готовых оберток. Так что не грамотный программист может забыть закрыть файл и там, и там.
E>Это проблемы тех, кто использует ВыньАПИ вместо Qt, FOX или wxWidgets.
Qt тоже оберток не имеет. Да и проблемы эти один хрен есть. Что же людям застрелиться если они используют КОМ или КОРБУ?
Ну, и надо еще задумываться над тем, что любая оберточная библиотека требует изучения и поддержания политик владения.
Вот ты тут все пошь: Апач, КуТи, АСЕ... А раскажи мне как будет выглядеть работа с венигретом в котором по некоторой не зависящей от тебя причине попало все это? Прикинь Апач на котором АСЕ, буст, кусти КуТи и т.п. У каждого свои политики владения объектами. Это же повеситься можно в преключении мозгов на их отслеживание!!!
E>Даже если приходится обращаться к специфическим особенностям OC (которые везде, а не только в Windows, не инкапсулированы в ОО библиотеки) проще потратить пару часов на написание обертки вокруг native-вызовов, чем потом тратить дни и недели на отладку.
Согласен, что конечно это самый грамотный выход. Но:
1. Не все так считают.
2. Обертка так же может приводить к утечкам.
3. На их написание нужно убивать время. Порой большее чем на саму задачу решаемую оберткой.
4. Нужно отслеживать политики владения чтобы не получить проблем второго и более порядков. Ох никак не забуду ловлю багов вылезавших в релизе КОМ-овского приожения где были пара синглтонов и 8 модулей.
E> Те, кто в C++ этим не пользовался уже давно ушли в сторону Java, а сейчас пойдут еще и в сторону C#.
Ты знашь я как раз в С++ всем этим пользовался. Потому и говрю, что идиотизм все это. Можно жить куда проще и удобнее.
родилось как раз в следствии этого правила, так как задолбались клепать обертки.
E>Ну что же, у нас свобода сновидений. Ты можешь верить во что угодно.
А я не верю. Я попробовал... сравнил и сделал выбор. Ты же кормишь себя сказками и разводишь теории. Все же просто. Найди человека серьезно занимющегося дотнетом который ныл бы о том, что ему нужны деструкторы. Вот про подключение реализаций (множественно наследование с человеческим лицом) я слыша не раз. Про шаблоны — слышал. А про деструкторы — нет.
E>А я бы выбрал GC и RAII. Жалко, что это есть, AFAIK, только в D.
Смотря чем за это прийдется платить. Ну, да юсинг мало чем отличается. А сделать автоматический контроль вызова диспоза у полей задача на 10 минут. Так что если было бы нужно, то сделали бы давно.
E>Вот что-то я не помню, где бы я такое говорил. Я говорил, что на Ruby у меня код меньше получается. Это есть.
Ну, а где ты гворил о том, что в Руби есть проблемы с освобождением ресурсов?
E>По статистике, когда-то приведенной Gaperton-ом, количество ошибок на одинаковый объем строк является постоянной величиной и не зависит от языка программирования. Поэтому уменьшение объема кода косвенно приводит к уменьшению количества ошибок.
Ну, эта теория слишком сомнительна. Это он ФЯ выгораживал. А вообще без управления памятью и кода будет меньше.
E>А вот о том, что при сокрашении объема кода серьезность остающихся в коде ошибок уменьшается -- об этом речи не было. Как раз проблема с копированием ссылки, а не клонированием объекта -- это очень серьезная ошибка (аналога которой в C++ так сразу и не вспомнишь).
Можно ссылки с жалобами на это дело?
E> Я на днях потратил полчаса на то, чтобы понять, почему у меня чужая информация в мой Hash попадает. Оказалось потому, что я не сделал копирование Hash-а, а скопировал ссылку на него. И в Java, в свое время, я на такие грабли наступал. А вот в C++ такой ошибки бы в принципе не было.
Это как? Где ты его брал?
E>А откуда берутся ошибки типизации?
От невозможности писать весь код в типобезопасном режиме. От желания сделать его по быстрее (ну, там memmove/memset в С++). От необходимости постоянно работать с С-АПИ. Да от многого.
E>От грязных хаков, которые тянутся из C и которые тем же WinAPI стимулируются. Переход на нормальный C++ (с шаблонами, ссылками, dynamic_cast-ами) и ОО библиотеки сильно упрощает жизнь.
Да не очень то перйдешь. И не очень то упрощает. Для этого ведь нормальный рантайм нужен. А его нет. Плюс борьба за скорость...
E>Правда еще и в том, что языками с GC является не только C#. Есть еще более мейнстримовая Java.
Куда ж более то?
E> Есть еще динамические языки. Когда я говорил о проблемах в языках со сборкой мусора, я говорил о собирательном образе. Ты же все к C# приводишь.
А что мне говорить о сферокониках. Есть дотнет и Шарп. Количество ошибок в них несравнимо меньше чем в С++. Тут даже обсуждать нечего. Можно только понты покидать о своей крутости (это я не о тебе, но таких хватает).
VD>>1. Объекты обычно выстраиваются в деревья и умирают целыми группами.
E>Или не умирают, если вершина дерева остается живой.
Примеры в студию.
VD>>В общем, ну нежно придумывать. Попробуй и все миф пройдут сами собой.
E>Пробую сейчас с Ruby. RAII не хватает, хотя там и можно применять приемы a-la C#-вский using.
Интересно, что примеров нет. И вспомнил ты об этом только сейчас. Странная проблема которая колышит только в спорах.
Кстати, Руби явно значительно менее защищенный от ошибок язык. Возможно в этом и дело.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
E>>Уверен. Нормальна C++ библиотека закрывает все ресурсы в деструкторах.
VD>Да? А С или АПИ? А если объект из нормальной С++-библиотеки создан через new или того хуже через malloc?
Через malloc объекты не создают. Даже если хочется разместить объект в заранее выделенном блоке памяти, то std::vector<char>, а затем placement new и все дела.
А если объект создается через new то для него тот же std::auto_ptr есть.
E>>В качестве примера еще можно библиотеку Qt привести. Там большинство объектов через new создается. А вызов delete -- крайне редкая операция. И никаких проблем нет,
VD>Редкая? Значит есть...
E>>потому что работа с памятью продумана: все объекты объеденены в иерархии родитель-потомок. И при уничтожении родителя все потомки уничтожаются автоматически.
VD>И сколько времени было затрачено на создание этой стратегии, а потом на отслеживание следование ей?
Сколько времени затрачено на создание теперь уже не важно. Qt уже лет десять, если не больше. А следовать этой стратегии совсем не сложно. Qt вообще очень легко изучается. Бывшие студенты осваивают ее в лет.
VD>А сколько случаев не вписались в идею дерева, и потребовали ручной обработки?
Не помню вообще такого. Там объекты хоть на стеке создавай, хоть в хипе -- они все равно корректно умирают.
VD>Дело в том, что так просто стараются не писать. А если пишут, то делают общий IDisposeble в Dispose которого освобождают ссылки.
Но ведь пишут. А с деструкторами писать не нужно
VD>А посутпают обычно так: VD>1. Читают все данные в рамках start и хранят тольк результат. А то и вооще ничего не хранят.
Ну это на тему "память больше не ресурс"
VD>2. Организуется пул ресурсов и для отдельных операций используются временные ресурсы которые можно освобождать или юсингом или оставить на отуп ЖЦ. VD>3. Делается итератор в котором все прозрачно. Юсинг в итераторе автоматом приводит к реализации освобождения ресурсов в Dispose-е итератора.
VD>Другими словами просто не занимаются такой фигней как явным хранением ссылок на ресурсы. Это вообще полезно, так как позволяет блокировать ресурсы на минимальное время.
E>> И коннекшены к БД.
VD>Вовсе нет. Подключение к БД не критичный ресурс.
Не знаю. Когда мне приходилось их отслеживать, это был весьма критичный ресурс, причем очень органиченный. Что-то типа 5 или 10 одновременных коннекшенов к БД.
E>>Кстати, std::ofstream, открытый для чтения/записи не блокирует файл и позволяет открыть тот же файл для изменения еще раз. Как той же программе, так и любой другой.
VD>Вот это как раз и есть п. 1. И ошибки с ним ловятся на раз. Файл ведь заблокирован.
Нет, Влад, простой std::ofstream или fopen не блокирует файл. Разве что от переименования. Для блокирования файла при открытии нужно либо CreateFile задействовать, либо sopen (это под Windows). А в Unix-е после открытия файла нужно через fcntl блокировать фрагмент файла.
VD>>>3. Память в языках без ЖЦ. Это самый частый случай в программировании. Средняя программа оперирует еденицами ресурсов ОС, и тысячами, а то и миллионами блоками памяти.
E>>Давай для объективности скажем, что в языках без ЖЦ огромное количество объектов создается на стеке и автоматически разрушается при выходе из области видимости. Работа с такими объектами вообще никаких проблем не вызывает.
VD>Дык вэлью-типы никто не отменял. Но в ОО-приложении без динамически созданных экземпляров обычно не обходится. В нормальном ОО-приложении количество памяти которую нужно контролировать просто огромно.
Обычно не обходится. Но так же обычно все эти операции с хипом очень тчательно от меня скрыты. Например, я много работаю с STL контейнерами (list, vector, deque, set, map) -- и практически всегда передаю туда ссылки на автоматические объекты, а не указатели. А уже контейнеры работают с хипом. Причем очень хорошо работают.
E>>А твой пример с драйвером БД, который инициирует сборку мусора при нехватке коннекшенов -- это сильно. Представим себе: многопоточное приложение с багом по освобождению коннекшена. Какие-то потоки генерят тысячи объектов. Один поток исчерпывает ресурсы и при очередном connection запускается GC. Все приложение замирает. И так периодически. Но наиболее часто в момент пиковой нагрузки, когда коннекшены запрашиваются с большой скоростью. Веселуха, короче.
VD>Почему замирают? Сборка мусора — это молниеносная операция.
VD>Вот ты тут все пошь: Апач, КуТи, АСЕ... А раскажи мне как будет выглядеть работа с венигретом в котором по некоторой не зависящей от тебя причине попало все это? Прикинь Апач на котором АСЕ, буст, кусти КуТи и т.п. У каждого свои политики владения объектами. Это же повеситься можно в преключении мозгов на их отслеживание!!!
К счастью, все эти библиотеки решают разные задачи (за исключением Apache Portable Runtime и ACE, но вряд ли кто-нибудь их в одном проекте сведет, все же APR -- это чисто C-шная либа). Поэтому в случае конкретно с ACE, Boost и Qt проблем я не вижу.
А вообще, ты прав. Объединение в одном C++ разнородных библиотек -- это серьезная задача. В языках с GC все на порядки проще.
E>>Вот что-то я не помню, где бы я такое говорил. Я говорил, что на Ruby у меня код меньше получается. Это есть.
VD>Ну, а где ты гворил о том, что в Руби есть проблемы с освобождением ресурсов?
А вот так эта проблема решается с помощью using-похожего механизма:
File.open( "myfile.txt" ) { |f| f.gets ... }
При выходе из блока кода с обработкой содержимого файла, файл автоматически закрывается. На самом деле там нет никаких фокусов c IDisposable, просто этот вариант open раскрывается во что-то подобное:
def File.open(file_name)
f = File.new(file_name)
if block_given? # Если передали в функцию блок кода...
begin # аналог try
yeild f # вызываем этот блок...
ensure # аналог finally
f.close
end
return nil
else
return f
end
end
E>> Я на днях потратил полчаса на то, чтобы понять, почему у меня чужая информация в мой Hash попадает. Оказалось потому, что я не сделал копирование Hash-а, а скопировал ссылку на него. И в Java, в свое время, я на такие грабли наступал. А вот в C++ такой ошибки бы в принципе не было.
VD>Это как? Где ты его брал?
А это я строил один Hash, ключем которого была строка, а значением -- еще один Hash с результатами обработки. Затем мне из этого Hash-а часть данных нужно было перекинуть во второй Hash. Ну я так и сделал:
b[ key ] = a[ key ]
Но на самом деле я скопировал ссылку на Hash с результатами обработки, а не его значение. Поэтому, когда я пошел дальше делать обработку b, то оказалось что значения из b как-то появляются в a
А нужно было делать:
b[ key ] = a[ key ].clone
E>>А откуда берутся ошибки типизации?
VD>От желания сделать его по быстрее (ну, там memmove/memset в С++).
За такие вещи руки, вообще-то отрывать нужно
E>>Правда еще и в том, что языками с GC является не только C#. Есть еще более мейнстримовая Java.
VD>Куда ж более то?
Более, более, не сумлевайся
Пока еще более. Хотя по своим фичам C# мне более симпатичен, чем Java. Туда бы еще нормальный code convention...
E>>Или не умирают, если вершина дерева остается живой.
VD>Примеры в студию.
E>Через malloc объекты не создают. Даже если хочется разместить объект в заранее выделенном блоке памяти, то std::vector<char>, а затем placement new и все дела.
Еще как создают. Я еще не те извращения видел.
E>А если объект создается через new то для него тот же std::auto_ptr есть.
Который нужно подставлять вручную. И какая разница с юсингом?
E>Сколько времени затрачено на создание теперь уже не важно. Qt уже лет десять, если не больше. А следовать этой стратегии совсем не сложно. Qt вообще очень легко изучается. Бывшие студенты осваивают ее в лет.
На КуТи свет клином не сошелся.
VD>>А сколько случаев не вписались в идею дерева, и потребовали ручной обработки?
E>Не помню вообще такого. Там объекты хоть на стеке создавай, хоть в хипе -- они все равно корректно умирают.
Пока дерево. Первое кольцо и...
VD>>Дело в том, что так просто стараются не писать. А если пишут, то делают общий IDisposeble в Dispose которого освобождают ссылки.
E>Но ведь пишут. А с деструкторами писать не нужно
Не пишут. У ламеров вообрежения на это не хватает, а у остальных хватает ума так не писать.
E>Ну это на тему "память больше не ресурс"
Для многих задач оптимальное решение — это построение модели данных в памяти. Для других пакетная обработка. Так что копья ломать?
E>Интересные примеры на эту тему Sinclair привел: Re[10]: Смотрел на Java код. ...много думал.
Ничего там интересного. Там куча лишних действий которые от избытка энергии разве что можно сделать.
E>Не знаю. Когда мне приходилось их отслеживать, это был весьма критичный ресурс, причем очень органиченный. Что-то типа 5 или 10 одновременных коннекшенов к БД.
Тебе уже сказали, что провайдеры в дотнете специально спроектированы в рассчете на пул. В рельных приложениях обычно не больше одиного соединение активно. В общем, опять таки высасывание проблемы из пальша если бы это было проблемой, то она часто встречалась бы на форуме. А это не так.
VD>>Вот это как раз и есть п. 1. И ошибки с ним ловятся на раз. Файл ведь заблокирован.
E>Нет, Влад, простой std::ofstream или fopen не блокирует файл. Разве что от переименования. Для блокирования файла при открытии нужно либо CreateFile задействовать, либо sopen (это под Windows). А в Unix-е после открытия файла нужно через fcntl блокировать фрагмент файла.
Думаю ты ошибаешся. Это как раз для параллельного доступа нужно CreateFile испольовать. К тому же это не важно. Если ресурс не блокируется, то это сразу перестает быть п. 1.
E>Обычно не обходится. Но так же обычно все эти операции с хипом очень тчательно от меня скрыты. Например, я много работаю с STL контейнерами (list, vector, deque, set, map) -- и практически всегда передаю туда ссылки на автоматические объекты, а не указатели. А уже контейнеры работают с хипом. Причем очень хорошо работают.
Опять же приходим к продумыванию политики владения объектами. В общем, автоматики как не было, так и нет. Есть головная боль. То что ты к ней привык не избавляет от нее. Время она отнимает.
VD>>Почему замирают? Сборка мусора — это молниеносная операция. E>
А что ты улыбашся. Это факт. Ты просто не интересовался этим вопросом серьезно. Я вот интересовался. Заметить на глаз процесс сборки мусора невозможно на современных процессорах.
E>К счастью, все эти библиотеки решают разные задачи (за исключением Apache Portable Runtime и ACE, но вряд ли кто-нибудь их в одном проекте сведет, все же APR -- это чисто C-шная либа). Поэтому в случае конкретно с ACE, Boost и Qt проблем я не вижу.
А ты почитай о планах создания Януса на С++. Как раз хотели запихнуть почти все это дело в одно приложение.
E>А вообще, ты прав. Объединение в одном C++ разнородных библиотек -- это серьезная задача. В языках с GC все на порядки проще.
Именно. И дело и менно в том, что каждая из них пропагандирует собственную политику владения объектами.
Вообще дотнет в принципе снимает много проблем именно стандартизацией. Там где в С++ приходится или выбирать что-то одно, или мириться с нестандартностью в Шарпе обычно решаетя однообразно да еще и описано в разных стайл-гайдах. В итоге повторное использование кода значительно выше.
E>Да хотя бы здесь: E>
А не ты ли говорил, что файл сам закроется при выходе из области видимости?
E>А вот так эта проблема решается с помощью using-похожего механизма: E>
E>File.open( "myfile.txt" ) { |f| f.gets ... }
E>
E>При выходе из блока кода с обработкой содержимого файла, файл автоматически закрывается. На самом деле там нет никаких фокусов c IDisposable, просто этот вариант open раскрывается во что-то подобное: E>
E>def File.open(file_name)
E> f = File.new(file_name)
E> if block_given? # Если передали в функцию блок кода...
E> begin # аналог try
E> yeild f # вызываем этот блок...
E> ensure # аналог finally
E> f.close
E> end
E> return nil
E> else
E> return f
E> end
E>end
E>
Ну, это далеко не юсинг. Это аналог форича и итераторов внутри которого стоит finally.
E>За такие вещи руки, вообще-то отрывать нужно
Надо, не надо. Но это факт. И в большинстве случаев работает. Вот только с меньшинством траху не оберешся.
E>Пока еще более. Хотя по своим фичам C# мне более симпатичен, чем Java. Туда бы еще нормальный code convention...
CS>Вот такой вот показательный пример,
CS>Фрагмент (очень неполный) читает нечто по протоколу superset of http
CS>Еще раз ничего личного ни про Java ни про другие фреймворки. CS>Просто разработка надежного кода занимает ровно то же самое время что с что без. CS>Глубокое заблуждение что если managed code то типа надежная система автоматом.
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>Здравствуйте, c-smile, Вы писали:
CS>>Проблема в том что среди десяти threads появляется одна в которой CS>>выполняется этот вот кусок. И все. Всем привет. CS>>GC начинает останавливать все потоки. Когда они *все* остановились CS>>тогда чистится мусор. Затем вся эта бодяга весело перезапускается. CS>>Тут же выпадая в следующий осадок. Потому как тот IP на котором CS>>работает приведенный фрагмент сидит на жирной трубе.
A>>>Зачем? Для этого у GC есть поколения.
CS>>Есть поколения и что? Не надо останавливать потоки? CS>>Такого чуда имхо еще нет. В Java есть но в специфических продуктах.
ANS>afair, в 1.5 есть конкурентные сборщики не только для "молодого" поколения (который "parallel"), но и для tenured (сборщик "concurent"). Он останавливает потоки не на всё время сборки мусора. ANS>Можно попробовать молодое поколение побольше сделать. Вы какие крутилки у ВМ крутили?
там вообще-то еще MS Java жужжит и кстати нормально так жужжит. Если при проектировании считать память ресурсом то все работает.
Здравствуйте, VladD2, Вы писали:
E>>А если объект создается через new то для него тот же std::auto_ptr есть.
VD>Который нужно подставлять вручную. И какая разница с юсингом?
Тем, что у std::auto_ptr есть методы reset и release, а так же std::auto_ptr передает владение указателем, что бывает очень удобно.
VD>>>Вот это как раз и есть п. 1. И ошибки с ним ловятся на раз. Файл ведь заблокирован.
E>>Нет, Влад, простой std::ofstream или fopen не блокирует файл. Разве что от переименования. Для блокирования файла при открытии нужно либо CreateFile задействовать, либо sopen (это под Windows). А в Unix-е после открытия файла нужно через fcntl блокировать фрагмент файла.
VD>Думаю ты ошибаешся. Это как раз для параллельного доступа нужно CreateFile испольовать. К тому же это не важно. Если ресурс не блокируется, то это сразу перестает быть п. 1.
Нет, я не ошибаюсь, вот пример:
#include <fstream>
#include <iostream>
#include <string>
#include <stdexcept>
void do_test()
{
const std::string file_name( "test.txt" );
const std::string content( "Hello, world!" );
// Пресоздаем файл для записи.
std::ofstream out_file( file_name.c_str(), std::ios::out | std::ios::trunc );
// И открываем его тут же для чтения.
std::ifstream in_file( file_name.c_str(), std::ios::in );
// Размер файла, открытого на чтение равен 0.
in_file.seekg( 0, std::ios::end );
if( 0 != in_file.tellg() )
throw std::runtime_error( "EOF in in_file expexted!" );
// Записываем в выходной файл строку...
out_file << content << std::flush;
// И считываем ее в том же виде из входного файла.
std::string in_line;
std::getline( in_file, in_line );
// Должна получиться та же самая строка.if( content != in_line )
throw std::runtime_error( "expected value: " + content +
", actual value: " + in_line );
}
int main()
{
try
{
do_test();
}
catch( const std::exception & x )
{
std::cerr << "Oops! " << x.what() << std::endl;
}
}
отрабатывает без исключений. Кстати, обрати внимание на выделенный фрагмент -- это принудительное флуширование. Без него тест не отрабатывает на коротких строках, т.к. они не сбрасываются в файл без явного флуширования. Это еще одна потенциальная проблема с незакрытыми файлами -- если не сделано флуширование (а его редко делают, т.к. отдают флуширование на откуп операции close) и файл не закрыт, то его содержимое на диске может отличаться от того, что мы в него записывали. Вот и ищи потом такой баг -- в одном месте все записали, а в другом читаем только часть записанных данных.
E>>Обычно не обходится. Но так же обычно все эти операции с хипом очень тчательно от меня скрыты. Например, я много работаю с STL контейнерами (list, vector, deque, set, map) -- и практически всегда передаю туда ссылки на автоматические объекты, а не указатели. А уже контейнеры работают с хипом. Причем очень хорошо работают.
VD>Опять же приходим к продумыванию политики владения объектами. В общем, автоматики как не было, так и нет. Есть головная боль.
Нет, Влад. Нет никакой головной боли. И политик владения здесь никаких придумывать не нужно -- выполняется простое копирование.
E>>К счастью, все эти библиотеки решают разные задачи (за исключением Apache Portable Runtime и ACE, но вряд ли кто-нибудь их в одном проекте сведет, все же APR -- это чисто C-шная либа). Поэтому в случае конкретно с ACE, Boost и Qt проблем я не вижу.
VD>А ты почитай о планах создания Януса на С++. Как раз хотели запихнуть почти все это дело в одно приложение.
Знаешь, фраза "планы о создания чего-нибудь" у меня вызывает только ироническую улыбку. Лично мой опыт показывает, что планировать можно что угодно и как угодно. А до реализации это в большинстве случаев не доходит. Так же и здесь. Проблема не в том, что слишком много инструментов предлагалось. А в том, что "предлагалось" вместо "использовалось".
E>>А вообще, ты прав. Объединение в одном C++ разнородных библиотек -- это серьезная задача. В языках с GC все на порядки проще.
VD>Именно. И дело и менно в том, что каждая из них пропагандирует собственную политику владения объектами.
+1
Для C++, имхо, это одна из причин того, что нет настолько серьезных фреймворков, как JDK, .NET Framework, Perl CPAN или RubyGems. И, как следствие, понижает шансы C++ в борьбе с более молодыми и централизованно развиваемыми конкурентами.
VD>Вообще дотнет в принципе снимает много проблем именно стандартизацией. Там где в С++ приходится или выбирать что-то одно, или мириться с нестандартностью в Шарпе обычно решаетя однообразно да еще и описано в разных стайл-гайдах. В итоге повторное использование кода значительно выше.
+1
Это не только в Шарпе так. Но и в Java, и в Python, и в Ruby.
E>>Да хотя бы здесь: E>>
E>>При выходе из блока кода с обработкой содержимого файла, файл автоматически закрывается. На самом деле там нет никаких фокусов c IDisposable, просто этот вариант open раскрывается во что-то подобное: E>>
...
E>>
VD>Ну, это далеко не юсинг. Это аналог форича и итераторов внутри которого стоит finally.
Не, Влад, не утрируй. Я не утверждал, что в Java столько же ликов, сколько в C++. Но вот то, что они бывают, это точно. К тому же я упеваю читать только "Философию программирования" и, изредка, форумы по C++ и Unix. А в форумы по Java вообще не заглядываю.
Ты, кстати, сам как оцениваешь популярность Java-вского форума на Rsdn? Судя по количеству приверженцев Java в "Философии программирования" на Rsdn их относительно не много (по сравнению с C++ и .Net).
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
VD>Ничего там интересного. Там куча лишних действий которые от избытка энергии разве что можно сделать.
А, ну то есть то, что орлы в MS не смогли корректно реализовать IDisposable — это от избытка энергии? А я-то дурак думал, это от того, что понять, когда вызывать Dispose на мембере, не всегда так легко, как хотелось. Я тебе еще десяток могу примеров привести, но они, в отличие от System.Drawing.Image, будут вымышленными.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>А, ну то есть то, что орлы в MS не смогли корректно реализовать IDisposable — это от избытка энергии?
Уроды потому что. Это всего лишь пример дизайнерской ошибки. Наботу с картинками нужно было реализовывать как набор статических методов. Один для чтения заголовка, другой для работы с картинкой, третий для работы с ее содержимым.
S> А я-то дурак думал, это от того, что понять, когда вызывать Dispose на мембере, не всегда так легко, как хотелось. Я тебе еще десяток могу примеров привести, но они, в отличие от System.Drawing.Image, будут вымышленными.
Во-вот. Вымешленных. Это все и объясняет. А по жизни я что-то проблем не встречаю.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Это с непривычки. Когда появились Фортран, С и Паскаль народ долгое время упиравшися в работу максимум на уровне ассемблеров, а в основном машинных кодов, тоже не весь сразу оценил приемущество языков высокого уровня. По началу тоже не видили приемуществ. Точнее считали что недостатки (тормоза ведь какие?!) перевешивали.
Здравствуйте, VladD2, Вы писали:
VD>У профи, по-моему, должно быть понимание, что в не типобезопасных языках избавиться от утечек памяти и вообще от проблем с ее интерпретацией можно только путем нехилого тестирования. И то полной гарантии не будет. И это при том, что вопрос о том что нужно стараться делать контроль за ресурсами автоматически даже не обсуждается.
Про умные указатели не слыхали? Или вспомнить религия не позволяет?
Здравствуйте, savaDAN, Вы писали:
E>>Какие-такие смартпоинтеры, которые толком не поддерживаются компилятором. DAN>Ну например о которых Джэф Элджер в С++ библиотека программиста пишут. DAN>ИМХО, сказать что эти сущности полностью поддерживаются компилятором (в том смысле что не позволят программисту допустить ошибку с управлением памятью) — нельзя.
А что, .NET языки полностью исключают ошибку программиста? Может они тогда и программы сами писать уже умеют?
DAN>Я уж не говорю о всяких вещах типа "кто создает память?", "кто удаляет память?", что _вообще_ не поддерживается компилером, только соглашениями и архитектурой. опять лишний источник ошибок для программиста и лишняя работа тестерам.
Что значит "не поддерживается компилером"? Вот у меня уже не первый десяток проектов с пулами потоков и распределенным взаимодействием на С++ сдано в эксплуатацию, и что-то как-то не нарываюсь на меморилики.... видимо не судьба...
E>>>Какие-такие смартпоинтеры, которые толком не поддерживаются компилятором. DAN>>Ну например о которых Джэф Элджер в С++ библиотека программиста пишут. DAN>>ИМХО, сказать что эти сущности полностью поддерживаются компилятором (в том смысле что не позволят программисту допустить ошибку с управлением памятью) — нельзя. LM>А что, .NET языки полностью исключают ошибку программиста? Может они тогда и программы сами писать уже умеют?
а где это вы такое у меня прочитали? я писал лишь о том что допустить ошибку при работе с памятью на .NET значительно сложнее чем на С++ и особенно на С.
DAN>>Я уж не говорю о всяких вещах типа "кто создает память?", "кто удаляет память?", что _вообще_ не поддерживается компилером, только соглашениями и архитектурой. опять лишний источник ошибок для программиста и лишняя работа тестерам. LM>Что значит "не поддерживается компилером"? Вот у меня уже не первый десяток проектов с пулами потоков и распределенным взаимодействием на С++ сдано в эксплуатацию, и что-то как-то не нарываюсь на меморилики.... видимо не судьба...
Это значит что мне приходится в документе описывающим архитектуру проекта, или в комментариях к методу или еще где-то писать "уважаемые разработчики! передайте в эту функцию вами выделенный буфер и не забудьте его потом удалить", и далее, никакими средствами кроме code review или долгим дебагированием я ошибку разработчика, нарушившего этого правило не найду.
По поводу сданных вами проектов в реализацию: ну где я писал о том, что на С/С++ нельзя писать больших проектов? Я писал только что на языках с автоматическим управлением памятью их писать быстрее, потому что допускаешь меньше ошибок и тратишь меньше ресурсов.
Влад писал об этом ниже. Прочитайте, пожалуйста, всю ветку.
Здравствуйте, VladD2, Вы писали: VD>Уроды потому что.
О! Это все объясняет. Конечно же. В том то и дело, что крайне трудно быть неуродами. Может, МС там девелоперам недоплачивает? И туда идут только студенты от безысходности? VD> Это всего лишь пример дизайнерской ошибки. Наботу с картинками нужно было реализовывать как набор статических методов. Один для чтения заголовка, другой для работы с картинкой, третий для работы с ее содержимым.
Да-да-да. И это бы автоматически реализовало диспозабл за нас. VD>Во-вот. Вымешленных. Это все и объясняет. А по жизни я что-то проблем не встречаю.
Везет значит. Я вот — встретил. В самом что ни на есть кошерном коде. К счастью, удалось это оттрассировать быстро — часа за четыре. Это, Влад, тебе только кажется, что "файл залокан — сразу найдешь". Во-первых, залокан он только на чтение, и ты об этом не узнаешь, пока не начнешь в него писать. Во-вторых, GC таки отрабатывает нулевое поколение шустро, и обнаружить проблему можно только под некоторой нагрузкой. В-третьих, это не такая маленькая проблема. Если бы фреймворк при открытии файла ждал, пока его отпустят, это был бы всего лишь перформанс проблем. Увы — обнаруживается это как странные ексепшны во время работы приложения. То есть твои пользователи в 5 случаях из 100 получают 500 Error. Для справки: при 10000 визитах в день, 5% — это 500 человек. Примерно одна десятая от них звонит в тех. суппорт. Представляешь себе расходы на это? Оттого, что некорректно реализован IDisposable.
Твои рассуждения о легкости реализации, они, извини, языком. Языком мы все с феноменальной легкостью пишем супернадежный безошибочный код.
А если у тебя есть какие-то соображения на тему того, как писать код, устойчивый к таким проблемам, то расскажи нам, пожалуйста. А мы, в свою очередь, проведем ликбез среди девелоперов в MS. А то я вот не уверен, что нашел единственный глюк во всем фреймворке.
1.1.4 stable rev. 510
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>О! Это все объясняет. Конечно же. В том то и дело, что крайне трудно быть неуродами. Может, МС там девелоперам недоплачивает? И туда идут только студенты от безысходности?
В МС слишком много программистов. Так что есть там и уроды, и нормальные люди. К сожелению кучу второстепенного кода пишут далеко не самые лучшие представители. Посему во фрэймворке косяков хватает.
S>Да-да-да. И это бы автоматически реализовало диспозабл за нас.
Это избавило бы от ситуации когда имеется неявно заблокированный ресурс. Посмотри как написан тот же АПИ к фаловой системе. Там похожих мест масса, но блокировки файлов не просходит.
VD>>Во-вот. Вымешленных. Это все и объясняет. А по жизни я что-то проблем не встречаю. S>Везет значит. Я вот — встретил. В самом что ни на есть кошерном коде. К счастью, удалось это оттрассировать быстро — часа за четыре.
Один раз? Ну, это конечно сразу бросает огромную тень. Ты попиши на голом ВыньАпи и посмотри сколько там косяков вылезает. Все, как бы, познается в сравнении.
S> Это, Влад, тебе только кажется, что "файл залокан — сразу найдешь".
А, ну, ясно это у меня глюки. Проблема то есть, но она как суслик... ее не видно...
S> Во-первых, залокан он только на чтение, и ты об этом не узнаешь, пока не начнешь в него писать.
При эксклюзивной то блокировке используемой по умолчанию? Ну-ну.
S> Во-вторых, GC таки отрабатывает нулевое поколение шустро, и обнаружить проблему можно только под некоторой нагрузкой.
Не так быстро как тебе кажется. Конечно вероятность получить тнудно понимаемую ошибку есть, но она довольно эфимерна. Как раз под нагрузкой ЖЦ пашет чаще.
S> В-третьих, это не такая маленькая проблема. Если бы фреймворк при открытии файла ждал, пока его отпустят, это был бы всего лишь перформанс проблем.
Да? И с чего бы это? Проблем с производительностью открытый файл не создает. Он создает блокировку. Вот она уже может попродить проблемы, но не с производительностью.
S> Увы — обнаруживается это как странные ексепшны во время работы приложения. То есть твои пользователи в 5 случаях из 100 получают 500 Error. Для справки: при 10000 визитах в день, 5% — это 500 человек. Примерно одна десятая от них звонит в тех. суппорт. Представляешь себе расходы на это? Оттого, что некорректно реализован IDisposable.
Ага. Теперь остается умножить это на количество населения в стране, и из этих данных уже можно будет узнать сколько у нас аэродромов. (с) Райкин.
Что за манера производить вычисления над высасаными из пальца цифрами и делать на их базе далеко идущие выводы?
Давай проще. Подведи статистику проблем с незакрытыми файлами на базе нашего форума. Если она окажется хоть сколь-нибудь значимой, то продолжим разговор. А если нет, то и говорить не очем, так как проблема высасона из пальца.
Лично я вообще не помню, чтобы кто-то поднимал вопрос о блокировках файлов.
S>Твои рассуждения о легкости реализации, они, извини, языком. Языком мы все с феноменальной легкостью пишем супернадежный безошибочный код.
Я то с файлами работаю плотно. И как-то особых проблем не заметил. А вот ты... ну, да я уже все сказал.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Давай проще. Подведи статистику проблем с незакрытыми файлами на базе нашего форума. Если она окажется хоть сколь-нибудь значимой, то продолжим разговор. А если нет, то и говорить не очем, так как проблема высасона из пальца. VD>Лично я вообще не помню, чтобы кто-то поднимал вопрос о блокировках файлов.
Эээ.. Не знаю насколько я в тему попаду щас, но у меня (правда редко) при чтении форумов вываливается ошибка что то типа "база блаблабла залочена пользователем Admin. Все в сад!" Лечится перезапуском януса. Оно?
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, CreatorCray, Вы писали:
CC>Эээ.. Не знаю насколько я в тему попаду щас, но у меня (правда редко) при чтении форумов вываливается ошибка что то типа "база блаблабла залочена пользователем Admin. Все в сад!" Лечится перезапуском януса. Оно?
Такое сообщение бывает если параллельно запустить Эксес и открыть в нем БД Януса. Вот только это проблемы джета написанного на С++.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
CS>Вот такой вот показательный пример,
CS>Фрагмент (очень неполный) читает нечто по протоколу superset of http
CS>
... поскипано
CS>
Всё оттого что товарищ курс о структурах данных и алгоритмах не слушал и выше уровня кодера не поднялся, а ещё оттого что с появлением управляемых языков о производительности, оптимизации можно забыть, а с неи и Кнута похоронить.
Здравствуйте, savaDAN, Вы писали:
CS>>Внимание! я не критикую автора. Я просто хочу обратить внимание CS>>на то как safe код фактически рушит систему — код работал на клиенте CS>>и возникла потребность перенсти его на сервер. Сервер не сказать CS>>чтобы умер — просто перестал "серверить". DAN>Ага, при этом если бы человек начал писать данный код оптимально, потратив в 2-3 раза времени больше (с учетом отладки и поиска ошибок), то получил бы нагоняй от менеджера за то что занимается gold plating-ом и срывает сроки.
Просто есть разные фирмы с разной политикой найма работником, у Джоэла кстати об этом есть статься. Есть програмисты звёзды, а есть кодеры. И то на что первый потратит 10 минут причём и отладит за это время другой иа день не сделает.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, CreatorCray, Вы писали:
CC>>Эээ.. Не знаю насколько я в тему попаду щас, но у меня (правда редко) при чтении форумов вываливается ошибка что то типа "база блаблабла залочена пользователем Admin. Все в сад!" Лечится перезапуском януса. Оно?
VD>Такое сообщение бывает если параллельно запустить Эксес и открыть в нем БД Януса. Вот только это проблемы джета написанного на С++.
Дык нету аксесса. Из офиса стоит только ворд+excel. Все остальное принудительно не ставилось.
Шож ета такие правильные .нет девелоперы да такой неправильный Jet использовали? Почему не .нет-овское что нить? ась?
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
savaDAN,
> мне приходится в документе описывающим архитектуру проекта, или в комментариях к методу или еще где-то писать "уважаемые разработчики! передайте в эту функцию вами выделенный буфер и не забудьте его потом удалить", и далее, никакими средствами кроме code review или долгим дебагированием я ошибку разработчика, нарушившего этого правило не найду.
А ведь можно было вместо этих "приседаний" завести специальный тип указателя, обозначавшего именно эту семантику, и тогда компилятор стоял бы на страже, и комментарии/документация подобного содержания не понадобились бы...
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
ПК>А ведь можно было вместо этих "приседаний" завести специальный тип указателя, обозначавшего именно эту семантику, и тогда компилятор стоял бы на страже, и комментарии/документация подобного содержания не понадобились бы...
А давайте вы мне дадите конкретный пример, а я покажу вам как вследствие невнимательности/неопытности разработчика можно допустить ошибку в его использовании, хотя я думаю вы и сами, если используете подобные типы указателей, наверняка с такими ошибками сталкивались.
Да и опять же — этот смарт поинтер надо а) написать, б) объяснить всем как использовать, с) использовать, д) этот указатель будет несовместим с другими типами таких же умных указателей разработанных другими авторами в других библиотеках (от которых у вас и исходников может не быть). Как минимум 4 источника багов, не говоря уже о дополнительных затратах во время разработки проекта.
В общем у меня начинает складываться впечатление, что мы спорим об очевидном, просто ради спора.
Если бы в С++ все было хорошо с управлением памятью никто бы GC не изобретал.
DAN>>Ага, при этом если бы человек начал писать данный код оптимально, потратив в 2-3 раза времени больше (с учетом отладки и поиска ошибок), то получил бы нагоняй от менеджера за то что занимается gold plating-ом и срывает сроки.
S>Просто есть разные фирмы с разной политикой найма работником, у Джоэла кстати об этом есть статься. Есть програмисты звёзды, а есть кодеры. И то на что первый потратит 10 минут причём и отладит за это время другой иа день не сделает.
[OFF]
Хм, у меня возникает нехорошее впечатление, что кроме Джоэла на этом форуме больше никто ничего не читает.
Брукс об этом писал за 20 лет до Джоэла, ДеМарко с Листером об этом писали, МкКоннел об этом писал. Лучше бы их в пример привели, чем статьи глубоко уважаемого Джоэла, который по сути колумнист и автор системы багтрекинга.
[/OFF]
Теперь по теме: Забивать гвозди микроскопом, во-первых, очень дорого, во-вторых, неэффективно, в-третьих, микроскоп сломается и уйдет в другую фирму потому как хочет чтобы им микробов смотрели, а не гвозди забивали.
S>Всё оттого что товарищ курс о структурах данных и алгоритмах не слушал и выше уровня кодера не поднялся, а ещё оттого что с появлением управляемых языков о производительности, оптимизации можно забыть, а с неи и Кнута похоронить.
А вы разве еще не поняли зачем это все? Зачем все эти .NET-ы, GC и прочая? И почему мы перестали писать суперэффективные программы на ассемблере?
А потому что задач много, а хороших программистов мало. И потому что бизнесу надо денег зарабатывать, а не плясать вокруг дорогостоящих гуру. ИМХО основные усилия в ИТ индустрии направлены на то, чтобы как можно менее квалифицированный персонал мог делать как можно больше работы с приемлемым качеством. Да и не только в ИТ к этому стремятся, просто ИТ индустрия молодая, поэтому еще не успела дойти до конвейера.
"мы не разработчики, мы пользователи программного продукта по имени компилятор" (С) к сожалению забыл.
DAN>>Если бы в С++ все было хорошо с управлением памятью никто бы GC не изобретал. E>Так просто, реплика: GC изобрели и начали использовать задолго до появления C++.
Коненчно. My fault.
Исправляюсь:
"Если бы в С++ все было хорошо с управлением памятью, никто бы не тащил GC в mainstream языки типа Java и .NET"
Здравствуйте, CreatorCray, Вы писали:
CC>Шож ета такие правильные .нет девелоперы да такой неправильный Jet использовали? Почему не .нет-овское что нить? ась?
N-ный участник форума задает этот вопрос. Тенденция, однако.
Пора на заставке Януса написать: Использован Jet, поскольку .Net-овского аналога пока нет. Ждем-с.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, savaDAN, Вы писали:
S>>Всё оттого что товарищ курс о структурах данных и алгоритмах не слушал и выше уровня кодера не поднялся, а ещё оттого что с появлением управляемых языков о производительности, оптимизации можно забыть, а с неи и Кнута похоронить. DAN>А вы разве еще не поняли зачем это все? Зачем все эти .NET-ы, GC и прочая? И почему мы перестали писать суперэффективные программы на ассемблере? DAN>А потому что задач много, а хороших программистов мало. И потому что бизнесу надо денег зарабатывать, а не плясать вокруг дорогостоящих гуру. ИМХО основные усилия в ИТ индустрии направлены на то, чтобы как можно менее квалифицированный персонал мог делать как можно больше работы с приемлемым качеством. Да и не только в ИТ к этому стремятся, просто ИТ индустрия молодая, поэтому еще не успела дойти до конвейера.
Логика получается какая-то вывернутая: изобретение комбайна было направлено на то чтобы больше менее квалифицированных косарей больше косили...
Может таки лучше чтобы хорошие программисты писали больше и лучшие программы?
CS>Логика получается какая-то вывернутая: изобретение комбайна было направлено на то чтобы больше менее квалифицированных косарей больше косили...
CS>Может таки лучше чтобы хорошие программисты писали больше и лучшие программы?
некорректное сравнение.
Тоже не самое лучшее, но то что первым пришло в голову:
Древообрабатывающий станок был изобретен для того, чтобы больше менее квалифицированных столяров могли работать с деревом. То, что классные столяры будут делать еще более классные вещи — побочное приятное дополнение. Обществу, грубо говоря, важнее 5 млн. табуреток, чем 1 один стул выполненный как произведение искусства, даже не смотря на то, что у табуретки качество куда ниже.
CS>Вопрос: означенная фирма до конца ли понимает "назначение управляемых сред"? Как думаешь?
Проблема с Dimension не в том, что "фирма не понимает".
"Просто" был допущен архитектурный просчёт, пока все ещё были молодые и не опытные
Либо нужно было делать Dimension immutable объёктом, либо добавлять везде методы
ака void getPreferredSize(Dimension dest, ...).
Этот момент был упущен, ну а дальше пришлось тащить его из-за необходимости обеспечения обратной совместимости версий
(с) по мотивам "Effective Java. Programming Language Guide" Джошуа Блоха.
CS>ПыСы: Там еще кстати замечательное такое слово synchronized используется. "Для знатоков штучка".
Не скажешь в какой версии jdk ты нашёл этот код? А то я всё перерыл — нет такого
savaDAN,
> ПК> А ведь можно было вместо этих "приседаний" завести специальный тип указателя, обозначавшего именно эту семантику, и тогда компилятор стоял бы на страже, и комментарии/документация подобного содержания не понадобились бы...
> А давайте вы мне дадите конкретный пример,
Запросто. Только давайте проясним один момент...
> а я покажу вам как вследствие невнимательности/неопытности разработчика можно допустить ошибку в его использовании
Расшифруйте, что такое в вашем понимании "неопытность". Это незнание каких-то вещей, или общее отношение, при котором человек не стремится разобраться в классе/компоненте, которые начинает использовать?
> В общем у меня начинает складываться впечатление, что мы спорим об очевидном, просто ради спора. > Если бы в С++ все было хорошо с управлением памятью никто бы GC не изобретал.
: определения семантики владения объектами. Т.е. кроме освобождения памяти при удалении объекта еще нужно совершать некоторые действия. В C# это делается с помощью Dispose. Попробуйте применить ваши рассуждения к Dispose, чтобы я лучше понял, о чем идет речь...
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, eao197, Вы писали:
E>N-ный участник форума задает этот вопрос. Тенденция, однако. E>Пора на заставке Януса написать: Использован Jet, поскольку .Net-овского аналога пока нет. Ждем-с.
Вообще-то есть SQL Server-ный вариант. И он вроде как летает.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, CreatorCray, Вы писали:
VD>>Такое сообщение бывает если параллельно запустить Эксес и открыть в нем БД Януса. Вот только это проблемы джета написанного на С++. CC>Дык нету аксесса. Из офиса стоит только ворд+excel. Все остальное принудительно не ставилось.
Короче, приведи стэк-трэйс и поговорим конкретно. Пока что я склоняюсь к мысли, что ты что-то путашь.
CC>Шож ета такие правильные .нет девелоперы да такой неправильный Jet использовали? Почему не .нет-овское что нить? ась?
Альтернатива? Написать для проекта создающегося в свободное от отдыха иработы время собственную БД?
Кого не устраивает Эксес может попробовать использовать Сиквел. Текущая версия Януса это позволяет.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Короче, приведи стэк-трэйс и поговорим конкретно. Пока что я склоняюсь к мысли, что ты что-то путашь.
Как только в очередной раз вывалится — постараюсь не забыть что обещал тебе показать трейс.
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, NotGonnaGetUs, Вы писали:
CS>>Это вот родной код фирмы Sun:
CS>>
CS>>
CS>>Вопрос: означенная фирма до конца ли понимает "назначение управляемых сред"? Как думаешь?
NGG>Проблема с Dimension не в том, что "фирма не понимает". NGG>"Просто" был допущен архитектурный просчёт, пока все ещё были молодые и не опытные
Архитектурный просчет называется "GC он умный, сам все уберет" я так понимаю.
CS>>ПыСы: Там еще кстати замечательное такое слово synchronized используется. "Для знатоков штучка".
NGG>Не скажешь в какой версии jdk ты нашёл этот код? А то я всё перерыл — нет такого
Это из Personal Java сейчас это по-моему J2ME называется.
Первое что попалось под руку.
Вот пример из стандартного набора примеров стандартного SDK
Я выделил те места где в методе on paint аллоцируются новые объеты:
public class BullsEye extends DemoSurface {
public void drawDemo(int w, int h, Graphics2D g2) {
Color reds[] = { Color.red.darker(), Color.red };
for (int N = 0; N < 18; N++) {
float i = (N + 2) / 2.0f;
float x = (float) (5+i*(w/2/10));
float y = (float) (5+i*(h/2/10));
float ew = (w-10)-(i*w/10);
float eh = (h-10)-(i*h/10);
float alpha = (N == 0) ? 0.1f : 1.0f / (19.0f - N);
if ( N >= 16 )
g2.setColor(reds[N-16]);
else
g2.setColor(new Color(0f, 0f, 0f, alpha));
g2.fill(new Ellipse2D.Float(x,y,ew,eh));
}
}
Т.е. приложение ничего не делает но аллокация идет непрерывно.
Вот характерный скриншот: справа — memory monitor.
Видим явную пилу. Провалы — это сборка мусора — приложение застывает.
Извиняюсь но такое решение UI грамотным я называть не могу.
Здравствуйте, c-smile, Вы писали:
CS>Архитектурный просчет называется "GC он умный, сам все уберет" я так понимаю.
Сарказм — это хорошо. Только в просчёт был в другом
CS>Вот пример из стандартного набора примеров стандартного SDK CS>[java] CS>public class BullsEye extends DemoSurface {
Это не библиотеки java — это демки, а в них, хоть это и не красиво, но не фатально писать плохой код.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Конвеер неприменим к разработке дизайна продуктов, каковым является программирование при построении аналогий с производством "материальных" продуктов.
Черт его знает. С одной стороны в плане аналогий ты конечно прав (и вобще меня последнее время дурацкие аналогии софтостроения с автомобилями, зданиями, табуретками и прочей фигней задолбали, а особенно задолбали далеко идущие из этих аналогий выводы). С другой стороны не могу не согласится, что точка приложения интеллектуальных усилий смещается все больше со стороны машинных кодов в сторону проектирования и планирования. В этом отношении весьма показателен подход Team System, когда управление требованиями, разработка архитектур на разных уровнях, написание кода, его тестирование и, наконец, сценарии развертывания объединяются в один непрерывный итеративный процесс, в котором непосредственно написатели кода играют отнюдь не самую главную роль.
AndrewVK,
> С другой стороны не могу не согласится, что точка приложения интеллектуальных усилий смещается все больше со стороны машинных кодов в сторону проектирования и планирования.
Это всегда так было.
> В этом отношении весьма показателен подход Team System, когда управление требованиями, разработка архитектур на разных уровнях, написание кода, его тестирование и, наконец, сценарии развертывания объединяются в один непрерывный итеративный процесс, в котором непосредственно написатели кода играют отнюдь не самую главную роль.
Я отрицательно отношусь к "архитекторам", непосредственно не пишущим код: ИМХО, они достаточно быстро "теряют нюх". Итеративные процессы не являются новинкой, введенной Team System, а существовали уже задолго до, и начались именно с небольших команд, где все что-то делают "руками": Lead Developer/Architect ощутимую часть времени пишет код, Lead QA ощутимую часть времени занят непосредственным исполнением тестов и т.п.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
>> С другой стороны не могу не согласится, что точка приложения интеллектуальных усилий смещается все больше со стороны машинных кодов в сторону проектирования и планирования.
ПК>Это всегда так было.
Ну вобщем да. Единственное, происходит этот процесс не линейно, а скачками.
ПК>Я отрицательно отношусь к "архитекторам", непосредственно не пишущим код: ИМХО, они достаточно быстро "теряют нюх".
Одно другому не мешает. Архитектор конечно писать код должен, но деньги ему платят совсем за другое.
ПК> Итеративные процессы не являются новинкой, введенной Team System, а существовали уже задолго до,
Дело не в императивности, дело в подходе. Когда нет жестко очерченой границы между разработкой и деплойментом, к примеру.
DAN>Брукс об этом писал за 20 лет до Джоэла, ДеМарко с Листером об этом писали, МкКоннел об этом писал. Лучше бы их в пример привели, чем статьи глубоко уважаемого Джоэла, который по сути колумнист и автор системы багтрекинга.
Привёл его потому как его читал недавно и он быстрее вспомнился. Кроме того в его статьях кратко и с юмором делается квинтессенция из процитированых вами авторов, кроме того с конкретнымы примерами в современных реальных условиях разработки.
DAN>Теперь по теме: Забивать гвозди микроскопом, во-первых, очень дорого, во-вторых, неэффективно, в-третьих, микроскоп сломается и уйдет в другую фирму потому как хочет чтобы им микробов смотрели, а не гвозди забивали.
Ну это уже задача руководства как этот микроскоп удержать.
DAN>Обществу, грубо говоря, важнее 5 млн. табуреток, чем 1 один стул выполненный как произведение искусства, даже не смотря на то, что у табуретки качество куда ниже.
При Союзе вырабатывалось много безполезных вещей, которые тут же шли на свалку, обувь в которой невозможно было ходить, мебли которые без ножовки и молотка нельзя было собрать.
В начале топика автор привёл результат такой идеологии система просто не работает, всегда есть какой-то критерий минимального качества, если им пренебречь то получаем плачевные результаты.
eao197,
> Добавленный в C# unsing уже упрощает работу с ресурсами. Но это не RAII. Нормально сделан RAII в сочетании со сборкой мусора в языке D. Да только D пока в таком состоянии, что очень стремно на нем проекты делать.
Еще в C++/CLI или C++ плюс внешнаяя GC (например, Hans Boehm).
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Sinclair,
> Кстати, о птичках. Управление неуправляемыми ресурсами из управляемого кода — та еще песня > Особенно это касается взаимодействия нескольких Disposable-объектов. <...>
C++/CLI поможет отцу русской демократии (ессно, кроме ошибок в .Net Framework)
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
DAN>>Обществу, грубо говоря, важнее 5 млн. табуреток, чем 1 один стул выполненный как произведение искусства, даже не смотря на то, что у табуретки качество куда ниже. S>При Союзе вырабатывалось много безполезных вещей, которые тут же шли на свалку, обувь в которой невозможно было ходить, мебли которые без ножовки и молотка нельзя было собрать.
Аналогии неуместны. Мы в свободном рынке, ПО с недостаточным уровнем качества либо слишком дорогое покупать никто не будет.
S> В начале топика автор привёл результат такой идеологии система просто не работает, всегда есть какой-то критерий минимального качества, если им пренебречь то получаем плачевные результаты.
Приведенный автором код отлично работал там, где он и должен был работать (на клиентской машине), после перетаскивания без адаптации на сервер работать перестал, что логично, т.к. я уверен в требованиях нигде не было написано "должен работать под любой нагрузкой".
И я думаю РМ этого проекта, во-первых, на эту функциональность поставил кого-нить послабей, а, во-вторых, ревью не делал, что в данной ситуации является вполне верным решением.
Да, код не самый лучший, да, более опытный разработчик написал бы его куда оптимальней, но опытных разработчиков надо ставить на наиболее важные задачи, а не разбрасываться этим ресурсом куда попало, иначе стоимость проекта возрастет до заоблачных высот.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Я отрицательно отношусь к "архитекторам", непосредственно не пишущим код: ИМХО, они достаточно быстро "теряют нюх". Итеративные процессы не являются новинкой, введенной Team System, а существовали уже задолго до, и начались именно с небольших команд, где все что-то делают "руками": Lead Developer/Architect ощутимую часть времени пишет код, Lead QA ощутимую часть времени занят непосредственным исполнением тестов и т.п.
Именно. Так и работаем. Иначе очень быстро можно от реальности оторваться. А если ты становишься неадекватен как руководитель, то наиболее адекватные работники того, голосуют ногами.
Здравствуйте, Павел Кузнецов, Вы писали:
>> Не, ты мне вот покажи на нашем форуме... Ну, должно же быть такое же засилие вопросов как по ликам в С++?
ПК>Вопросы по GC и управлению временем жизни объектов задают каждые несколько дней:
Ненадо поменять суть вопроса. Вопросы по внутреннему встройсву или поведению могут быть в люой области, ты мне покажи засилие вопросв типа "у меня течет ххх... ничего не помогает... как быть?". Вот в форуме "С++" я тебе их тоннами раною.
Точ то приводишь ты в большинстве слвучае вообще к ликам тоношения не имеет.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
> ты мне покажи засилие вопросв типа "у меня течет ххх... ничего не помогает... как быть?"
Ты вопросы читал?
> Точ то приводишь ты в большинстве слвучае вообще к ликам тоношения не имеет.
Речь не об утечках (кто там против "калек" с английского боролся?), а о тех или иных проблемах с GC и управлении временем жизни объектов. "Утечки" -- одна из разновидностей проблем.
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
>> ты мне покажи засилие вопросв типа "у меня течет ххх... ничего не помогает... как быть?"
ПК>Ты вопросы читал?
Я его писал.
>> Точ то приводишь ты в большинстве слвучае вообще к ликам тоношения не имеет.
ПК>Речь не об утечках (кто там против "калек" с английского боролся?), а о тех или иных проблемах с GC и управлении временем жизни объектов. "Утечки" -- одна из разновидностей проблем.
Так есть пробемы или нет? Если нет, то закроем тему. Если есть, то хотелось бы их видеть. Я вот помню только проблему с событиями синглтонов. Явно редкая проблема. Уж точно ни в какое сравнение с постоянным отслеживанием политик владения объектами не идет.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VladD2,
>>> ты мне покажи засилие вопросв типа "у меня течет ххх... ничего не помогает... как быть?" > > ПК>Ты вопросы читал? > > Я его писал.
Последний шанс. Вопросы те, ссылки на которые я привел выше.
> ни в какое сравнение с постоянным отслеживанием политик владения объектами не идет.
Проблема как раз в том, что, как видно по вопросам, ссылки на которые я привел выше, это все равно приходится делать, только в условиях когда об этом постоянно не заботятся (читай, когда с этим делом бардак, и (почти) нет средств автоматизации этих задач).
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, c-smile, Вы писали:
CS>Резюме: Наличие высокоуровневых языков с GC и библиотек это конечно здорово, но! CS>результат который вот реально получился тот же примерно что и поймать GPF в С++. CS>Для нахождения где оно и как оно клинит сервер ушел один день — ровно столько сколько CS>бы вызвало устранение GPF.
Гы. Если писать на правильном С++ и если где-то есть catch (std::bad_alloc &) или catch (...) при обработке запроса, результат будет примерно такой же
Правильно работающая программа — просто частный случай Undefined Behavior
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Последний шанс.
ПК> Вопросы те, ссылки на которые я привел выше.
Читал. И про наличие утечек там ни слова. Там один теоритеческие вопросы.
>> ни в какое сравнение с постоянным отслеживанием политик владения объектами не идет.
ПК>Проблема как раз в том, что, как видно по вопросам, ссылки на которые я привел выше, это все равно приходится делать, только в условиях когда об этом постоянно не заботятся (читай, когда с этим делом бардак, и (почти) нет средств автоматизации этих задач).
Это твои выдумки. Никто о политиках владения в большинстве случаев не заботится. Все получается само собой. Ты просто проектируешь граф объектов и пишеш код его использующий. Ни в какое сравнение с отслеживанием политик владения в С++ (коих море) это не идет. Пытаться поставить тут знак равенства значит заниматься банальным обманом.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Nickolay Ch, Вы писали:
CS>>Извиняюсь но как минимум код должен разрабатываться с применением инженерной совести. CS>>А специфика задачи...
NC>Ну вот опять совесть полезла. Что такое совестьЮ тогда давайте пофлеймим, только уж лучше в Священных войнах. NC>Писать надо так, как целесообразней, сиречь, так, что быстрее привелет нас к результатую. Целесообразность целиком зависит от задачи.
Целесообразность ни при чем. Только на самом верхнем уровне можно писать абы как. Все что находится под ним — вылизывается сообразно глубине.
CC>>AFAIK убиение ненужного происходит не сразу после pointer = NULL; а тогда, когда сработает некая логика в GC...
VD>Убиения не просходит вообще RTFM (извинясь за грубость). VD>Логика ЖЦ ищет живые объекты, а не мертвые.
Я пока работал в основном С++. Можете пояснить работу GC.
Судя по описанию работы ЖЦ мне кажется, что он может затруднять поиск ошибок.
Если в С++ я уничтожил объект, то при при попытке обратиться к ниму снова (на самом деле мне нужен другой объект, но я забыл изменить указатель) я получаю ошибку.
При использовании ЖЦ, как такую ошибку найти? Ведь объект не уничтажается, если есть ссылки на него (ошибочные).
Здравствуйте, astranom, Вы писали:
A>Я пока работал в основном С++.
В этом все и дело. Ты живешь в своем мире предрассудков. Поверь, что есть другие миры где проблем С++ просто не существует.
A>Можете пояснить работу GC.
и вообще поиск по этому форуму и форума по дотнету очень помогает.
A>Судя по описанию работы ЖЦ мне кажется, что он может затруднять поиск ошибок. A>Если в С++ я уничтожил объект, то при при попытке обратиться к ниму снова (на самом деле мне нужен другой объект, но я забыл изменить указатель) я получаю ошибку. A>При использовании ЖЦ, как такую ошибку найти? Ведь объект не уничтажается, если есть ссылки на него (ошибочные).
Эта ошибка не связана с ЖЦ. Эта ошибка связана с тем, что ты используешь не типобезопасный язык программирования и соотвественно не типобезопасный код. В типобезопасном языке подобную ошибку просто невозможно соврешить.
ЖЦ как раз помогает избавиться от таких ошибо. Тебе просто не нужно уничтожать объекты. Ты просто держишь ссылку на объект или забывашь об объекте теряя ссылку. Так что ситуации когда у тебя есть указатель, но он указывает в никуда просто не существует. Языки типа C#, т.е. типобезопасные языки, в безопасном режиме просто не позволяют штатными средствами получить некорректный укзатель.
Собственно в С++ есть следующие способы получить некорректный указатель:
1. Освободить память и использовать указатель который ранее указывал на эту память.
2. Вручную задать неверное значение указателю. Например, в следствии реинтерпретации памяти в погоне за повышением быстродействия.
3. Произвести некорректную арифметическую операцию с указателем. Это можно сделать как напрямую, так и просто ошибившись с индексом массива.
В безопасном режиме C# без применения интеропа такие ошибки невозможны в принципе. Язык и рантайм котролируют все подобные ситуации или вовсе берут их на себя предоставляя в замен более высокоуровневые конструкции.
С++ тоже позволяет уменьшить риски связанные с описанными случаями, но это требует значительного и постоянного напряжения усилий программиста, что особенно в больших коллективах, приводит к снижению скорости разработки и неизбежно ведет к ошибкам. Для уменьшения ошибок связанных с ошибками типизации используются так называемые политики владения. В реальных проектах почти всегда не удается программировать исключительно в рамках выбранных политик владения, так как периодически приходится обращаться к С-АПИ (например, ВыньАПИ) и т.п. К тому же использование разных библиотек приводит к тому, что в одном проекте появляются сразу несколько разных политик владения. Ну, и вообще отслеживание соотвествия политике владения является не простой задачей.
Поиск ошибок связанных с типизацией очень сложен. Отчасти его облегчают средства вроде рантайм-проверок вставляемых компилторами и программ вроде Баундчерека. Но все равно это куда сложнее чем просто не иметь подобных ошибок.
С другой стороны программисту привкшему к тому, что типизацию можно легко обойти порой бывает очень трудно понять и темболее привыкнуть к средам в которых контроль типизации стопроцентный. Хорошм примером тому является наш уважаемый Пвел Дворкин.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>ЖЦ как раз помогает избавиться от таких ошибо. Тебе просто не нужно уничтожать объекты. Ты просто держишь ссылку на объект или забывашь об объекте теряя ссылку. Так что ситуации когда у тебя есть указатель, но он указывает в никуда просто не существует. Языки типа C#, т.е. типобезопасные языки, в безопасном режиме просто не позволяют штатными средствами получить некорректный укзатель.
А вот это как раз полная ж-па. К примеру когда у меня есть сеть и я хочу выкинуть один узел чтобы ее перестроить, то я удаляю его (физически) и перестраиваю сеть, если я ошибся в алгоритме и в элементах остались указатели на этот мертвый узел, то ошибка сразу вылезет . Когда есть GC то мертвые души будут вести себя как живые, и в отладке будет гемор. Можно конечно завести в обьект поле is_dead, но тогда фактически в каждую функцию прийдется ставить проверку if ( is_dead ) {...}, но это имхо попахивает гемором.
VD>Собственно в С++ есть следующие способы получить некорректный указатель: VD>1. Освободить память и использовать указатель который ранее указывал на эту память.
Такая ошибка быстро отлавливается и локализуется, что есть благо. Мертвые души мне в программе не нужны.
VD>2. Вручную задать неверное значение указателю. Например, в следствии реинтерпретации памяти в погоне за повышением быстродействия.
Это очень редкая ситуация, да и ловится легко.
VD>3. Произвести некорректную арифметическую операцию с указателем. Это можно сделать как напрямую, так и просто ошибившись с индексом массива.
В этом случае если буде неккоректный указатель-то это благо. Легко выловишь, гораздо хуже кода ошибся с индексом и вернул корректный (физически), но некорректный алгоритмически указатель.
VD>В безопасном режиме C# без применения интеропа такие ошибки невозможны в принципе. Язык и рантайм котролируют все подобные ситуации или вовсе берут их на себя предоставляя в замен более высокоуровневые конструкции.
Только от алгоритмических это не спасет.
VD>С++ тоже позволяет уменьшить риски связанные с описанными случаями, но это требует значительного и постоянного напряжения усилий программиста
Непряжения не больше чем при обычной отладке. А когда неверный алгоритм дает невалидный указатель, то это даже проще локализуется и исправляется.
VD>Поиск ошибок связанных с типизацией очень сложен. Отчасти его облегчают средства вроде рантайм-проверок вставляемых компилторами и программ вроде Баундчерека. Но все равно это куда сложнее чем просто не иметь подобных ошибок.
Я полным ходом юзаю множественное наследование в С++, никогда не было ошибок связанных с типизацией. Да и откуда им взятся? Юзаем dynamic_cast, а небезопастные привдения используются осознанно да и то в классах хелперах
VD>С другой стороны программисту привкшему к тому, что типизацию можно легко обойти порой бывает очень трудно понять и темболее привыкнуть к средам в которых контроль типизации стопроцентный. Хорошм примером тому является наш уважаемый Пвел Дворкин.
100% контроль так же означает и 100% ограничение. А иногда требуется хак, никуда не денешься.
Посмотрел статьи, но так до конца и не понял. Можете прояснить ситуацию, мне это важно — рассматриваю возможность пересеть на Java.
VD>ЖЦ как раз помогает избавиться от таких ошибо. Тебе просто не нужно уничтожать объекты. Ты просто держишь ссылку на объект или забывашь об объекте теряя ссылку.
VD> Языки типа C#, т.е. типобезопасные языки, в безопасном режиме просто не позволяют штатными средствами получить некорректный укзатель.
Это-то и беспокоит. Если в с++, есть 2-указателя на один объект. Мне надо освободить память и изменить оба указателя. Я забыл изменить один из них, при первом запуске я получаю ошибку -> нахожу -> исправляю
Как это будет работать в С#? Подозреваю, что если я изменю только один указатель, а второй будет указывать на не нужный объект — то GC не удалит его. Программа работать будет — но неправильно. И иди ищи где ты ошибся.
Здравствуйте, astranom, Вы писали:
A>Это-то и беспокоит. Если в с++, есть 2-указателя на один объект. Мне надо освободить память и изменить оба указателя. Я забыл изменить один из них, при первом запуске я получаю ошибку -> нахожу -> исправляю
Это-то так. Плохо только, что это не обязательно произойдет сразу в момент обращения ко второму указателю. Если бы сразу, то на С++ было бы куда приятнее программировать.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
не все так плохо как вы думаете...
CS> // Пеночка №1: чтобы сделать нечто полезное с текстовыми (ASCII) CS> // данными их надо в строку widechar загнать. CS> // Не барское это дело с bytes работать. CS> // Реаллокация буфера №1 — кол-во байт +2N. CS> String header_line = new String( line.get() );
реально это делается только для строк в хэдере, соот-но само тело файла тут обрабатыватся не будет.
новый объект в яве занимает всего несколько байт и выделение их в отличае от malloc() происходит не поиском свободного фрагмента памяти а простой инкрементацией поинтера. если правильно помню то на intel процессрах гарантируется что аллокация занимает не более 8 инструкций процессора против более 50 у malloc()
собственно, релокации не будет т.к. ява переиспользует байтовый массив при аллокации новой строки при условии что размер тотже. собственно, код библиотеки можно слегка подхачить чтобы переиспользовать байтовый массив при substring().
public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;
if (originalValue.length > size) {
v = new char[size];
System.arraycopy(originalValue, original.offset, v, 0, size);
} else {
v = originalValue;
}
this.offset = 0;
this.count = size;
this.value = v;
}
CS> // Пеночка №2: делаем еще одну строку потому как нам надо CS> // регистронезависимый парсинг делать. CS> // Реаллокация буфера №2 — кол-во байт +2N+2N. CS> header_line = header_line.toUpperCase().substring( 0, len — 2 );
реаллокация конечно будет, но, все старые объекты тутже уберутся GC, так что памяти съедать не будут. кстати, деаллокация в жабе тоже практически бесплатная в отличае от C/C++.
CS> // Щаз будем парсить. CS> // Аллокация объекта — сколько ест — то нам не ведомо. CS> StringTokenizer v = new StringTokenizer(header_line, ": ");
всего-то несколько байт на запрос, короче несерьезно.
CS> // Теперича значить толкаем на стек try frame CS> // потому как нужно ловить NumberFormatException в Integer.parseInt CS> try{ CS> v.nextToken(); CS> v.nextToken(" "); CS> ContentLen = Integer.parseInt( v.nextToken() ); CS> }catch(Exception e3){} CS> }
точно не помню, но, где-то читал что в яве эксепшены приводят к оверхеду только если они были реально брошены. но можно просто отлов вынести повыше — так обычно и делают на самом деле.
CS>Итого загрузка 1мб файла вызывает аллокацию 5мб памяти. Вот серверок-то и дохнет.... CS>100 тредов и "шоб ви жили на один page file"
это только проблемы MS Java (которой не обновлялась годами, и которую нормальные люди давно не используют) и того что нет thread pool. те 5мб скорее всего отъедены "про запас" чтобы лишних malloc() не делать, да и все это подберется GC моментально, причем не останавливая другие потоки.
попробуйте на последнюю версию Java5 все перевести — должно быть much better.
CS>Резюме: Наличие высокоуровневых языков с GC и библиотек это конечно здорово, но! CS>результат который вот реально получился тот же примерно что и поймать GPF в С++. CS>Для нахождения где оно и как оно клинит сервер ушел один день — ровно столько сколько CS>бы вызвало устранение GPF.
хотите сказать что после того как вы переписали все это на использование байтовых массивов стало намного лучше? неверю, хотя на MS Java все может быть. лучше бы thread pool сделали, на Java5 перешли и решили не только эту проблему а сразу много всего.
а вообще — я бы конечно написал это несколько подругому — использовал бы NIO и regexpы. или вообще не парился а взял бы одну из десятка реализаций lightweight http.
и вообще про память — на нормальном серваке должно стоять 32гб памяти минимум. стоит это достаточно дешево (на порядок дешевле чем труд програмеров по оптимизации каждого байта). и спокойно будут 1000 потоков с 5мб хипом у каждого жить.
Здравствуйте, Kluev, Вы писали:
K>А вот это как раз полная ж-па. К примеру когда у меня есть сеть и я хочу выкинуть один узел чтобы ее перестроить, то я удаляю его (физически) и перестраиваю сеть, если я ошибся в алгоритме и в элементах остались указатели на этот мертвый узел, то ошибка сразу вылезет .
Откуда сведения? Почему не знал? K> Когда есть GC то мертвые души будут вести себя как живые, и в отладке будет гемор. Можно конечно завести в обьект поле is_dead, но тогда фактически в каждую функцию прийдется ставить проверку if ( is_dead ) {...}, но это имхо попахивает гемором.
Отвечу на вопрос: можно ли организовать утечку в памяти с Net GC. Отвечаю, можно. Но только организовать.
Ты сразу дай знать что тебе нужно. Если тебе нужно удалить объект, то удаляй все ссылки. В случае невыполнения, в чистом С++, ты будешь общаться с памятью как с живым объектом с неопределенным результатом. В Net ты будешь общаться с живым объектом потому что он живой.
Если же ты хочешь пометить объект как удаленный, то помечай как удаленный. Ты как то непонятно перенес проблему предметную на технологический уровень.
VD>>Собственно в С++ есть следующие способы получить некорректный указатель: VD>>1. Освободить память и использовать указатель который ранее указывал на эту память. K>Такая ошибка быстро отлавливается и локализуется, что есть благо. Мертвые души мне в программе не нужны.
Предотвращается, да. А вот ловится — нет. Иногда и профайлер не помогает. Он сам по себе падает от таких программ.
Здравствуйте, astranom, Вы писали:
A>Это-то и беспокоит. Если в с++, есть 2-указателя на один объект. Мне надо освободить память и изменить оба указателя. Я забыл изменить один из них, при первом запуске я получаю ошибку -> нахожу -> исправляю
Попробуй перестать думать о том, что тебе нужно освободить память. Ты же не думашь о том, что тебе нужно дышать? Вот и тут не нужно думать об управлении памятью.
Если у тебя есть двае ссылки на один объект, то и оперируй ими. А память не освобождай.
Не нужно вообще думать блоками памяти. Нужно думать програмными сущьностями. Нужна ссылка — значит она указывает ну нужный объект. Не нужна — значит она должна содержать null.
A>Как это будет работать в С#? Подозреваю, что если я изменю только один указатель, а второй будет указывать на не нужный объект — то GC не удалит его. Программа работать будет — но неправильно. И иди ищи где ты ошибся.
Если ты имешь две постоянные ссылки на один объект (что уже навиват на раздумья) и забыл поправить одну из них, то ты получишь логическую ошибку которая приведет к неверному поведению программы. Найти ошибку можно будет банальным отладчиком. При подобной ошибке в С++ у тебя будет так называемое неопределенное поведение. Это значит, что будет просто принципиально невозможно предсказать, как поведет себя система. Возможно ты получишь вылет. Возможно ты запортишь память отведенную другому объекту. Возможно все вообще будет работать как надо до определенного времени. Причем с большой долей веорятности эта ошибка приведет к тому, что реальная ошибка будет проявляться совершенно в другом месте. И скорее всего совершенно непонятным образом. Такие ошибки даже при наличии специальных средств искать очень не просто. Они зачастую порождают ошибки вторго и третьего порядка (когда некоторое действи не приводит сразу к вылету, а только портит память в днругом месте, а вылет случается в совершенно не предсказуемом месте.
ЗЫ
Мужики, поймите (и не обижайтесь). Вы живете в своем мире. Ваш мозг думает только одним единственным образом. Я уже который раз пытаюсь объяснить вам казалось бы совсем примитивные вещи, но вы просто не можете переключиться со своей точки зрения.
Очень советую вам познакомиться с языками и средами в которых реализовано автоматическое управление памятью. Это, кстати, не только дотнет или Ява. Сюда отноятся почти все скриптовые языки (напрмер Руби и Питон). Уверяю вас, что как только вы познакомитесь с ними по ближе все ваши вопросы отпадут сами собой.
Вы даже не представляете насколько проще становится отладка когда из списка возможных ошибок исключаются ошибки связанные с типами.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Очень советую вам познакомиться с языками и средами в которых реализовано автоматическое управление памятью. Это, кстати, не только дотнет или Ява. Сюда отноятся почти все скриптовые языки (напрмер Руби и Питон). Уверяю вас, что как только вы познакомитесь с ними по ближе все ваши вопросы отпадут сами собой.
VD>Вы даже не представляете насколько проще становится отладка когда из списка возможных ошибок исключаются ошибки связанные с типами.
Вот чесно тебе скажу Влад. Пользуюсь Ruby, нравится мне, что не нужно о памяти думать. Не нравится, что a = b на самом деле означает копирование ссылок, а не объектов. Это приводит к труднообнаруживаемым проблемам. А уж забыть какую-то ссылку в nil установить -- так это вообще раз плюнуть. И будет затем чего-нибудь где-нибудь болтаться. Хуже всего, если с неожиданными проявлениями (вроде как изменяем один объект, а изменения еще где-то оказываются, потому что ссылки-то на один объект).
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, n0name2, Вы писали:
N>новый объект в яве занимает всего несколько байт и выделение их в отличае от malloc() происходит не поиском свободного фрагмента памяти а простой инкрементацией поинтера. если правильно помню то на intel процессрах гарантируется что аллокация занимает не более 8 инструкций процессора против более 50 у malloc()
N>собственно, релокации не будет т.к. ява переиспользует байтовый массив при аллокации новой строки при условии что размер тотже. собственно, код библиотеки можно слегка подхачить чтобы переиспользовать байтовый массив при substring().
N>реаллокация конечно будет, но, все старые объекты тутже уберутся GC, так что памяти съедать не будут. кстати, деаллокация в жабе тоже практически бесплатная в отличае от C/C++.
N>точно не помню, но, где-то читал что в яве эксепшены приводят к оверхеду только если они были реально брошены. но можно просто отлов вынести повыше — так обычно и делают на самом деле.
N>это только проблемы MS Java (которой не обновлялась годами, и которую нормальные люди давно не используют) и того что нет thread pool. те 5мб скорее всего отъедены "про запас" чтобы лишних malloc() не делать, да и все это подберется GC моментально, причем не останавливая другие потоки.
N>попробуйте на последнюю версию Java5 все перевести — должно быть much better.
N>хотите сказать что после того как вы переписали все это на использование байтовых массивов стало намного лучше? неверю, хотя на MS Java все может быть. лучше бы thread pool сделали, на Java5 перешли и решили не только эту проблему а сразу много всего.
N>а вообще — я бы конечно написал это несколько подругому — использовал бы NIO и regexpы. или вообще не парился а взял бы одну из десятка реализаций lightweight http.
N>и вообще про память — на нормальном серваке должно стоять 32гб памяти минимум. стоит это достаточно дешево (на порядок дешевле чем труд програмеров по оптимизации каждого байта). и спокойно будут 1000 потоков с 5мб хипом у каждого жить.
не я угараю. я конечно понимаю, это ваше первое сообщение и все такое....
Вы б поискали по форуму про MS VM как она попрежнему всех делает... ох, ну ладно. и 32гб..
Здравствуйте, vladserge, Вы писали:
V>Вы б поискали по форуму про MS VM как она попрежнему всех делает...
нюню... кого она делает? это вы про отрисовку строк чтоли? кроме как быстро рисовать MS VM ниче не может, вообще ничего. если надо че-то быстро отрисовывать на Java5 юзайте SWT и будет вам щастье.
в любом коректном микробенчмарке не юзающем GDI MS VM сольет по полной.
вообще судя по всему вы явой интересуетесь раз в полгода а не юзаете ее сервер сайдный вариант каждый день.
Здравствуйте, eao197, Вы писали:
E>Вот чесно тебе скажу Влад. Пользуюсь Ruby, нравится мне, что не нужно о памяти думать. Не нравится, что a = b на самом деле означает копирование ссылок, а не объектов. Это приводит к труднообнаруживаемым проблемам. А уж забыть какую-то ссылку в nil установить -- так это вообще раз плюнуть. И будет затем чего-нибудь где-нибудь болтаться. Хуже всего, если с неожиданными проявлениями (вроде как изменяем один объект, а изменения еще где-то оказываются, потому что ссылки-то на один объект).
Про Руби не скажу, а на C# мне практически не приходится вручную ссылки в null устанавливать. Как-то все и без того получается. К тому же Шарп позволяет довольно много всего. Так есть вэлью-типы которые копируются по содержимому, и есть возможность воспользоваться привдением типов с копированием.
В общем, проблем с копированием ссылок я как-то даже в самом начале не почувствовал.
... << RSDN@Home 1.2.0 alpha rev. 620>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, GlebZ, Вы писали:
K>>А вот это как раз полная ж-па. К примеру когда у меня есть сеть и я хочу выкинуть один узел чтобы ее перестроить, то я удаляю его (физически) и перестраиваю сеть, если я ошибся в алгоритме и в элементах остались указатели на этот мертвый узел, то ошибка сразу вылезет . GZ>Откуда сведения? Почему не знал? K>> Когда есть GC то мертвые души будут вести себя как живые, и в отладке будет гемор. Можно конечно завести в обьект поле is_dead, но тогда фактически в каждую функцию прийдется ставить проверку if ( is_dead ) {...}, но это имхо попахивает гемором. GZ>Отвечу на вопрос: можно ли организовать утечку в памяти с Net GC. Отвечаю, можно. Но только организовать. GZ>Ты сразу дай знать что тебе нужно. Если тебе нужно удалить объект, то удаляй все ссылки. В случае невыполнения, в чистом С++, ты будешь общаться с памятью как с живым объектом с неопределенным результатом. В Net ты будешь общаться с живым объектом потому что он живой. GZ>Если же ты хочешь пометить объект как удаленный, то помечай как удаленный. Ты как то непонятно перенес проблему предметную на технологический уровень.
Ты все не понял. Ситуация состоит в том, что в процессе программирования алгоритмических ошибок не избежать. К примеру я хочу удалить обьект, естественно я должен обнулить все ссылки на него. Если в результате алгоритмической ошибки программера обнулены не все ссылки то ситуация будет следущей:
В С++:
Я удалю обьект делитом (физически), а когда программа пойдет по невалидной ссылке то как правило будет runtime error. В деббагере это место сразу локализуется и дальше можно определить причину, почему осталась невалидная ссылка и исправить алгоритм.
В С# если я по ошибке не обнулю все ссылки, то заведется мертвая душа. Т.е. алгоритмически обьект должен быть мертвым, а физически он жив. При обращении по этим ссылкам рантайм error не возникнет и программа будет работать дальше только неправильно(алгоритмически). В результате ошибку будет не так то просто найти т.к. она может проявится только в выходных данных или еще бог знает на каком этапе работы. Тогда найти место откуда ноги ростут будет достаточно проблематично.
Здравствуйте, Kluev, Вы писали:
K>Ты все не понял. Ситуация состоит в том, что в процессе программирования алгоритмических ошибок не избежать.
Не избежать. Но их меньше чем элементарных ошибок, и они чаще сразу тестируются при разработке. K>В С++: K>Я удалю обьект делитом (физически), а когда программа пойдет по невалидной ссылке то как правило будет runtime error. В деббагере это место сразу локализуется и дальше можно определить причину, почему осталась невалидная ссылка и исправить алгоритм.
Как правило? О, нет. Это адская ошибка. Обычно она появляется не в лишней ссылке, а в лишнем(преждевременном) делете. Пока это пространство под убитым объектом никто не заполнил, ее можно считать живой и работающей и никто этого не замечает. Проявляется вообще сказочно. Может проявиться например, в Debug все работает, а под Release ни фига. Или еще хуже, все работает, дает полезный результат, но тут тронул пупок и вся задница отвалилась. Притом долго смотришь на код который только что правил. Начинаешь верить в потусторонние силы, и что у программы есть бог который тебя проклял. Теряешь веру в собственную логику. Рука тянется к бубну. Например, каким образом вставка тупого if может выдавать access violation. Мысль заглянуть в код, который уже два года нормально работает отгоняется как неправдоподобная. А вот когда уже взглянешь туда, тоже начинаешь удивляться. Каким образом такое, мало того что работало два года, но еще умудрялось возвращать правильные результаты. Система искуственного интелекта в действии. Вобщем, хуже такой ошибки быть ничего не может.
). E>Но только, если ошибка есть, то она обязательно проявится. А вот со сборщиком мусора -- может вообще не проявиться.
если никак не проявляется, значит ее нет вообще. если вдруг память стала отъедатся и не возвращатся то если большое кол-во инструментов анализирующих heap, дающих stack trace того места где была аллокация и т.д. но это бывает достаточно редко и никакой мистики вроде неопределенного поведения не вызывает.
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, Kluev, Вы писали:
K>>Ты все не понял. Ситуация состоит в том, что в процессе программирования алгоритмических ошибок не избежать. GZ>Не избежать. Но их меньше чем элементарных ошибок, и они чаще сразу тестируются при разработке. K>>В С++: K>>Я удалю обьект делитом (физически), а когда программа пойдет по невалидной ссылке то как правило будет runtime error. В деббагере это место сразу локализуется и дальше можно определить причину, почему осталась невалидная ссылка и исправить алгоритм. GZ>Как правило? О, нет. Это адская ошибка. Обычно она появляется не в лишней ссылке, а в лишнем(преждевременном) делете. Пока это пространство под убитым объектом никто не заполнил, ее можно считать живой и работающей и никто этого не замечает. GZ>С уважением, Gleb.
Ну так в C# еще хуже. В С++ это рано или поздно всплывет с грохотом. В шарпе все будет долго и упорно работать, только неправильно.
). E>Но только, если ошибка есть, то она обязательно проявится.
Нет. В том-то и дело-нет. В этом как раз и вся соль. Я согласен чтобы у меня были утечки памяти. Я вполне понимаю как они проявляются и что нужно делать. Они заметны. В этом же случае все более похабно чем может быть. Несколько раз встречал такие ошибки, хуже их не найдешь.
E>А вот со сборщиком мусора -- может вообще не проявиться.
С одной стороны — может и не проявиться. Просто памяти достаточно и никто не замечает что она увеличивается. Нехорошо и да ладно. С другой стороны, если у тебя память хорошо утекает, то будь ты в С++, или с GC в C# у тебя есть показания для профайлера.
Здравствуйте, Kluev, Вы писали:
K>Ну так в C# еще хуже. В С++ это рано или поздно всплывет с грохотом. В шарпе все будет долго и упорно работать, только неправильно. Re[17]: Смотрел на Java код. ...много думал.
).
> E> Но только, если ошибка есть, то она обязательно проявится.
> Нет. В том-то и дело-нет. В этом как раз и вся соль. Я согласен чтобы у меня были утечки памяти. Я вполне понимаю как они проявляются и что нужно делать. Они заметны. В этом же случае все более похабно чем может быть.
Ты говоришь совершенно о другой проблеме. Утечки памяти здесь ни при чем совершенно. Речь идет о том, что где-то осталась ссылка на старый объект, в то время как в других местах уже используется новый. Это логическая ошибка, которую порой очень тяжело отследить. В случае, если старый объект был бы удален, шансы на ее обнаружение были бы существенно выше, т.к. в тех местах, где он бы продолжал использоваться программа с хорошей вероятностью "падала".
Posted via RSDN NNTP Server 2.0 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ты говоришь совершенно о другой проблеме. Утечки памяти здесь ни при чем совершенно.
Конечно нет. Я упомянул про утечки поскольку они обычно используются как аргумент в managed vs unmanaged. ПК>Речь идет о том, что где-то осталась ссылка на старый объект, в то время как в других местах уже используется новый. Это логическая ошибка, которую порой очень тяжело отследить.
Дело в том, что я делал достаточно сложные структуры со множественными связями и на Net и на C# и на Паскале. И знаешь, я не помню таких ошибок. К алгоритмам и структурам как то всегда более акуратно подходишь. Их всегда не грех продумать конкретно. А вот ошибки по невнимательности на каждом шагу.
В Net существуют некоторые возможности для утечки иногда проскакивают. Но это ошибки данного плана. В основном это когда объект подписывают к какому-то событию время жизни которого достаточно большое, и забывают отписываться. Мне одного раза хватило, и я стал более акуратно относиться к отписке от событий. В остальном, о том чтобы обнулять ссылки я давно уже не задумываюсь. Если подобного не вписано в некоторый алгоритм. ПК>В случае, если старый объект был бы удален, шансы на ее обнаружение были бы существенно выше, т.к. в тех местах, где он бы продолжал использоваться программа с хорошей вероятностью "падала".
Что такое хорошая вероятность? В какой момент она создается?
Че-то я вас не пойму, господа. Вы никогда не встречали в С++ Access Violation который появлялся ниоткуда после перекомпиляции? Или Unit Test которые работают правильно 9 раз из 10? Не верю....
GZ>Что такое хорошая вероятность? В какой момент она создается? GZ>Че-то я вас не пойму, господа. Вы никогда не встречали в С++ Access Violation который появлялся ниоткуда после перекомпиляции? Или Unit Test которые работают правильно 9 раз из 10? Не верю....
Хорошая или плохая, но без GС она есть.
Если у вас программа 9 из 10 раз работает без Access Violation, то она эти 9 раз работет неверно — адрессуется не к тому объекту и вы этого не замечаете.
C GC она все десять раз сработает без ошибок и все десеть неверно, теперь ошибку сложнее обнаружить и кроме того сразу нет ясности из-за чего она: причин для неправильной работы море и неправильный указатель лишь одна из них.(Access Violation — прямо указывает на необходимость проверить указатели, и нередко сразу указывает на не исправленную ссылку)
ИМХО. GC нужен. Но и комманда delete, лишней не будет. Если бы можно было бы для объектов принудительно задавать delete, и если бы GC находил ещё ссылки на этот объект и тогда выдовал exception — это бы было идельно.
ЗЫ: Я тебя породил, я тебя и убью! — такое часто нужно, и иметь хоть какую-нибудь возможность конролировать процесс это не так уж и плохо.
Здравствуйте, n0name2, Вы писали:
N>Здравствуйте, vladserge, Вы писали:
V>>Вы б поискали по форуму про MS VM как она попрежнему всех делает...
N>нюню... кого она делает? это вы про отрисовку строк чтоли? кроме как быстро рисовать MS VM ниче не может, вообще ничего. если надо че-то быстро отрисовывать на Java5 юзайте SWT и будет вам щастье.
N>в любом коректном микробенчмарке не юзающем GDI MS VM сольет по полной.
N>вообще судя по всему вы явой интересуетесь раз в полгода а не юзаете ее сервер сайдный вариант каждый день.
"микробенчмарк" это такой бенчмарк который в общем и целом плохой поэтому мы переходим к замерам
частных ситуаций? Я правильно понял?
Здравствуйте, astranom, Вы писали:
A>Хорошая или плохая, но без GС она есть. A>Если у вас программа 9 из 10 раз работает без Access Violation, то она эти 9 раз работет неверно — адрессуется не к тому объекту и вы этого не замечаете.
+1 Только небольшая поправка. К области памяти которая может еще содержать данные от убитого объекта.
A>C GC она все десять раз сработает без ошибок и все десеть неверно, теперь ошибку сложнее обнаружить и кроме того сразу нет ясности из-за чего она: причин для неправильной работы море и неправильный указатель лишь одна из них.(Access Violation — прямо указывает на необходимость проверить указатели, и нередко сразу указывает на не исправленную ссылку)
Почему нет ясности? У тебя есть гарантия что они будут работать либо верно, либо неверно. Если неверно, то ищи ошибку.
A>ИМХО. GC нужен. Но и комманда delete, лишней не будет. Если бы можно было бы для объектов принудительно задавать delete, и если бы GC находил ещё ссылки на этот объект и тогда выдовал exception — это бы было идельно.
Есть стандартная фича. Если у объекта прошел Dispose(аналог детерменированного деструктора) то на все методы которые не могут быть вызваны ты можешь бросать ObjectDisposedException. Это более локализуемое чем Access Violation, который к тому-же имеет тенденцию вызываться в nt.dll.
A>ЗЫ: Я тебя породил, я тебя и убью! — такое часто нужно, и иметь хоть какую-нибудь возможность конролировать процесс это не так уж и плохо.
Не нужно. Практически никогда не нужно. Это С++ в деструкторе нужно удалить все зависимые объекты. С GC все зависимые объекты становятся мертвыми автоматически. После одного-двух больших проектов начинаешь понимать что деструкторы без unmanaged ресурсов практически не нужны. Без них спокойно и нормально живется и о них не нужно задумываться.
То что описывал Kluev штука весьма специфичная. Практически всегда сетевые структуры можно выразить в виде деревьев. В этом случае, если у тебя при стирании ссылки теряется вся ветка. Чаще такие структуры отображаются вручную через массивы чтобы не лазить на тормозное выделение памяти. А там уже другие законы. Насколько я понял и у него кастомный менеджер памяти.
Здравствуйте, c-smile, Вы писали:
N>>в любом коректном микробенчмарке не юзающем GDI MS VM сольет по полной.
CS>"микробенчмарк" это такой бенчмарк который в общем и целом плохой поэтому мы переходим к замерам CS>частных ситуаций? Я правильно понял?
ну народу (см. скажем топик про "сравнение про-ти Java 1.5 и .NET 2.0" в священных войнах) как правило лень качать/запускать/анализировать нормальные бенчмарки JVM, скажем, SPECjbb2000. так что лобают что в голову взбредет, то сортировку пузырьком, то аллокацию объектов, то перемножение матриц.
в общем, в "микробенчмарках" нет ничего плохого т.к. они более понятны народу и как следствие им больше доверяют. но от MSVM на сервере постарайтесь избавится ASAP...
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Ты говоришь совершенно о другой проблеме. Утечки памяти здесь ни при чем совершенно. Речь идет о том, что где-то осталась ссылка на старый объект, в то время как в других местах уже используется новый. Это логическая ошибка, которую порой очень тяжело отследить. В случае, если старый объект был бы удален, шансы на ее обнаружение были бы существенно выше, т.к. в тех местах, где он бы продолжал использоваться программа с хорошей вероятностью "падала".
можно пример (на неком псевдокоде) того что вы имеете в виду? никак немогу понять как то о чем вы говорите может быть возможным.