Почему преждевременная оптимизация - корень всех зол?
От: Аноним  
Дата: 18.08.08 14:43
Оценка: -2 :)
Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?

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

19.08.08 13:35: Перенесено из 'C/C++'
Re: Почему преждевременная оптимизация - корень всех зол?
От: bexab  
Дата: 18.08.08 14:56
Оценка: 27 (7) +6 -1
Здравствуйте, Аноним, Вы писали:

А>Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?


Наверное в том, что корректно работающую программу проще переделать в быструю, чем быструю в корректно работающую.
Re: Почему преждевременная оптимизация - корень всех зол?
От: Аноним  
Дата: 18.08.08 14:58
Оценка: 20 (3) +4 :)
А>И реальная ситуация — есть какой-то проект который должен делать что-то. Сейчас сделана четверть нужной функциональности, но уже заметгны тормоза. Судя по этой фразе — на оптимизацию пока надо забить, но ведь тогда может оказаться, что в конце будет такая ж..а, что на это никто сомтреть не станет
Во первых зло это преждевременная низкоуровневая оптимизация — ручная раскрутка циклов, асмовые вставки, кэширования всяческих результатов везде подряд, кастомные менеджеры памяти, шаманская рассовывание данных и хитрых примитивов синхронизации etc.
Есть еще оптимизация высокоуровневая — архитектурная и алгоритмическая.
Так вот низкоеровневая оптимизация очень затрудняет алгоритмическую, которая в свою очередь часто затрудняет архитектурную. В то время как в большинстве случаев выигрышь в производительности распределяется в обратном порядке.
Потому вначале следует написать и заимплементить эффеективную архитектуру. Потом на этапе альфы пройтись профайлером и оптимизировать алгоритмы (поменять сортировки пузырьком на qsort, поиски на мапы, распараллелить долгие вычисления на несколько ядер etc.
И только потом, если маркетинг еще попросит чтоб было быстрее браться за профайлер еше раз, и заменять где требуется стандартные мапы на самописные, написать свой lookaside аллокатор для кучи объектов если профайлер показал >5% потерь на дефолтовом аллокаторе etc.
Re: Почему преждевременная оптимизация - корень всех зол?
От: Sergey Россия  
Дата: 18.08.08 15:02
Оценка: 1 (1) +2
> Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?

Потому что можно угрохать просто так кучу сил и времени. Например, оптимизированный (преждевременно) кусок кода, после прототипирования будет решено выкинуть. Или окажется, что тормоза в этом куске кода — пустяки по сравнению с тормозами в другом куске и оптимизировать надо было не здесь.

> И реальная ситуация — есть какой-то проект который должен делать что-то. Сейчас сделана четверть нужной функциональности, но уже заметгны тормоза.


Пессимизация (т.е., написание кода без оглядки на его производительность) — еще большее зло.

> Судя по этой фразе — на оптимизацию пока надо забить, но ведь тогда может оказаться, что в конце будет такая ж..а, что на это никто сомтреть не станет


Вот именно на оптимизацию — да, пока забить. А вот заранее оценить потенциал быстродействия не помешает.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Re[2]: Почему преждевременная оптимизация - корень всех зол?
От: vayerx  
Дата: 18.08.08 15:03
Оценка: 29 (3) +1
Здравствуйте, bexab, Вы писали:

B>Наверное в том, что корректно работающую программу проще переделать в быструю, чем быструю в корректно работающую.

Согласен. Оптимизировать/рефакторить программу многократно проще, когда она полностью работает и ее код покрыт тестами.
Re: Почему преждевременная оптимизация - корень всех зол?
От: Roman Odaisky Украина  
Дата: 18.08.08 16:24
Оценка: 1 (1) :)))
Здравствуйте, Аноним, Вы писали:

А>Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?


Такой, что оптимизировать на уровне алгоритмов и структур данных нужно сразу.

А заменять boost::lexical_cast на велосипед не нужно, потому что это всегда можно сделать потом — и только в том месте, где по-настоящему тормозит.

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


Вот тебе реальная ситуация:
началось этим — http://rsdn.ru/forum/message/2229305.1.aspx
Автор: Ubivetz
Дата: 23.11.06
,
закончилось этим — http://rsdn.ru/forum/message/2231390.1.aspx
Автор: Ubivetz
Дата: 24.11.06
.
До последнего не верил в пирамиду Лебедева.
Re: Почему преждевременная оптимизация - корень всех зол?
От: drol  
Дата: 18.08.08 18:34
Оценка: 6 (3)
Здравствуйте, Аноним, Вы писали:

А>Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?


В приведённой Вами — не знаю какой. Оригинал же выглядит так:

There is no doubt that the grail of efficiency leads to abuse. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.
Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified.


И, на мой взгляд, это практически полный ответ на Ваш вопрос...
*Читайте первоисточники — они рулез
Re: Почему преждевременная оптимизация - корень всех зол?
От: rg45 СССР  
Дата: 18.08.08 20:21
Оценка: 13 (2) +4
Здравствуйте, Аноним, Вы писали:

А>Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?


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


Как известно, на данную проблему можно взглянуть с двух противоположных точек зрения: с одной точки зрения преждевременная оптимизация — корень всех зол, с другой — преждевременная пессимизация. Как обычно бывает в жизни, истина находится где-то посредине, и важно уметь этой золотой середины придерживаться. Я придерживаюсь такого критерия: если в процессе разработки, особенно на ранних ее стадиях, в жертву оптимизации приносится качество архитектуры, понятность и читабельность кода, его тестопригодность и рефакторопригодность, если по соображениям оптимизации в программе появляются хитросплетения зависимостей и велосипеды с костылями, то это и есть преждевременная оптимизация и, соответственно, зло. Оптимизация же, полученная в результате построения хорошей архитектуры, применения прогрессивных алгоритмических решений, а также элементарная опрятность и культура кодирования, которая при любой архитектуре дает улучшение быстродействия, может только приветствоваться.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Почему преждевременная оптимизация - корень всех зол?
От: Erop Россия  
Дата: 18.08.08 20:22
Оценка: +1 -1
Здравствуйте, Аноним, Вы писали:

А>...(поменять сортировки пузырьком на qsort...


IMHO от сортировки пузырьком следует отказаться раз и навсегда...
Вообще, можно завсети правило, что использование квадратичных и более медленных алгоритмов требует обоснования...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Почему преждевременная оптимизация - корень всех зол?
От: skeptik_  
Дата: 18.08.08 22:23
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Аноним, Вы писали:


А>>...(поменять сортировки пузырьком на qsort...


E>IMHO от сортировки пузырьком следует отказаться раз и навсегда...

E>Вообще, можно завсети правило, что использование квадратичных и более медленных алгоритмов требует обоснования...
При работе с графами и кубы встречаются
Re[4]: Почему преждевременная оптимизация - корень всех зол?
От: Erop Россия  
Дата: 19.08.08 05:05
Оценка:
Здравствуйте, skeptik_, Вы писали:

E>>IMHO от сортировки пузырьком следует отказаться раз и навсегда...

E>>Вообще, можно завсети правило, что использование квадратичных и более медленных алгоритмов требует обоснования...
_>При работе с графами и кубы встречаются
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Почему преждевременная оптимизация - корень всех зол?
От: _FRED_ Черногория
Дата: 19.08.08 05:30
Оценка: +2
Здравствуйте, Erop, Вы писали:

А>>...(поменять сортировки пузырьком на qsort...

E>IMHO от сортировки пузырьком следует отказаться раз и навсегда...
E>Вообще, можно завсети правило, что использование квадратичных и более медленных алгоритмов требует обоснования...

Не раз видел, когда при необходимости всего-то найти пересечение двух множеств (заданных массивом\IList\IEnumerable, не важно) делался foreach по одному списку, а внутри него — по другому И на все пожелания сделать правильно отвечалось, что "нечего преждевременной оптимизацией заниматься", тогда как дело попросту в незнании более эффективных алгоритмов (что, к счастью, поправимо) и нежелании их узнать (с чем уже ничего не поделать)
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Почему преждевременная оптимизация - корень всех зол?
От: Erop Россия  
Дата: 19.08.08 05:34
Оценка: :)
Здравствуйте, _FRED_, Вы писали:

_FR>Не раз видел, когда при необходимости всего-то найти пересечение двух множеств (заданных массивом\IList\IEnumerable, не важно) делался foreach по одному списку, а внутри него — по другому И на все пожелания сделать правильно отвечалось, что "нечего преждевременной оптимизацией заниматься", тогда как дело попросту в незнании более эффективных алгоритмов (что, к счастью, поправимо) и нежелании их узнать (с чем уже ничего не поделать)


Ну, например, если завести какую-нибудь бюрократическую процедуру обоснования использования квадратичных и более медленных алгоритмов (например требовать писать докладную аписку начальнику с обоснованием), то программистам будет проще использовать правильные алгоритмы, и код улучшится практически забесплатно...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Почему преждевременная оптимизация - корень всех зол?
От: MasterZiv СССР  
Дата: 19.08.08 06:22
Оценка: +2 :)
Аноним 791 wrote:

> Ведь оптимизация может привести к переписыванию много чего и даже в

> рамках одного модуля или класса. Какой смысл в этой фразе?

Очень хорошая тема, интересная. Только вот почему я её читаю в С++ ?
Очень странно.
Posted via RSDN NNTP Server 2.1 beta
Re[5]: Почему преждевременная оптимизация - корень всех зол?
От: MasterZiv СССР  
Дата: 19.08.08 06:25
Оценка: 1 (1) +2 :)
Erop wrote:

> Ну, например, если завести какую-нибудь бюрократическую процедуру

> обоснования использования квадратичных и более медленных алгоритмов
> (например требовать писать докладную аписку начальнику с обоснованием),
> то программистам будет проще использовать правильные алгоритмы, и код
> улучшится практически забесплатно...

Для начала нужно написать другую бюрократическую процедуру — опознания
сложности алгоритма программистом.
Posted via RSDN NNTP Server 2.1 beta
Re[6]: Почему преждевременная оптимизация - корень всех зол?
От: Erop Россия  
Дата: 19.08.08 07:42
Оценка: :)
Здравствуйте, MasterZiv, Вы писали:

MZ>Для начала нужно написать другую бюрократическую процедуру — опознания

MZ>сложности алгоритма программистом.


Эта процедура давно изрбретена

1) Пункт про согласование вносим в долж. инструкцию.
2) За нарушение должностной инструкции -- штрафуем.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Почему преждевременная оптимизация - корень всех зол?
От: jazzer Россия Skype: enerjazzer
Дата: 19.08.08 09:39
Оценка: 13 (1) +3
Здравствуйте, Аноним, Вы писали:

А>Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?


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


если тормоза уже заметны, то, очевидно, это уже не преждевременная оптимизация
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Почему преждевременная оптимизация - корень всех зол?
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.08.08 10:23
Оценка: 1 (1) +9 -3
Здравствуйте, <Аноним>, Вы писали:

А>И реальная ситуация — есть какой-то проект который должен делать что-то. Сейчас сделана четверть нужной функциональности, но уже заметгны тормоза.

А> Судя по этой фразе — на оптимизацию пока надо забить, но ведь тогда может оказаться, что в конце будет такая ж..а, что на это никто сомтреть не станет
Судя по этой фразе забивать нужно на преждевременную оптимизацию. Если у вас уже сейчас видны тормоза, то это повод задуматься над их устранением. Если, конечно, есть уверенность, что эти тормоза — реальные, а не вызваны тем, что еще три четверти кода просто не написаны, а вместо них работают тормозные заглушки.
Преждевременная оптимизация — это, например, замена всех пузырьков на qsort без оглядки на реальные показания профайлера.
Вон уже народ понабежал с запретами на квадратичные алгоритмы. Бред ведь полнейший. Известна байка про то, как чувак переписал пузырек на квиксорт и получил 1% ускорения. А надо было перейти от строковых сравнений к сравнению perfect hash-ей, что дало рост перформанса в разы. Что характерно, такая замена дала бы почти такой же рост и для пузырька. Вот почему преждевременная оптимизация плоха.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Почему преждевременная оптимизация - корень всех зол?
От: minorlogic Украина  
Дата: 19.08.08 10:35
Оценка: +2 :)
Здравствуйте, Sinclair, Вы писали:

S>Преждевременная оптимизация — это, например, замена всех пузырьков на qsort без оглядки на реальные показания профайлера.

S>Вон уже народ понабежал с запретами на квадратичные алгоритмы. Бред ведь полнейший. Известна байка про то, как чувак переписал пузырек на квиксорт и получил 1% ускорения. А надо было перейти от строковых сравнений к сравнению perfect hash-ей, что дало рост перформанса в разы. Что характерно, такая замена дала бы почти такой же рост и для пузырька. Вот почему преждевременная оптимизация плоха.

Сортировку логично использовать стандартную , и уж точно в коде не должна появляться пузырьковая по определению.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: Почему преждевременная оптимизация - корень всех зол?
От: Erop Россия  
Дата: 19.08.08 10:54
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Вон уже народ понабежал с запретами на квадратичные алгоритмы. Бред ведь полнейший. Известна байка про то, как чувак переписал пузырек на квиксорт и получил 1% ускорения. А надо было перейти от строковых сравнений к сравнению perfect hash-ей, что дало рост перформанса в разы. Что характерно, такая замена дала бы почти такой же рост и для пузырька. Вот почему преждевременная оптимизация плоха.


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


1) За слово "бред", IMHO, можно и извиниться
2) Лично я предлагал не запрет на квадратичные алгоритмы, а требования обоснования их использования...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Почему преждевременная оптимизация - корень всех зол?
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.08.08 10:57
Оценка: 1 (1) +4 -1
Здравствуйте, minorlogic, Вы писали:

M>Сортировку логично использовать стандартную , и уж точно в коде не должна появляться пузырьковая по определению.

Ух какая уверенность в себе! Мне б такую.
По делу: пузырек в случае почти отсортированных данных рвет qsort по производительности. Учите матчасть.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: Почему преждевременная оптимизация - корень всех зол?
От: Кэр  
Дата: 19.08.08 13:59
Оценка: 1 (1)
Здравствуйте, Erop, Вы писали:

А>>...(поменять сортировки пузырьком на qsort...

E>IMHO от сортировки пузырьком следует отказаться раз и навсегда...

Ух, "какие мы нежные и суровые". А ничего что quick sort — это квардратичный алгоритм? У него on average NlogN
Re[2]: Почему преждевременная оптимизация - корень всех зол?
От: Кэр  
Дата: 19.08.08 14:09
Оценка:
Здравствуйте, jazzer, Вы писали:

J>если тормоза уже заметны, то, очевидно, это уже не преждевременная оптимизация


Осталось ответить на вопрос — как они заметны? "На глазок"? Многоопытным взглядом ищем вложенные циклы и начинаем костерить ламеров писавших код за квардатичные алгоритмы? Если так — это и есть преждевременная оптимизация.
Браться что-то оптимизировать стоит только после того, как:
1. Был запущен профайлер, причем очень желательны данные приблеженные к реальным.
2. Были найдены проблемные места.

"На глазок" видны только самые очевидные места, те самые 3% о которых говорится в оригинальной цитате. Их можно исправить сразу. Но опять же ключевое слово "можно". Если уж браться за оптимизацию серьезно — то и очевидные места тоже надо профайлить. Особенно в сравнении с другими проблемными местами и опять же желательно на реальных данных.
Re: Почему преждевременная оптимизация - корень всех зол?
От: Кэр  
Дата: 19.08.08 14:15
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?


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


Можно поучиться на чужих ошибках. Тут даже выводы подготовлены из ошибок, осталось прочитать и подумать:
http://www.flounder.com/optimization.htm
Re[4]: Почему преждевременная оптимизация - корень всех зол?
От: skeptik_  
Дата: 19.08.08 14:19
Оценка: :)
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, minorlogic, Вы писали:


M>>Сортировку логично использовать стандартную , и уж точно в коде не должна появляться пузырьковая по определению.

S>Ух какая уверенность в себе! Мне б такую.
S>По делу: пузырек в случае почти отсортированных данных рвет qsort по производительности. Учите матчасть.

Хорошо, давайте учить матчасть:
#define _SECURE_SCL 0
#define _SECURE_SCL_THROWS 0

#include <iostream>
#include <algorithm>
#include <vector>
#include <iomanip>
using namespace std;

#include <boost/timer.hpp>
using boost::timer;

template< typename Func, typename Cont >
double sort_timing( Cont c, Func f )
{
    timer t1;
    f( c.begin(), c.end() );
    return t1.elapsed();
}

#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/random/mersenne_twister.hpp>

template< typename Dist, typename Cont, typename Arg >
Cont generate_random( typename Cont::size_type size, Arg arg1, Arg arg2 )
{
    static boost::mt11213b gen( std::time(0) );
    boost::variate_generator< boost::mt11213b&, Dist > rand_gen( gen, Dist( arg1, arg2 ) );

    Cont c;
    generate_n( back_inserter( c ), size, rand_gen );
    return c;
}

template< typename Cont >
Cont& make_almost_sorted( Cont& cont, double swap_percent )
{
    sort( cont.begin(), cont.end() );
    using namespace boost;
    static mt11213b gen( std::time(0) );
    variate_generator< mt11213b&, uniform_int<> > rand_gen( gen, uniform_int<>( 0, cont.size() - 1 ) );
    for ( int i = 0, N = swap_percent * cont.size() / 2; i < N; ++i )
        swap( cont[ rand_gen() ], cont[ rand_gen() ] );
    return cont;
}

template<class Iterator>
void insertion_sort( Iterator First, Iterator Last )
{
    for( Iterator i = First; i < Last; ++i )
        for( Iterator j = i; First < j && *j < *(j - 1); --j )
            std::iter_swap( (j - 1), j );
}

template<class Iterator>
void bubble_sort( Iterator First, Iterator Last )
{
    while( First < --Last )
        for( Iterator i = First; i < Last; ++i )
            if ( *i > *(i + 1) )
                std::iter_swap( (i + 1), i );
}

template<class Iterator>
void selection_sort( Iterator First, Iterator Last )
{
    for( ; First < Last; ++First )
    {
        Iterator min = First;
        for( Iterator i = First; i < Last; ++i )
            if ( *i < *min )
                min = i;
        std::iter_swap( First, min );
    }
}

template<class Iterator>
void heap_sort( Iterator First, Iterator Last )
{
    partial_sort( First, Last, Last );
}

int main()
{
    typedef std::vector< int > vt;
    typedef void (*SORT_FUNC)( vt::iterator, vt::iterator );
    struct Func { SORT_FUNC func; const char* name; };
    Func sort_functions[] =
    {
        { &sort< vt::iterator >, "std::sort" }
        , { &stable_sort< vt::iterator >, "merge_sort" }
        , { &heap_sort< vt::iterator >, "heap_sort" }
        , { &insertion_sort< vt::iterator >, "insertion_sort" }
        , { &bubble_sort< vt::iterator >, "bubble_sort" }
        , { &selection_sort< vt::iterator >, "selection_sort" }
    };

    const double pc_min = 0.001, pc_max = 0.1, pc_step = 10;
    for( double i = pc_min; i <= pc_max; i *= pc_step )
    {
        cout << "Sort an almost sorted vector with " << 100*i << "% exchanged elements\n";
        cout << setw(8) << left << "size";
        for ( int fn = 0; fn < sizeof(sort_functions)/sizeof(Func); ++fn )
            std::cout << setw(16) << left << sort_functions[fn].name;
        cout << endl;

        const int min = 16000, max = 128000, step = 2;
        for( vt::size_type n = min; n <= max; n *= step )
        {
            cout << setw(8) << left << n;
            vt cont = generate_random< boost::uniform_int<>, vt, int >( n, 0, INT_MAX );
            make_almost_sorted( cont, i );
            for ( int fn = 0; fn < sizeof(sort_functions)/sizeof(Func); ++fn )
                std::cout << setw(16) << left << sort_timing( cont, sort_functions[fn].func );
            cout << endl;
        }      
        cout << endl;
    }
}


Результат:
Sort an almost sorted vector with 0.1% exchanged elements
size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
16000   0               0               0.015           0               0.172           0.141
32000   0               0               0               0               0.703           0.61
64000   0               0.016           0               0.016           2.75            2.453
128000  0               0.016           0.015           0.016           11.125          9.797

Sort an almost sorted vector with 1% exchanged elements
size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
16000   0               0               0               0               0.188           0.156
32000   0               0               0               0.015           0.735           0.64
64000   0               0               0.016           0.031           3               2.5
128000  0               0.016           0.015           0.157           11.765          9.813

Sort an almost sorted vector with 10% exchanged elements
size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
16000   0               0               0               0.032           0.265           0.157
32000   0               0               0               0.094           1.062           0.609
64000   0.016           0               0               0.344           4.25            2.438
128000  0.015           0.016           0.016           1.422           17.015          9.813


Вывод: пузырьку в коду делать нечего. Без исключений.
Re[5]: Почему преждевременная оптимизация - корень всех зол?
От: Кэр  
Дата: 19.08.08 14:39
Оценка: +3 :)
Здравствуйте, skeptik_, Вы писали:

M>>>Сортировку логично использовать стандартную , и уж точно в коде не должна появляться пузырьковая по определению.

S>>Ух какая уверенность в себе! Мне б такую.
S>>По делу: пузырек в случае почти отсортированных данных рвет qsort по производительности. Учите матчасть.

_>Хорошо, давайте учить матчасть:

_>...
_>Вывод: пузырьку в коду делать нечего. Без исключений.

С каких пор изучение матчасти заключается в написании тонны сомнительного кода, из которого потом делаются такие далеко идущие выводы? Кормана лучше почитайте.
Re[5]: Почему преждевременная оптимизация - корень всех зол?
От: anton_t Россия  
Дата: 19.08.08 16:42
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>Здравствуйте, Sinclair, Вы писали:


S>>Здравствуйте, minorlogic, Вы писали:


M>>>Сортировку логично использовать стандартную , и уж точно в коде не должна появляться пузырьковая по определению.

S>>Ух какая уверенность в себе! Мне б такую.
S>>По делу: пузырек в случае почти отсортированных данных рвет qsort по производительности. Учите матчасть.

_>Хорошо, давайте учить матчасть:

_>[ccode]

_>Вывод: пузырьку в коду делать нечего. Без исключений.


У меня был реальный случай, когда я без зазрения совести не взял qsort из стандартной библтотеки, а реализовал сортировку пузырьком: было известно, что в более 90% случаев данные отсортированы, а в оставшихся случаях имеют 2 неотсортированных элемента и, кроме того, менять местами равные элементы было нельзя. Естественно это решение в коде я прокомментировал.
Re[6]: Почему преждевременная оптимизация - корень всех зол?
От: skeptik_  
Дата: 19.08.08 17:15
Оценка: +1
Здравствуйте, anton_t, Вы писали:

_>Здравствуйте, skeptik_, Вы писали:


_>>Здравствуйте, Sinclair, Вы писали:


S>>>Здравствуйте, minorlogic, Вы писали:


M>>>>Сортировку логично использовать стандартную , и уж точно в коде не должна появляться пузырьковая по определению.

S>>>Ух какая уверенность в себе! Мне б такую.
S>>>По делу: пузырек в случае почти отсортированных данных рвет qsort по производительности. Учите матчасть.

_>>Хорошо, давайте учить матчасть:

_>>[ccode]

_>>Вывод: пузырьку в коду делать нечего. Без исключений.


_>У меня был реальный случай, когда я без зазрения совести не взял qsort из стандартной библтотеки, а реализовал сортировку пузырьком: было известно, что в более 90% случаев данные отсортированы, а в оставшихся случаях имеют 2 неотсортированных элемента и, кроме того, менять местами равные элементы было нельзя. Естественно это решение в коде я прокомментировал.


В этом случае лучшим решением была бы сортировка вставками, а не пузырёк.
Re[3]: В защиту пузырька
От: andy1618 Россия  
Дата: 20.08.08 04:59
Оценка: +1 :)
А>>...(поменять сортировки пузырьком на qsort...

E>IMHO от сортировки пузырьком следует отказаться раз и навсегда...

У пузырька есть свои плюсы:
1) простота/надёжность (безошибочно написать по памяти qsort с первой попытки — задача не тривиальная)
2) устойчивость (qsort не обладает этим качеством)
Так что при небольшом числе элементов сортировка пузырьком вполне имеет право на жизнь


E>Вообще, можно завсети правило, что использование квадратичных и более медленных алгоритмов требует обоснования...


Как уже писали, у qsort в худшем случае может вылезти O(n^2), поэтому в критических приложениях (медицина, транспорт, системы реального времени) использование qsort может оказаться недопустимым, т.е. придётся искать более стабильные по ресурсам алгоритмы.
Re[3]: Почему преждевременная оптимизация - корень всех зол?
От: Privalov  
Дата: 20.08.08 05:16
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Сортировку логично использовать стандартную , и уж точно в коде не должна появляться пузырьковая по определению.


Стандартную — это какую?

Совсем недавно мне надо было сортировать массив, содержащий от 4 до 15 элементов, и сортировка вызывается раз в пару часов. Что здесь логичнее всего применить?
Re[4]: Почему преждевременная оптимизация - корень всех зол?
От: minorlogic Украина  
Дата: 20.08.08 05:30
Оценка: +4 -1
Здравствуйте, Privalov, Вы писали:

P>Здравствуйте, minorlogic, Вы писали:


M>>Сортировку логично использовать стандартную , и уж точно в коде не должна появляться пузырьковая по определению.


P>Стандартную — это какую?


P>Совсем недавно мне надо было сортировать массив, содержащий от 4 до 15 элементов, и сортировка вызывается раз в пару часов. Что здесь логичнее всего применить?


Стандартную , это потдерживаемую языком/фреймворком, библиотеками. Вручную написанную сортировку я бы мог понять если требуется жесткая специфическая оптимизация(но тогда уже речь идет о днях проведенных в профайлере ).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[7]: Почему преждевременная оптимизация - корень всех зол?
От: anton_t Россия  
Дата: 20.08.08 07:00
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>Здравствуйте, anton_t, Вы писали:


_>>Здравствуйте, skeptik_, Вы писали:


_>>>Здравствуйте, Sinclair, Вы писали:


S>>>>Здравствуйте, minorlogic, Вы писали:


M>>>>>Сортировку логично использовать стандартную , и уж точно в коде не должна появляться пузырьковая по определению.

S>>>>Ух какая уверенность в себе! Мне б такую.
S>>>>По делу: пузырек в случае почти отсортированных данных рвет qsort по производительности. Учите матчасть.

_>>>Хорошо, давайте учить матчасть:

_>>>[ccode]

_>>>Вывод: пузырьку в коду делать нечего. Без исключений.


_>>У меня был реальный случай, когда я без зазрения совести не взял qsort из стандартной библтотеки, а реализовал сортировку пузырьком: было известно, что в более 90% случаев данные отсортированы, а в оставшихся случаях имеют 2 неотсортированных элемента и, кроме того, менять местами равные элементы было нельзя. Естественно это решение в коде я прокомментировал.


_>В этом случае лучшим решением была бы сортировка вставками, а не пузырёк.


И на сколько лучшим?
Re[5]: Почему преждевременная оптимизация - корень всех зол?
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 20.08.08 07:24
Оценка: +3
Здравствуйте, skeptik_, Вы писали:

_>Хорошо, давайте учить матчасть:

_>
_>template<class Iterator>
_>void bubble_sort( Iterator First, Iterator Last )
_>{
_>    while( First < --Last )
_>        for( Iterator i = First; i < Last; ++i )
_>            if ( *i > *(i + 1) )
_>                std::iter_swap( (i + 1), i );
_>}
_>


Если я не ошибаюсь, в сортировке пузырьком есть простая оптимизация -- если на очередной итерации не было ни одной перестановки, то дальнейшие действия не выполняются. Пусть меня поправят, если я не прав. Но, если я прав, то данная реализация метода пузырька весьма не оптимальна.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[4]: В защиту пузырька
От: vayerx  
Дата: 20.08.08 07:50
Оценка:
Здравствуйте, andy1618, Вы писали:
A>У пузырька есть свои плюсы:
A>безошибочно написать по памяти qsort с первой попытки — задача не тривиальная
вы считаете частой задачей написание собственных велосипедов?
Re[8]: Почему преждевременная оптимизация - корень всех зол?
От: skeptik_  
Дата: 20.08.08 11:17
Оценка:
Здравствуйте, anton_t, Вы писали:

_>>>>Вывод: пузырьку в коду делать нечего. Без исключений.


_>>>У меня был реальный случай, когда я без зазрения совести не взял qsort из стандартной библтотеки, а реализовал сортировку пузырьком: было известно, что в более 90% случаев данные отсортированы, а в оставшихся случаях имеют 2 неотсортированных элемента и, кроме того, менять местами равные элементы было нельзя. Естественно это решение в коде я прокомментировал.


_>>В этом случае лучшим решением была бы сортировка вставками, а не пузырёк.


_>И на сколько лучшим?


Это прекрасно видно из моего кода и результатов. Сортировка вставками быстрее (в несколько раз на случайных данных, на порядок при почти отсортированных) и проще в имплементации (3 строки против 4).
Re[6]: Почему преждевременная оптимизация - корень всех зол?
От: skeptik_  
Дата: 20.08.08 11:25
Оценка: 6 (1)
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, skeptik_, Вы писали:


_>>Хорошо, давайте учить матчасть:

_>>
_>>template<class Iterator>
_>>void bubble_sort( Iterator First, Iterator Last )
_>>{
_>>    while( First < --Last )
_>>        for( Iterator i = First; i < Last; ++i )
_>>            if ( *i > *(i + 1) )
_>>                std::iter_swap( (i + 1), i );
_>>}
_>>


E>Если я не ошибаюсь, в сортировке пузырьком есть простая оптимизация -- если на очередной итерации не было ни одной перестановки, то дальнейшие действия не выполняются. Пусть меня поправят, если я не прав. Но, если я прав, то данная реализация метода пузырька весьма не оптимальна.

Она мне известна, но она почти ничего не даёт:
template< typename Iterator >
void bubble_sort1( Iterator First, Iterator Last )
{
    bool test = true;
    for( --Last; First < Last && test; --Last )
    {
        test = false;
        for( Iterator j = First; j < Last; ++j )
            if( *(j + 1) < *j )
                std::iter_swap( j, j + 1 ), test = true;
    }
}

Результат:
Sort an almost sorted vector with 0.1% exchanged elements
size        std::sort       insertion_sort  bubble_sort     bubble_sort1
4000        0               0               0.031           0.015
8000        0               0               0.079           0.046
16000       0               0               0.172           0.157
32000       0               0               0.687           0.594
64000       0               0.016           2.719           2.625

Sort an almost sorted vector with 1% exchanged elements
size        std::sort       insertion_sort  bubble_sort     bubble_sort1
4000        0               0               0               0.016
8000        0               0               0.047           0.047
16000       0               0.015           0.172           0.188
32000       0               0.015           0.719           0.719
64000       0.016           0.031           2.875           2.844

Sort an almost sorted vector with 10% exchanged elements
size        std::sort       insertion_sort  bubble_sort     bubble_sort1
4000        0               0.015           0.016           0.015
8000        0               0               0.063           0.062
16000       0               0.016           0.265           0.25
32000       0               0.078           1.047           1.031
64000       0               0.359           4.141           4.094

Sort an almost sorted vector with 100% exchanged elements
size        std::sort       insertion_sort  bubble_sort     bubble_sort1
4000        0               0.015           0.031           0.047
8000        0               0.032           0.156           0.14
16000       0               0.125           0.594           0.594
32000       0               0.5             2.406           2.422
64000       0               2.031           9.828           9.75

Кнут кстати тоже пишет, что у пузырька нет никаких преимуществ, чтобы найти хоть какой-нибудь сценарий применения.
Re[5]: Почему преждевременная оптимизация - корень всех зол?
От: skeptik_  
Дата: 20.08.08 11:35
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>Здравствуйте, Sinclair, Вы писали:


S>>Здравствуйте, minorlogic, Вы писали:


M>>>Сортировку логично использовать стандартную , и уж точно в коде не должна появляться пузырьковая по определению.

S>>Ух какая уверенность в себе! Мне б такую.
S>>По делу: пузырек в случае почти отсортированных данных рвет qsort по производительности. Учите матчасть.

_>Хорошо, давайте учить матчасть:


PS Ну и на тот случай, если кто-нибудь возразит, что std::sort это не qsort:


template< typename T >
int int_compare( const void* left, const void* right )
{
    return *static_cast<const T*>(left) - *static_cast<const T*>(right);
}

template<class Iterator>
void quick_sort( Iterator First, Iterator Last )
{
    typedef typename iterator_traits< Iterator >::value_type value_t;
    qsort( &*First, distance( First, Last ), sizeof( value_t ), &int_compare< value_t > );
}


Sort an almost sorted vector with 0.1% exchanged elements
size        std::sort       insertion_sort  bubble_sort     quick_sort
32000       0               0               0.719           0.015
64000       0               0               2.719           0
128000      0.015           0.016           10.875          0.016

Sort an almost sorted vector with 1% exchanged elements
size        std::sort       insertion_sort  bubble_sort     quick_sort
32000       0               0.016           0.719           0
64000       0               0.047           2.906           0.016
128000      0               0.157           11.562          0.016

Sort an almost sorted vector with 10% exchanged elements
size        std::sort       insertion_sort  bubble_sort     quick_sort
32000       0.015           0.078           1.063           0
64000       0               0.359           4.187           0.016
128000      0               1.422           16.656          0.016

Sort an almost sorted vector with 100% exchanged elements
size        std::sort       insertion_sort  bubble_sort     quick_sort
32000       0               0.515           2.391           0
64000       0               2.047           9.641           0.015
128000      0.016           8.203           38.437          0.032
Re[7]: таки матчасть
От: vayerx  
Дата: 20.08.08 12:53
Оценка: +1
Здравствуйте, skeptik_, Вы писали:

_>Результат:

_>
_>Sort an almost sorted vector with 0.1% exchanged elements
_>size        std::sort       insertion_sort  bubble_sort     bubble_sort1
_>4000        0               0               0.031           0.015
_>8000        0               0               0.079           0.046
_>16000       0               0               0.172           0.157
_>32000       0               0               0.687           0.594
_>64000       0               0.016           2.719           2.625

_>Sort an almost sorted vector with 1% exchanged elements
_>size        std::sort       insertion_sort  bubble_sort     bubble_sort1
_>4000        0               0               0               0.016
_>8000        0               0               0.047           0.047
_>16000       0               0.015           0.172           0.188
_>32000       0               0.015           0.719           0.719
_>64000       0.016           0.031           2.875           2.844

_>Sort an almost sorted vector with 10% exchanged elements
_>size        std::sort       insertion_sort  bubble_sort     bubble_sort1
_>4000        0               0.015           0.016           0.015
_>8000        0               0               0.063           0.062
_>16000       0               0.016           0.265           0.25
_>32000       0               0.078           1.047           1.031
_>64000       0               0.359           4.141           4.094

_>Sort an almost sorted vector with 100% exchanged elements
_>size        std::sort       insertion_sort  bubble_sort     bubble_sort1
_>4000        0               0.015           0.031           0.047
_>8000        0               0.032           0.156           0.14
_>16000       0               0.125           0.594           0.594
_>32000       0               0.5             2.406           2.422
_>64000       0               2.031           9.828           9.75
_>


1e6 циклов (по уникальным буферам, естественно):
Sort an almost sorted vector with 0.1% exchanged elements
size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
4       0.046875        0.460938        0.171875        0.015625        0.015625        0.0546875
8       0.09375         0.507812        0.335938        0.03125         0.03125         0.21875
16      0.164062        1.00781         0.71875         0.0546875       0.046875        0.570312
32      0.382812        1.46875         1.67969         0.09375         0.109375        1.67188
64      0.945312        2.71094         4.08594         0.179688        0.203125        5.3125

Sort an almost sorted vector with 1% exchanged elements
size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
4       0.101562        0.484375        0.1875          0.0625          0.0546875       0.101562
8       0.125           0.53125         0.351562        0.0703125       0.0625          0.226562
16      0.179688        1.01562         0.742188        0.0859375       0.0859375       0.578125
32      0.375           1.48438         1.70312         0.109375        0.109375        1.67188
64      0.945312        2.71094         4.08594         0.179688        0.203125        5.3125

Sort an almost sorted vector with 10% exchanged elements
size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
4       0.101562        0.484375        0.1875          0.0546875       0.0546875       0.101562
8       0.125           0.53125         0.351562        0.0703125       0.0625          0.226562
16      0.1875          1.01562         0.742188        0.0859375       0.0859375       0.578125
32      0.382812        1.46094         1.71094         0.117188        0.226562        1.6875
64      1.46094         3.4375          4.39844         0.851562        7.75781         5.4375


время выполнения фунции соизмеримо со временем ее вызова, тем не менее, на некторых тестах различе в скоростях проявляется.
замечу, что на других аппаратных платформах (C64 или Mega168, к примеру) преимущество пузырька гораздо выше.

--
Core Duo 1.6, FreeBSD 7.0-STABLE-200803, g++ 4.2.1 20070719, boost 1.34, -O2
Re[4]: Почему преждевременная оптимизация - корень всех зол?
От: Константин Л. Франция  
Дата: 20.08.08 13:17
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, Erop, Вы писали:


А>>>...(поменять сортировки пузырьком на qsort...

E>>IMHO от сортировки пузырьком следует отказаться раз и навсегда...
E>>Вообще, можно завсети правило, что использование квадратичных и более медленных алгоритмов требует обоснования...

_FR>Не раз видел, когда при необходимости всего-то найти пересечение двух множеств (заданных массивом\IList\IEnumerable, не важно) делался foreach по одному списку, а внутри него — по другому И на все пожелания сделать правильно отвечалось, что "нечего преждевременной оптимизацией заниматься", тогда как дело попросту в незнании более эффективных алгоритмов (что, к счастью, поправимо) и нежелании их узнать (с чем уже ничего не поделать)


а правильно это как? что может быть быстрее на неотсортированной коллекции
Re[8]: таки матчасть
От: skeptik_  
Дата: 20.08.08 13:42
Оценка:
Здравствуйте, vayerx, Вы писали:

V>1e6 циклов (по уникальным буферам, естественно):

V>
V>Sort an almost sorted vector with 0.1% exchanged elements
V>size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
V>4       0.046875        0.460938        0.171875        0.015625        0.015625        0.0546875
V>

А какой вообще смысл, на векторе из 4 элементов менять каждый тысячный? У Вас полностью отсортированный вектор, а не почти.


V>
V>size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
V>8       0.125           0.53125         0.351562        0.0703125       0.0625          0.226562
V>

А ну да, ну да, на 8 элементах. Это конечно потрясающий результат, на векторе из 8 элементов выиграть 8 наносекунд. Из-за этого конечно надо имплементировать пузырёк.

Я изменил свой тест, так что для сортировки передаётся вектор с миллионом сортируемых векторов, замер времени изменил на QueryPerformanceCounter:

Sort an almost sorted vector with 10% exchanged elements
size        std::sort       insertion_sort  bubble_sort     bubble_sort1    quick_sort      
4           0.038           0.014           0.019           0.013           0.059           
8           0.044           0.023           0.149           0.023           0.267           
16          0.083           0.041           0.409           0.041           0.585           
32          0.220           0.182           1.424           0.784           1.370           

Sort random vector
size        std::sort       insertion_sort  bubble_sort     bubble_sort1    quick_sort      
4           0.058           0.048           0.049           0.051           0.112           
8           0.148           0.146           0.236           0.252           0.392           
16          0.369           0.402           0.852           0.875           1.102           
32          0.888           1.169           2.893           2.986           2.713

Итог: сортировку вставками пузырёк не бьёт. Стандартную он бьёт только на отсортированных данных до примерно двух десятков элементов. В итоге я всё ещё не вижу, где бы был применим пузырёк. insertion sort допустим можно запустить на маленьких и/или отсортированных данных, а пузырёк нафиг не нужен.
Re[9]: таки матчасть
От: vayerx  
Дата: 20.08.08 14:13
Оценка: +1
Здравствуйте, skeptik_, Вы писали:

_>А ну да, ну да, на 8 элементах. Это конечно потрясающий результат, на векторе из 8 элементов выиграть 8 наносекунд. Из-за этого конечно надо имплементировать пузырёк.

8 наносекунд — это сферический конь в вакууме. попробуйте запустить этот тест на 20MHz risc-процессоре и посчитайте разницу во времени
ваши громкие крики относятся к конкретной области применения данного алгоритма и некорректны в общем случае.
Re[10]: таки матчасть
От: skeptik_  
Дата: 20.08.08 14:18
Оценка:
Здравствуйте, vayerx, Вы писали:

V>Здравствуйте, skeptik_, Вы писали:


_>>А ну да, ну да, на 8 элементах. Это конечно потрясающий результат, на векторе из 8 элементов выиграть 8 наносекунд. Из-за этого конечно надо имплементировать пузырёк.

V>8 наносекунд — это сферический конь в вакууме. попробуйте запустить этот тест на 20MHz risc-процессоре и посчитайте разницу во времени
V>ваши громкие крики относятся к конкретной области применения данного алгоритма и некорректны в общем случае.
Я повторюсь — сортировку вставками пузырёк не бьёт.
Re[4]: В защиту пузырька
От: Трурль  
Дата: 20.08.08 14:26
Оценка: +1
Здравствуйте, andy1618, Вы писали:

A>У пузырька есть свои плюсы:

У пузырька только один плюс — запоминающееся название.

A>1) простота/надёжность (безошибочно написать по памяти qsort с первой попытки — задача не тривиальная)

Сортировка вставками или выбором гораздо проще и понятнее.
Re[11]: таки матчасть
От: vayerx  
Дата: 20.08.08 14:38
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>Здравствуйте, vayerx, Вы писали:

V>>8 наносекунд — это сферический конь в вакууме. попробуйте запустить этот тест на 20MHz risc-процессоре и посчитайте разницу во времени
V>>ваши громкие крики относятся к конкретной области применения данного алгоритма и некорректны в общем случае.
_>Я повторюсь — сортировку вставками пузырёк не бьёт.

Sort an almost sorted vector with 10% exchanged elements
size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
8       0.226562        1.03906         0.6875          0.09375         0.078125        0.4375
16      0.351562        2.00781         1.45312         0.117188        0.117188        1.14062

Sort an almost sorted vector with 25% exchanged elements
size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
4       0.171875        0.945312        0.34375         0.078125        0.0703125       0.140625
8       0.226562        1.03906         0.6875          0.0859375       0.078125        0.4375
Re[11]: таки матчасть
От: vayerx  
Дата: 20.08.08 14:40
Оценка:
Здравствуйте, skeptik_, Вы писали:
_>Я повторюсь — сортировку вставками пузырёк не бьёт.
на всех архитектурах/компиляторах/etc?
Re[12]: таки матчасть
От: skeptik_  
Дата: 20.08.08 15:09
Оценка: +1
Здравствуйте, vayerx, Вы писали:

V>Здравствуйте, skeptik_, Вы писали:


_>>Здравствуйте, vayerx, Вы писали:

V>>>8 наносекунд — это сферический конь в вакууме. попробуйте запустить этот тест на 20MHz risc-процессоре и посчитайте разницу во времени
V>>>ваши громкие крики относятся к конкретной области применения данного алгоритма и некорректны в общем случае.
_>>Я повторюсь — сортировку вставками пузырёк не бьёт.

V>
V>Sort an almost sorted vector with 10% exchanged elements
V>size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
V>8       0.226562        1.03906         0.6875          0.09375         0.078125        0.4375
V>16      0.351562        2.00781         1.45312         0.117188        0.117188        1.14062

V>Sort an almost sorted vector with 25% exchanged elements
V>size    std::sort       merge_sort      heap_sort       insertion_sort  bubble_sort     selection_sort
V>4       0.171875        0.945312        0.34375         0.078125        0.0703125       0.140625
V>8       0.226562        1.03906         0.6875          0.0859375       0.078125        0.4375
V>


Вообще говоря таймер у Вас похоже не самый точный, это видно из повторяющихся значений в разных колонках. В таких условиях обуждать 8 миллисекунд нет смысла. Кроме того, обмен здесь есть только в последней строке. В остальных случаях мы имеем дело с полностью отсортированным вектором. А вот у меня с точным таймером (QueryPerformanceCounter) пузырёк проигрывает вставкам.
Re[4]: В защиту пузырька
От: _DAle_ Беларусь  
Дата: 20.08.08 21:21
Оценка: +1
Здравствуйте, andy1618, Вы писали:

А>>>...(поменять сортировки пузырьком на qsort...


E>>IMHO от сортировки пузырьком следует отказаться раз и навсегда...

A>У пузырька есть свои плюсы:
A>1) простота/надёжность (безошибочно написать по памяти qsort с первой попытки — задача не тривиальная)
A>2) устойчивость (qsort не обладает этим качеством)
A>Так что при небольшом числе элементов сортировка пузырьком вполне имеет право на жизнь

Не в тему, но.. всегда интересовало, почему в качестве самой простой (ну или первой в книге) сортировки приводят bubble sort. IMHO, не знающему алгоритмов сортировки школьнику придет в голову скорее алгоритм: находим минимум, меняем с первым, и т.д. Обычный selection sort, простой как топор, еще и эффективнее, чем пузырек.
Re[5]: В защиту пузырька
От: skeptik_  
Дата: 20.08.08 21:31
Оценка:
Здравствуйте, _DAle_, Вы писали:

_DA>Не в тему, но.. всегда интересовало, почему в качестве самой простой (ну или первой в книге) сортировки приводят bubble sort. IMHO, не знающему алгоритмов сортировки школьнику придет в голову скорее алгоритм: находим минимум, меняем с первым, и т.д. Обычный selection sort, простой как топор, еще и эффективнее, чем пузырек.


Сортировка вставками тоже весьма интуитивна, так народ обычно карты на руках сортирует.
Re[9]: Почему преждевременная оптимизация - корень всех зол?
От: anton_t Россия  
Дата: 21.08.08 05:09
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>Здравствуйте, anton_t, Вы писали:


_>>>>>Вывод: пузырьку в коду делать нечего. Без исключений.


_>>>>У меня был реальный случай, когда я без зазрения совести не взял qsort из стандартной библтотеки, а реализовал сортировку пузырьком: было известно, что в более 90% случаев данные отсортированы, а в оставшихся случаях имеют 2 неотсортированных элемента и, кроме того, менять местами равные элементы было нельзя. Естественно это решение в коде я прокомментировал.


_>>>В этом случае лучшим решением была бы сортировка вставками, а не пузырёк.


_>>И на сколько лучшим?


_>Это прекрасно видно из моего кода и результатов. Сортировка вставками быстрее (в несколько раз на случайных данных, на порядок при почти отсортированных) и проще в имплементации (3 строки против 4).


В коде и результатах нет случая, когда данные отсортированы, поэтому ничего не видно.
Re[10]: Почему преждевременная оптимизация - корень всех зол
От: anton_t Россия  
Дата: 21.08.08 05:17
Оценка:
Здравствуйте, anton_t, Вы писали:

_>Здравствуйте, skeptik_, Вы писали:


_>>Здравствуйте, anton_t, Вы писали:


_>>>>>>Вывод: пузырьку в коду делать нечего. Без исключений.


_>>>>>У меня был реальный случай, когда я без зазрения совести не взял qsort из стандартной библтотеки, а реализовал сортировку пузырьком: было известно, что в более 90% случаев данные отсортированы, а в оставшихся случаях имеют 2 неотсортированных элемента и, кроме того, менять местами равные элементы было нельзя. Естественно это решение в коде я прокомментировал.


_>>>>В этом случае лучшим решением была бы сортировка вставками, а не пузырёк.


_>>>И на сколько лучшим?


_>>Это прекрасно видно из моего кода и результатов. Сортировка вставками быстрее (в несколько раз на случайных данных, на порядок при почти отсортированных) и проще в имплементации (3 строки против 4).


_>В коде и результатах нет случая, когда данные отсортированы, поэтому ничего не видно.


Да, и добавлю, что данные представляли из себя много массивов длинной в 99% случаев не больше сотни элементов, в остальных случаях ну максимум пара тысяч, а в случае 64-х элементов, как я вижу, разница при 1% не сортированных элементов считанные проценты. Так что я пока остаюсь при мнении, что пузырёк был верным решением.
Re[6]: Пузырёк таки утонул :)
От: andy1618 Россия  
Дата: 21.08.08 07:38
Оценка: 4 (1)
Здравствуйте, skeptik_, Вы писали:
_>Здравствуйте, _DAle_, Вы писали:

_DA>>Не в тему, но.. всегда интересовало, почему в качестве самой простой (ну или первой в книге) сортировки приводят bubble sort. IMHO, не знающему алгоритмов сортировки школьнику придет в голову скорее алгоритм: находим минимум, меняем с первым, и т.д. Обычный selection sort, простой как топор, еще и эффективнее, чем пузырек.


Selection sort на многих тестах проигрывает — см. ссылку внизу (если, конечно, там с реализацией не накосячили)


_>Сортировка вставками тоже весьма интуитивна, так народ обычно карты на руках сортирует.


Мда, почитал тут Википедию:

Due to its simplicity, bubble sort is often used to introduce the concept of an algorithm, or a sorting algorithm, to introductory computer science students. However, some researchers such as Owen Astrachan have gone to great lengths to disparage bubble sort and its continued popularity in computer science education, recommending that it no longer even be taught.[1]

The Jargon file, which famously calls bogosort "the archetypical perversely awful algorithm", also calls bubble sort "the generic bad algorithm".[2] Donald Knuth, in his famous The Art of Computer Programming, concluded that "the bubble sort seems to have nothing to recommend it, except a catchy name and the fact that it leads to some interesting theoretical problems", some of which he discusses therein.

Bubble sort is asymptotically equivalent in running time to insertion sort in the worst case, but the two algorithms differ greatly in the number of swaps necessary. Experimental results such as those of Astrachan have also shown that insertion sort performs considerably better even on random lists. For these reasons many modern algorithm textbooks avoid using the bubble sort algorithm in favor of insertion sort.


И эти слова подтверждаются наглядными тестами — сортировка вставками ни в чём не проигрывает пузырьковой сортировке:
http://vision.bc.edu/~dmartin/teaching/sorting/anim-html/nearlysorted.html

Правда, эти выводы справедливы для обычной архитектуры.
Возможно, в параллельных/квантовых/... вычислениях старый добрый пузырёк ещё всплывёт
Re[5]: В защиту пузырька
От: andy1618 Россия  
Дата: 21.08.08 07:52
Оценка:
V>Здравствуйте, andy1618, Вы писали:
A>>У пузырька есть свои плюсы:
A>>безошибочно написать по памяти qsort с первой попытки — задача не тривиальная
V>вы считаете частой задачей написание собственных велосипедов?

Зависит от платформы — иногда в базовой поставке готовые велосипеды отсутствуют. А бывает и другая крайность — что проще наваять свой дизайнерский велик, чем разгребать огромные залежи готовых велосипедов, самокатов и веломобилей
Но, в целом, согласен — частой эту задачу не назовёшь.

Недавно, кстати, видел пузырьковую сортировку в топовых решениях в турнире Google Code Jam
Re[7]: Пузырёк таки утонул :)
От: _DAle_ Беларусь  
Дата: 21.08.08 11:08
Оценка:
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, skeptik_, Вы писали:

_>>Здравствуйте, _DAle_, Вы писали:

_DA>>>Не в тему, но.. всегда интересовало, почему в качестве самой простой (ну или первой в книге) сортировки приводят bubble sort. IMHO, не знающему алгоритмов сортировки школьнику придет в голову скорее алгоритм: находим минимум, меняем с первым, и т.д. Обычный selection sort, простой как топор, еще и эффективнее, чем пузырек.


A>Selection sort на многих тестах проигрывает — см. ссылку внизу (если, конечно, там с реализацией не накосячили)


Я про разную асимптотику в количестве свопов.
Re[10]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 21.08.08 12:34
Оценка:
Здравствуйте, anton_t, Вы писали:

_>>>>>У меня был реальный случай, когда я без зазрения совести не взял qsort из стандартной библтотеки, а реализовал сортировку пузырьком: было известно, что в более 90% случаев данные отсортированы, а в оставшихся случаях имеют 2 неотсортированных элемента и, кроме того, менять местами равные элементы было нельзя. Естественно это решение в коде я прокомментировал.


_>>>>В этом случае лучшим решением была бы сортировка вставками, а не пузырёк.


_>>>И на сколько лучшим?


_>>Это прекрасно видно из моего кода и результатов. Сортировка вставками быстрее (в несколько раз на случайных данных, на порядок при почти отсортированных) и проще в имплементации (3 строки против 4).


_>В коде и результатах нет случая, когда данные отсортированы, поэтому ничего не видно.


Там есть случай, когда в отсортированном векторе меняется местами один элемент из тысячи. Это почти отсортированный вектор. На полностью отсортированном сортировка вставками это один проход. O(N). Вообще, из теста видно, что ни один алгоритм не ускоряется так сильно на отсортированных данных. Хотя обычно берется без зазрения совести std::sort/std::stable_sort. Единственный оправданием в вашем случае может быть то, что Вы писали на чистом С.
Re[11]: Почему преждевременная оптимизация - корень всех зол
От: anton_t Россия  
Дата: 21.08.08 17:44
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>Здравствуйте, anton_t, Вы писали:


_>>>>>>У меня был реальный случай, когда я без зазрения совести не взял qsort из стандартной библтотеки, а реализовал сортировку пузырьком: было известно, что в более 90% случаев данные отсортированы, а в оставшихся случаях имеют 2 неотсортированных элемента и, кроме того, менять местами равные элементы было нельзя. Естественно это решение в коде я прокомментировал.


_>>>>>В этом случае лучшим решением была бы сортировка вставками, а не пузырёк.


_>>>>И на сколько лучшим?


_>>>Это прекрасно видно из моего кода и результатов. Сортировка вставками быстрее (в несколько раз на случайных данных, на порядок при почти отсортированных) и проще в имплементации (3 строки против 4).


_>>В коде и результатах нет случая, когда данные отсортированы, поэтому ничего не видно.


_>Там есть случай, когда в отсортированном векторе меняется местами один элемент из тысячи. Это почти отсортированный вектор. На полностью отсортированном сортировка вставками это один проход. O(N). Вообще, из теста видно, что ни один алгоритм не ускоряется так сильно на отсортированных данных. Хотя обычно берется без зазрения совести std::sort/std::stable_sort. Единственный оправданием в вашем случае может быть то, что Вы писали на чистом С.


На отсортированном массиве пузырёк тоже делает только один проход.
Re[5]: Почему преждевременная оптимизация - корень всех зол?
От: _FRED_ Черногория
Дата: 21.08.08 17:56
Оценка: 1 (1)
Здравствуйте, Константин Л., Вы писали:

_FR>>Не раз видел, когда при необходимости всего-то найти пересечение двух множеств (заданных массивом\IList\IEnumerable, не важно) делался foreach по одному списку, а внутри него — по другому И на все пожелания сделать правильно отвечалось, что "нечего преждевременной оптимизацией заниматься", тогда как дело попросту в незнании более эффективных алгоритмов (что, к счастью, поправимо) и нежелании их узнать (с чем уже ничего не поделать)


КЛ>а правильно это как? что может быть быстрее на неотсортированной коллекции


Примерно так:
  using System;
  using System.Collections.Generic;
  using System.Linq;

  internal static class Program
  {
    private static void Main() {
      var first = Enumerable.Range(1, 10);
      var second = Enumerable.Range(5, 10);
      var intersect = first.Intersect(second, null);
      foreach(var item in intersect) {
        Console.WriteLine(item);
      }//for
    }

    private static IEnumerable<T> Intersect<T>(this IEnumerable<T> left, IEnumerable<T> right, IEqualityComparer<T> comparer) {
      var set = new HashSet<T>(comparer ?? EqualityComparer<T>.Default);
      foreach(var item in left) {
        set.Add(item);
      }//for
      foreach(var item in right) {
        if(set.Contains(item)) {
          yield return item;
        }//if
      }//for
    }
  }
Help will always be given at Hogwarts to those who ask for it.
Re[5]: Почему преждевременная оптимизация - корень всех зол?
От: Privalov  
Дата: 21.08.08 19:54
Оценка: +1 -7
Здравствуйте, minorlogic, Вы писали:

M>Стандартную , это потдерживаемую языком/фреймворком, библиотеками. Вручную написанную сортировку я бы мог понять если требуется жесткая специфическая оптимизация(но тогда уже речь идет о днях проведенных в профайлере ).


Если разработчик находится в цейтноте, он превращается в "чукчу-писателя". Особенно, если балбес-менеджер отрапортовал, что "вчера все будет готово". Во многих прикладных задачах сортировку вообще не приходится реализовывать, поскольку данные уже приходят упорядоченными по требуемым критериям. Поэтому, читая описание фреймворка/библиотеки, разработчик, как правило, не сталкивается с описанием средств сортировки. А в условиях работы "на вчера" ему проще, легче и быстрее настрочить метод пузырька, чем копаться в документации в поисках стандартных средств.

Вот попробовал я заменить свою функцию на предоставленное фреймворком средство (в моем случае Arrays.sort() из Java 1.4). Выдалась пара свободных часов. Закодировать его несложно, однако нужно все время обращаться к документации, а это потеря времени. Поскольку производительность программы в моем случае не имеет никакого значения (объем данных мал, и вызывается сортировка редко), абсолютно безразлично, как эту сортировку делать. В условиях жесткого дефицита времени на первый план выходит производительность разработчика. При реализации метода пузырька мне даже не пришлось никуда подсматривать (ну еще бы, не я ли сам его изобрел не первом курсе ).

А при попытке заменить "своего" пузырька на Arrays.sort пришлось сначала узнать, где этот самый Arrays.sort находится, потом разобраться с его параметрами, выяснить, как и когда передается в него функция сравнения. Все достаточно просто, но времени на все это нет. Ибо вокруг все бегают, суетятся, торопят. Так что отложил я это дело в сторонку и сижу, пока QA какой-нибудь баг в том районе найдут. Тогда, может, и заменю сортировку. Хотя, откуда в медоде пузырька баги?

Естественно, второй раз на реализацию сортировки штатными средствами времени уйдет гораздо меньше, но для этого ее надо сделать первый раз. А задача это, как я уже сказал, делается не каждый день. Тот пузырек, кажется, единственная ручная сортировка на все приложение.
Re[6]: Почему преждевременная оптимизация - корень всех зол?
От: minorlogic Украина  
Дата: 21.08.08 20:43
Оценка: 63 (6) +5 :)
Пилу точить некогда , надо пилить... Удачи.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[6]: Почему преждевременная оптимизация - корень всех зол?
От: minorlogic Украина  
Дата: 21.08.08 20:49
Оценка: :)
Добавлю про правильность написания пузырька.

Двавал группе не самых слабых разработчиков написать функцию нахождения максимального элемента в массиве целых чисел.

В итоге больше половины написали с ошибками , из которых 3 были просто багами и одна архитектурная, а теперь попробую себе представить когда подобные алгоритмы пишутся в спешке , жуть .....

А если подумать это очень несложный алгоритм, по сравнению с сортировкой просто дет сад. Хотите проверить ? попробуйте сразу после прочтения поста написать за 5 минут такую функцию.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[7]: Почему преждевременная оптимизация - корень всех зол?
От: skeptik_  
Дата: 21.08.08 21:09
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Добавлю про правильность написания пузырька.


M>Двавал группе не самых слабых разработчиков написать функцию нахождения максимального элемента в массиве целых чисел.


M>В итоге больше половины написали с ошибками , из которых 3 были просто багами и одна архитектурная, а теперь попробую себе представить когда подобные алгоритмы пишутся в спешке , жуть .....


А в чём заключалась архитектурная?

ЗЫ У меня получился за 3 минуты почти один в один std::max_element.
Re[8]: Почему преждевременная оптимизация - корень всех зол?
От: minorlogic Украина  
Дата: 21.08.08 21:35
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>ЗЫ У меня получился за 3 минуты почти один в один std::max_element.


Интереснее было бы если бы вы привели тут итоговый код
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[7]: Почему преждевременная оптимизация - корень всех зол?
От: Сергей  
Дата: 21.08.08 21:50
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Хотите проверить ? попробуйте сразу после прочтения поста написать за 5 минут такую функцию.


int
array_max(int *array, size_t size) {
  int r;
  size_t i;

  assert(array != NULL);
  assert(size != 0);

  r = array[0];
  for (i = 1; i < size; i++) {
    if (array[i] > r) {
      r = array[i];
    }
  }
  return r;
}


Ну как?
Re[9]: Почему преждевременная оптимизация - корень всех зол?
От: skeptik_  
Дата: 21.08.08 21:57
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Здравствуйте, skeptik_, Вы писали:


_>>ЗЫ У меня получился за 3 минуты почти один в один std::max_element.


M>Интереснее было бы если бы вы привели тут итоговый код


Да пожалуйста. Разница с msvc 9.0 в том, что у них условие заключает в себя цикл, а у меня стоит в начале (это я уже потом посмотрел)
template< typename ForwardIterator >
ForwardIterator max( ForwardIterator first, ForwardIterator last )
{
    if ( first == last )
        return first;

    ForwardIterator result = first;
    while( ++first != last )
        if ( *result < *first )
            result = first;
    return result;
}

А можно всё таки огласить архитектурную ошибку?
Re[10]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 22.08.08 04:49
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>А можно всё таки огласить архитектурную ошибку?


Инициализация первого значения чемнить вроде MIN_INT
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[8]: Почему преждевременная оптимизация - корень всех зол?
От: minorlogic Украина  
Дата: 22.08.08 04:52
Оценка:
Здравствуйте, Сергей, Вы писали:


С>Ну как?


Всего 2 ошибки из 3 , зато стоит асерт на нулевой размер что уже лучше чем ничего.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[9]: Почему преждевременная оптимизация - корень всех зол?
От: ironwit Украина  
Дата: 22.08.08 05:38
Оценка:
minorlogic wrote:
>
> С>Ну как?
>
> Всего 2 ошибки из 3 , зато стоит асерт на нулевой размер что уже лучше
> чем ничего.

ты не выделывайся ты свой покажи.
Posted via RSDN NNTP Server 2.1 beta
Я не умею быть злым, и не хочу быть добрым.
Re[7]: Почему преждевременная оптимизация - корень всех зол?
От: Privalov  
Дата: 22.08.08 07:38
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>А если подумать это очень несложный алгоритм, по сравнению с сортировкой просто дет сад. Хотите проверить ? попробуйте сразу после прочтения поста написать за 5 минут такую функцию.


Вот как-то так, наверное. Под рукой сейчас только Eclipse.

    static int find(int[] a) throws Exception
    {
        if (a == null)
            throw new NullPointerException("Array is empty");
        
        if (a.length == 0)
            throw new IndexOutOfBoundsException("length is 0");
        
        if (a.length == 1)
            return a[0];
        
        int max = a[0];
        for (int i = 1; i < a.length; i++)
        {
            if (a[i] > max)
                max = a[i];
        }
        return max;
    }
Re[9]: Почему преждевременная оптимизация - корень всех зол?
От: Сергей  
Дата: 22.08.08 11:43
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Всего 2 ошибки из 3 , зато стоит асерт на нулевой размер что уже лучше чем ничего.


Какие ошибки-то?
Re[6]: Почему преждевременная оптимизация - корень всех зол?
От: Константин Л. Франция  
Дата: 22.08.08 12:05
Оценка:
Здравствуйте, _FRED_, Вы писали:

ну с сетами и мапами неинтересно.
Re[7]: Почему преждевременная оптимизация - корень всех зол?
От: nikov США http://www.linkedin.com/in/nikov
Дата: 22.08.08 12:31
Оценка:
Здравствуйте, Константин Л., Вы писали:

КЛ>Здравствуйте, _FRED_, Вы писали:


КЛ>ну с сетами и мапами неинтересно.


Почему?

Кстати, предварительная сортировка коллекций и то даст лучший результат, чем вложенные циклы.
Re[8]: Почему преждевременная оптимизация - корень всех зол?
От: minorlogic Украина  
Дата: 22.08.08 12:32
Оценка:
Здравствуйте, Privalov, Вы писали:

P>
P>    static int find(int[] a) throws Exception
P>    {
P>        if (a == null)
P>            throw new NullPointerException("Array is empty");
        
P>        if (a.length == 0)
P>            throw new IndexOutOfBoundsException("length is 0");
        
P>        if (a.length == 1)
P>            return a[0];
        
P>        int max = a[0];
P>        for (int i = 1; i < a.length; i++)
P>        {
P>            if (a[i] > max)
P>                max = a[i];
P>        }
P>        return max;
P>    }

P>


Явку знаю плохо , поэтому прокоментируй плиз.

P> if (a == null)

P> throw new NullPointerException("Array is empty");

А разве такое поведенеи не будет если проверки не делать ? при первом же обращении вроде как выкинет NullPointerException ?

P> if (a.length == 0)

P> throw new IndexOutOfBoundsException("length is 0");

почему именно IndexOutOfBoundsException ?

P> if (a.length == 1)

P> return a[0];

Лишний код , лишняя проверка ?

P> if (a[i] > max)

P> max = a[i];

рекомендовал бы max = max(max, a[i])


Спасибо за потреченное время , было интересно.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[10]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 22.08.08 12:42
Оценка: -1
Здравствуйте, Сергей, Вы писали:

С>Какие ошибки-то?


Думаю что вы не согласитесь что это ошибки но я считаю это ошибками.

1. Нет обработки случая нулевого массива. ассерт это не наш метод потому что находится в теле функции , в документации к функции нет прекондишенов. Фактически если у меня только заголовок перед глазами , я не вижу причин вызвать функцию с ненулевой длиной.

2. при массиве нулевой длины может быть большой бабах при обращении к несуществующему элементу .
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[9]: Почему преждевременная оптимизация - корень всех зол?
От: skeptik_  
Дата: 22.08.08 12:56
Оценка: +1
Здравствуйте, minorlogic, Вы писали:

P>> if (a[i] > max)

P>> max = a[i];

M>рекомендовал бы max = max(max, a[i])


Я бы сказал, что это будет лишнее присвоение.
Re[11]: Почему преждевременная оптимизация - корень всех зол
От: CreatorCray  
Дата: 22.08.08 12:56
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>1. Нет обработки случая нулевого массива. ассерт это не наш метод потому что находится в теле функции , в документации к функции нет прекондишенов. Фактически если у меня только заголовок перед глазами , я не вижу причин вызвать функцию с ненулевой длиной.

Кстати как по вашему должна реагировать эта функция на нулевой массив? Exception?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[12]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 22.08.08 13:05
Оценка: +2
Здравствуйте, CreatorCray, Вы писали:

CC>Здравствуйте, minorlogic, Вы писали:


M>>1. Нет обработки случая нулевого массива. ассерт это не наш метод потому что находится в теле функции , в документации к функции нет прекондишенов. Фактически если у меня только заголовок перед глазами , я не вижу причин вызвать функцию с ненулевой длиной.

CC>Кстати как по вашему должна реагировать эта функция на нулевой массив? Exception?
Так, как это делает моя — возвращая итератор end. На мой взгляд это архитектурная ошибка — работать напрямую со значениями.
Re[12]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 22.08.08 13:36
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Кстати как по вашему должна реагировать эта функция на нулевой массив? Exception?


Нет , я бы ексепшен не использовал , флажок какойнить например ... Но в любом случае функция может в интерфейсе сообщить пользователю о возможности возникновения вот такой вот ситуации.

Но ексепшен тоже неплохо, намного лучше чем просто упасть.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[12]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 22.08.08 13:44
Оценка: :)
Т.е. конечно тут std::max_element это красивый дизайн и имплементация , максимально эфективно , ничего лишнего.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[13]: Почему преждевременная оптимизация - корень всех зол
От: CreatorCray  
Дата: 22.08.08 14:07
Оценка: +2
Здравствуйте, skeptik_, Вы писали:

M>>>1. Нет обработки случая нулевого массива. ассерт это не наш метод потому что находится в теле функции , в документации к функции нет прекондишенов. Фактически если у меня только заголовок перед глазами , я не вижу причин вызвать функцию с ненулевой длиной.

CC>>Кстати как по вашему должна реагировать эта функция на нулевой массив? Exception?
_>Так, как это делает моя — возвращая итератор end. На мой взгляд это архитектурная ошибка — работать напрямую со значениями.
Кстати из исходного условия "написать функцию нахождения максимального элемента в массиве целых чисел" не совсем ясно что требуется: само значение, или какая то ссылка (указатель/итератор) на элемент с максимальным значением.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[9]: Почему преждевременная оптимизация - корень всех зол?
От: Privalov  
Дата: 22.08.08 14:14
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Явку знаю плохо , поэтому прокоментируй плиз.


P>> if (a == null)

P>> throw new NullPointerException("Array is empty");

M>А разве такое поведенеи не будет если проверки не делать ? при первом же обращении вроде как выкинет NullPointerException ?


Будет, разумеется. Но ты бы тогда спросил, где обработка входных параметров? Вот я и выписал.


P>> if (a.length == 0)

P>> throw new IndexOutOfBoundsException("length is 0");

M>почему именно IndexOutOfBoundsException ?


Это можно было тоже не писать. Если сделать так в вызывающем коде:

{
   a = new int[0];
   max = find(a)
}


Java выбрасывает именно это исключение. Но мне кажется, читать, как я написал, все же понятнее. Ну и, опять же, явный контроль ввода.

P>> if (a.length == 1)

P>> return a[0];

M>Лишний код , лишняя проверка ?


Это, разумеется, можно было не писать.

P>> if (a[i] > max)

P>> max = a[i];

M>рекомендовал бы max = max(max, a[i])


Зачем? Разве max не реализует тот же самый if?

M>Спасибо за потреченное время , было интересно.


P.S. Я не противник использования в приложениях стандартных средств. Когда работа идет в нормальном режиме, тогда времени хватает на все: найти в документации описания, набросать пару методов, чтобы посмотреть, как работает, и т. п. Но в клинических, повторю, случаях, приходится превращаться в "чукчу-писателя". Думаю, не только я с подобным сталкиваюсь. Сейчас, првада, все реже.

P.P.S Велосипед для двоичного поиска я бы писать, пожалуй, не стал.
Re[14]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.08.08 14:21
Оценка: +1
Здравствуйте, CreatorCray, Вы писали:

CC>>>Кстати как по вашему должна реагировать эта функция на нулевой массив? Exception?

_>>Так, как это делает моя — возвращая итератор end. На мой взгляд это архитектурная ошибка — работать напрямую со значениями.
CC>Кстати из исходного условия "написать функцию нахождения максимального элемента в массиве целых чисел" не совсем ясно что требуется: само значение, или какая то ссылка (указатель/итератор) на элемент с максимальным значением.

Из исходного условия так же не понятно, требовалась ли максимально безопасная (с проверками параметров) или максимально быстрая версия. Применительно к C++, имхо, логичнее было бы предполагать максимально быструю версию (максимум, что в ней может быть еще -- это набор ассертов).

А подход с итераторами ничем не лучше простого возврата значения из наивной реализации max_element, ведь никто не запрещает программисту написать так:
std::cout << "max element: " << *max_element(a.begin(), a.end()) << std::endl;

а потом получить крах приложения из-за разыменования итератора end().

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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[15]: Почему преждевременная оптимизация - корень всех зол
От: nikov США http://www.linkedin.com/in/nikov
Дата: 22.08.08 14:27
Оценка:
Здравствуйте, eao197, Вы писали:

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


Если он описал в документации поведение метода для массива нулевой длины — то он действительно весь в белом.
Re[15]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 22.08.08 14:28
Оценка:
Здравствуйте, eao197, Вы писали:

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


Так как это обычный для STL подход, то пользователю не нужно запоминать, что моя функция ведёт себя отличным от STL образом.
Re[15]: Почему преждевременная оптимизация - корень всех зол
От: CreatorCray  
Дата: 22.08.08 14:36
Оценка: :))
Здравствуйте, eao197, Вы писали:

E>Из исходного условия так же не понятно, требовалась ли максимально безопасная (с проверками параметров) или максимально быстрая версия. Применительно к C++, имхо, логичнее было бы предполагать максимально быструю версию (максимум, что в ней может быть еще -- это набор ассертов).

Мне это все больше напоминает картинку "что хотел заказчик" http://www.4p.ru/images/nsmail79.gif
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[16]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.08.08 14:45
Оценка:
Здравствуйте, nikov, Вы писали:

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


N>Если он описал в документации поведение метода для массива нулевой длины — то он действительно весь в белом.


Не думаю. Есть два способа проектировать интерфейсы библиотек:
1. Простота, стройность, ортогональность и единообразие с точки зрения разработчика библиотеки. Подход с итераторами в STL -- это пример такого подхода.
2. Простота использования и освоения с точки зрения пользователя библиотеки.

Эти понятия взаимоисключающие. Пример с max_element в этом плане показателен. Разработчик max_element в STL-стиле сделал реализацию, которая единым образом обрабатывает как наличие элементов в последовательности, так и их отсутствие. Зато пользователь получает головную боль в виде необходимости самостоятельной проверки результата max_element.

По сути, разработчик max_element отказался от выполнения проверок и принятия решения и переложил эту заботу на пользователя. Но пользователи они же (мы же) такие, что не хотим лишних забот. Ах передали в max_element пустую последовательность, ну чтож, бывает, чтож вы нам ничего по этому поводу не сказали, а вернули какой-то end?

В результате тот же if(), который будет проверять наличие максимального элемента, все равно будет написан (только уже другим человеком). Или не написан с той же самой степенью вероятности.

Применительно к C++ у разработчика max_element, по большому счету выбора нет, т.к. он не знает, что делать с пустой последовательностью: кидать исключение, возвращать значение по умолчанию, вызвать abort(), устанавливать errno или делать еще что-нибудь. Т.к. в C++ нет общих подходов к обработке ошибок. А вот в более современных языках, в которых исключения были с самого начала, исключение из max_element при пустой последовательности было бы более приемлимым решением.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[17]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 22.08.08 15:24
Оценка: +2 -1
Здравствуйте, eao197, Вы писали:

E>По сути, разработчик max_element отказался от выполнения проверок и принятия решения и переложил эту заботу на пользователя. Но пользователи они же (мы же) такие, что не хотим лишних забот. Ах передали в max_element пустую последовательность, ну чтож, бывает, чтож вы нам ничего по этому поводу не сказали, а вернули какой-то end?


E>Применительно к C++ у разработчика max_element, по большому счету выбора нет, т.к. он не знает, что делать с пустой последовательностью: кидать исключение, возвращать значение по умолчанию, вызвать abort(), устанавливать errno или делать еще что-нибудь. Т.к. в C++ нет общих подходов к обработке ошибок. А вот в более современных языках, в которых исключения были с самого начала, исключение из max_element при пустой последовательности было бы более приемлимым решением.


Это мнимое удобство. Отлавливать исключения ничем не более удобно, чем проверить итератор. Твой подход на самом деле ведёт к такому вот коду:
map< A, B > m;
try {
  B b = m.find( a );
  // do something if a found
}
catch( SomeException const& e ) {
  // do something if a not found
}

Это тоже архитектурная ошибка — кидать исключения, когда ситуация не является truly exceptional. И в данном случае это не так, ибо внутри функции max_element у нас недостаточно знаний о том, является ли ситуация исключительной.
Re[18]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.08.08 15:40
Оценка: +2
Здравствуйте, skeptik_, Вы писали:

_>Это мнимое удобство. Отлавливать исключения ничем не более удобно, чем проверить итератор. Твой подход на самом деле ведёт к такому вот коду:

_>
_>map< A, B > m;
_>try {
_>  B b = m.find( a );
_>  // do something if a found
_>}
_>catch( SomeException const& e ) {
_>  // do something if a not found
_>}
_>


Упс, а откуда map и find взялись? Подмена темы не пройдет!

_>Это тоже архитектурная ошибка — кидать исключения, когда ситуация не является truly exceptional.


В случае с map::find отсутствие заданного ключа является нормальной ситуацией. А вот попытку найти максимальный элемент в пустой последовательности нормальной ситуацией назвать тяжело.

Когда пользователь вызывает max_element, то нормально считать, что он позаботился о том, чтобы элементы в последовательности были. Если же их нет, то это явная ошибка. И сообщить о ней нужно сразу в месте обнаружения (то бишь в max_element).

_> И в данном случае это не так, ибо внутри функции max_element у нас недостаточно знаний о том, является ли ситуация исключительной.


Извлечение квадратного корня из отрицательного числа, в принципе, имеет больше смысла, чем max_element от пустой последовательности. Но почему-то большинство реализаций sqrt в разных языках либо выбрасывают исключения domain_error, либо абортируют программу.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 22.08.08 15:50
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, skeptik_, Вы писали:


_>>Это тоже архитектурная ошибка — кидать исключения, когда ситуация не является truly exceptional.


E>В случае с map::find отсутствие заданного ключа является нормальной ситуацией. А вот попытку найти максимальный элемент в пустой последовательности нормальной ситуацией назвать тяжело.


E>Когда пользователь вызывает max_element, то нормально считать, что он позаботился о том, чтобы элементы в последовательности были. Если же их нет, то это явная ошибка. И сообщить о ней нужно сразу в месте обнаружения (то бишь в max_element).


То есть, ты считаешь, что практически все алгоритмы в STL надо было писать так:
template< typename Iterator >
... some_algorithm( Iterator first, Iterator last, ... )
{
    if ( first == last )
        throw ...;
    ...
}

Так?
Re[20]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.08.08 16:10
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>То есть, ты считаешь, что практически все алгоритмы в STL надо было писать так:

_>
_>template< typename Iterator >
_>... some_algorithm( Iterator first, Iterator last, ... )
_>{
_>    if ( first == last )
_>        throw ...;
_>    ...
_>}
_>

_>Так?

Во-первых, я считаю, что STL подход с итераторами вида [begin, end) это всего лишь один из возможных. Да, он принят в языке, но это вовсе не означает, что он лучший.

Во-вторых, я считаю, что в языке с контрактами такие вещи записываются гораздо лучше. Что-то вроде:
max_element (where: COLLECTION[T]): T
  requires
    non_empty_collection: 0 /= where.size
  ...

Если для скорости программы проверки не критичны, то исключение о нарушении контракта, порожденное самим run-time гораздо лучше, чем запрограммированные кем-то проверки. Если же скорость критична настолько, что даже проверки недопустимы, то получается тоже самое, что и в C++.

В-третьих, не буду говорить за все алгоритмы STL, то в некоторых случаях я бы хотел иметь выбор между функциями:
template< class ITERATOR >
typename ITERATOR::value_type
max_element( ITERATOR begin, ITERATOR end ) { ... }

template< class ITERATOR >
ITERATOR
max_element_ref( ITERATOR begin, ITERATOR end ) { ... }

где max_element может бросать исключения.

И, в-четвертых, мне кажется, что написание таких с виду простых и фундаментальных вещей как max_element или buble_sort вовсе не так тривиально и однозначно, как это кажется на первый взгляд.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[15]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 22.08.08 16:47
Оценка:
Здравствуйте, eao197, Вы писали:

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


А вы знаете альтернативу ? поделитесь.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[16]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.08.08 05:25
Оценка: +3
Здравствуйте, minorlogic, Вы писали:

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


M>А вы знаете альтернативу ? поделитесь.


Если речь о C++, то я бы предпочел иметь набор из функций:
// Бросает исключение в случае пустой последовательности.
T max_element( FI begin, FI end );
// Не бросает исключений, но вызывает abort.
T max_element( FI begin, FI end, nothrow );
// Возвращает ссылку на максимальный элемент или end.
// Не бросает исключений.
FI max_element_reference( FI begin, FI end );


Только, боюсь, в современном C++ это невозможно.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[17]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 23.08.08 08:08
Оценка: -1
Здравствуйте, eao197, Вы писали:

E>Только, боюсь, в современном C++ это невозможно.


Таким образом ты подтверждаешь что std::max_element это лучшее решение, поскольку лучше ты не можешь предложить в рамках языка ?

P.S. в таком куске незначительной функциональности , я бы не хотел чтобы язык за меня делал выбор стратегии обработки ошибок. Поэтому возвращать указатель на последний (невалидный) элемент это мегаудачное решение.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[18]: Почему преждевременная оптимизация - корень всех зол
От: VoidEx  
Дата: 23.08.08 12:32
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>P.S. в таком куске незначительной функциональности , я бы не хотел чтобы язык за меня делал выбор стратегии обработки ошибок. Поэтому возвращать указатель на последний (невалидный) элемент это мегаудачное решение.


Т.е. сообщение об ошибке возвратом указателя на невалидный элемент — это мегаудочное решение, но при этом это не "выбор стратегии обработки ошибки"? Это как так?
Re[19]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 23.08.08 12:52
Оценка:
Здравствуйте, VoidEx, Вы писали:

VE>Здравствуйте, minorlogic, Вы писали:


M>>P.S. в таком куске незначительной функциональности , я бы не хотел чтобы язык за меня делал выбор стратегии обработки ошибок. Поэтому возвращать указатель на последний (невалидный) элемент это мегаудачное решение.


VE>Т.е. сообщение об ошибке возвратом указателя на невалидный элемент — это мегаудочное решение, но при этом это не "выбор стратегии обработки ошибки"? Это как так?


Просто , это не ребует усилий от програмитста. Можешь проверить , а можешь нет . Не вводится новый механизм , флаг или код возврата или исключения. На мой взгляд , очень удачное решение.

Обсуждать решение я готов только в сравнении с альтернативным.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[20]: Почему преждевременная оптимизация - корень всех зол
От: VoidEx  
Дата: 23.08.08 13:49
Оценка: +1
Здравствуйте, minorlogic, Вы писали:

M>Просто , это не ребует усилий от програмитста. Можешь проверить , а можешь нет . Не вводится новый механизм , флаг или код возврата или исключения. На мой взгляд , очень удачное решение.


M>Обсуждать решение я готов только в сравнении с альтернативным.


Как раз eao197 и предлагает набор функций, чтобы способ обработки ошибки выбирал программист, а не библиотека. В данном же случае, способ выбран за программиста.
Re: Потому что - преждевременная!
От: Геннадий Васильев Россия http://www.livejournal.com/users/gesha_x
Дата: 23.08.08 14:01
Оценка: 13 (1) +8
Здравствуйте, Аноним, Вы писали:

А>Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?


Это тонкая подколка патриархов IT. В фразе "premature optimization is a root of evil" ключевое слово не "optimization", а "premature". Многие попросту не понимают, что этим афоризмом отмечается не какой-то априорно негативный хараткер оптимизации, выполняемой до профилирования (там уже и в самом деле может оказаться поздно что-то оптимизировать), а лишь то, что вредно оптимизировать код, руководствуясь неполными предположениями о характере работы программы. Только и всего.

Сиречь, корень зол в постановке лошади позади телеги. Только и всего.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Re[18]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.08.08 15:27
Оценка:
Здравствуйте, minorlogic, Вы писали:

E>>Только, боюсь, в современном C++ это невозможно.


M>Таким образом ты подтверждаешь что std::max_element это лучшее решение, поскольку лучше ты не можешь предложить в рамках языка ?


Возможно, мои опасения напрасны и даже в рамках C++98/2003 можно реализовать предложенный мной набор функций. Выделив отдельные варианты для указателей и итераторов:
// Бросают исключение.
template< class T >
T & max_element( T * begin, T * end ) { ... }
template< class T >
const T & max_element( const T * begin, const T * end ) { ... }
template< class FI >
typename FI::reference_type max_element( FI begin, FI end ) { ... }
... аналогично остальные функции ...


Так что не подтверждаю.

M>P.S. в таком куске незначительной функциональности , я бы не хотел чтобы язык за меня делал выбор стратегии обработки ошибок. Поэтому возвращать указатель на последний (невалидный) элемент это мегаудачное решение.


Мне сложно назвать мегаудачным решение, при котором миллионы пользователей вынуждены проверять условие, которое мог проверить и обработать один разработчик max_element. Поскольку мне кажется очень странным использование max_element в стиле:
std::vector< int > v;
... какие-то действия, которые, по мнению разработчика, заполняют v...
std::vector< int >::iterator m = std::max_element( v.begin(), v.end() );
if( m == v.end() )
  // Что за оно вааще?!!

Ведь обращение к max_element делается в уверенности, что последовательность не пуста (аналогичная уверенность у разработчика есть при вызове sqrt -- он просто на 100% убежден, что его аргумент не отрицателен). Имея такую уверенность обычный разработчик вряд ли будет писать проверку возвращенного итератора. Как следствие -- неопределенное поведение программы.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[17]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 25.08.08 03:43
Оценка:
Здравствуйте, eao197, Вы писали:


E>Только, боюсь, в современном C++ это невозможно.

Почему невозможно? Ты имеешь в виду существующий STL? В языке никаких проблем сделать nothrow я не вижу.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[18]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 06:56
Оценка:
Здравствуйте, Sinclair, Вы писали:

E>>Только, боюсь, в современном C++ это невозможно.

S>Почему невозможно? Ты имеешь в виду существующий STL?

Я боялся, что подобная реализация выльется в большое количество перегруженных функций (чтобы разделить случаи итераторов и указателей):
// Бросают исключение.
template< class T >
T & max_element( T * begin, T * end ) { ... }
template< class T >
const T & max_element( const T * begin, const T * end ) { ... }
template< class FI >
typename FI::reference_type max_element( FI begin, FI end ) { ... }
... аналогично остальные функции ...

и что все равно окажутся какие-то случаи, которые не будут поддержаны. Но, вероятно, мои опасения напрасны.

S>В языке никаких проблем сделать nothrow я не вижу.


А он уже есть nothrow, но используется пока только для new.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 25.08.08 11:00
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Sinclair, Вы писали:


E>>>Только, боюсь, в современном C++ это невозможно.

S>>Почему невозможно? Ты имеешь в виду существующий STL?

E>Я боялся, что подобная реализация выльется в большое количество перегруженных функций (чтобы разделить случаи итераторов и указателей):

А зачем их делить? Шаблонная функция работает одинаково хорошо и с указателями, и с итераторами.
Re[20]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 11:05
Оценка:
Здравствуйте, skeptik_, Вы писали:

E>>Я боялся, что подобная реализация выльется в большое количество перегруженных функций (чтобы разделить случаи итераторов и указателей):

_>А зачем их делить? Шаблонная функция работает одинаково хорошо и с указателями, и с итераторами.

Вопрос в определении типа возвращаемого функцие значения. Для указателя тип возвращаемого значения выводится элементарно. Для итератора -- через вложенный тип reference_type.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[21]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 25.08.08 11:22
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, skeptik_, Вы писали:


E>>>Я боялся, что подобная реализация выльется в большое количество перегруженных функций (чтобы разделить случаи итераторов и указателей):

_>>А зачем их делить? Шаблонная функция работает одинаково хорошо и с указателями, и с итераторами.

E>Вопрос в определении типа возвращаемого функцие значения. Для указателя тип возвращаемого значения выводится элементарно. Для итератора -- через вложенный тип reference_type.


Это делается через iterator_traits. Типа так:
template< typename ForwardIterator >
typename std::iterator_traits< ForwardIterator >::reference max_element( ForwardIterator first, ForwardIterator last )
{
    ForwardIterator result = first;
    if ( first != last )
        while( ++first != last )
            if ( *result < *first )
                result = first;
    return *result;
}
Re[22]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 11:31
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>Это делается через iterator_traits. Типа так:

_>
_>template< typename ForwardIterator >
_>typename std::iterator_traits< ForwardIterator >::reference max_element( ForwardIterator first, ForwardIterator last )
_>{
_>    ForwardIterator result = first;
_>    if ( first != last )
_>        while( ++first != last )
_>            if ( *result < *first )
_>                result = first;
_>    return *result;
_>}
_>


Множественность реализаций max_element заменяется множественностью реализаций iterator_traits. Те же яйца -- только в профиль.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[23]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 25.08.08 12:06
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, skeptik_, Вы писали:


_>>Это делается через iterator_traits. Типа так:

_>>
_>>template< typename ForwardIterator >
_>>typename std::iterator_traits< ForwardIterator >::reference max_element( ForwardIterator first, ForwardIterator last )
_>>{
_>>    if ( first == last )
_>>        throw std::runtime_error( "..." );
_>>    ForwardIterator result = first;
_>>    while( ++first != last )
_>>        if ( *result < *first )
_>>            result = first;
_>>    return *result;
_>>}
_>>


E>Множественность реализаций max_element заменяется множественностью реализаций iterator_traits. Те же яйца -- только в профиль.


И почему это тебя волнует? Специализации iterator_traits предоставлены стандартной библиотекой. Так что хватит отмазок, скажи просто, что не знал о iterator_traits, и дело с концом.
Re[24]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 12:16
Оценка:
Здравствуйте, skeptik_, Вы писали:

E>>Множественность реализаций max_element заменяется множественностью реализаций iterator_traits. Те же яйца -- только в профиль.


_>И почему это тебя волнует?


Как я уже говорил
Автор: eao197
Дата: 22.08.08
есть два подхода к разработке библиотек: удобный для разработчика библиотеки и удобный для пользователя библиотеки. Первый способ, обычно, требует меньше кода в библиотеке, потому-то он и удобен для разработчика.

Существующий в STL max_element как раз служит примером первого подхода к разработке. Написали пять строчек "универсального" кода -- и дело с концом.

_> Специализации iterator_traits предоставлены стандартной библиотекой.


max_element так же предоставлен стандартной библиотекой, тем не менее он здесь обсуждается.

_>Так что хватит отмазок, скажи просто, что не знал о iterator_traits, и дело с концом.


Знал, но забыл, что равнозначно тому, что не знал. В C++ еще очень и очень много того, что я не знал никогда и не меньше того, что я основательно забыл.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[25]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 25.08.08 13:48
Оценка:
Здравствуйте, eao197, Вы писали:

E>Как я уже говорил
Автор: eao197
Дата: 22.08.08
есть два подхода к разработке библиотек: удобный для разработчика библиотеки и удобный для пользователя библиотеки. Первый способ, обычно, требует меньше кода в библиотеке, потому-то он и удобен для разработчика.


Я не вижу ни малейшей разницы для пользователя между
template< typename T > T& max_element( T* first, T* last );
template< typename I > typename I::reference max_element( I first, I last );

и
template< typename I > typename std::iterator_traits<I>::reference max_element( I first, I last );


Зато вижу огромную разницу для писателя данных функций.
Re[26]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 14:00
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>Я не вижу ни малейшей разницы для пользователя между

_>
_>template< typename T > T& max_element( T* first, T* last );
_>template< typename I > typename I::reference max_element( I first, I last );
_>

_>и
_>
_>template< typename I > typename std::iterator_traits<I>::reference max_element( I first, I last );
_>


_>Зато вижу огромную разницу для писателя данных функций.


Вы смотрите не туда, куда надо.
Сейчас у пользователя нет ни одной из указанных выше функций. Вот в этом-то и все дело.

Вам же нравится обсуждать то, что я с ходу не написал вариант max_element, который бы возвращал std::iterator_traits<I>::reference. Да, вы правы, я не написал. Более того, я думал, что в современном C++ это будет невозможно. Можете еще раз бросить в меня какашкой.

Только все это чисто технические вопросы, которые решаются в течении нескольких минут после начала программирования. Принципиальный вопрос в том, что было бы лучше иметь в C++ три варианта max_element (max_element с throw; max_element без nothrow, но с abort; max_element_reference без throw) или же единственный существующий max_element -- это и есть мегаудачное решение? Здесь уже знание C++ не причем.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 25.08.08 14:13
Оценка: +1
Попробуй посмотреть на это с такой стороны.

Все втои варианты можно реализовать используя текущий std::max_element без накладных расходов , а вот наоборот врятли ....

Если вспомнить что C++ дизайнится чтобы не вносить накладных расходов по неиспользуемым фичам...
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[20]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 14:20
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Попробуй посмотреть на это с такой стороны.


M>Все втои варианты можно реализовать используя текущий std::max_element без накладных расходов , а вот наоборот врятли ....


M>Если вспомнить что C++ дизайнится чтобы не вносить накладных расходов по неиспользуемым фичам...


Если переименовать max_element в max_element_reference и добавить два предложенных мной варианта max_element (с throw и с abort), то у пользователя будет выбор:
— иметь максимальную производительность без проверок при поиске максимального элемента (используется max_element_reference);
— иметь безопасность ценой одного if-а (max_element с throw или abort).

Ничего не теряется по сравнению с существующим вариантом.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[21]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 25.08.08 14:26
Оценка: +2
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, minorlogic, Вы писали:


M>>Попробуй посмотреть на это с такой стороны.


M>>Все втои варианты можно реализовать используя текущий std::max_element без накладных расходов , а вот наоборот врятли ....


M>>Если вспомнить что C++ дизайнится чтобы не вносить накладных расходов по неиспользуемым фичам...


E>Если переименовать max_element в max_element_reference и добавить два предложенных мной варианта max_element (с throw и с abort), то у пользователя будет выбор:

E>- иметь максимальную производительность без проверок при поиске максимального элемента (используется max_element_reference);
E>- иметь безопасность ценой одного if-а (max_element с throw или abort).

E>Ничего не теряется по сравнению с существующим вариантом.


Кому это надо добавляет себе в toolbox
template< typename ForwardIterator >
typename std::iterator_traits< ForwardIterator >::reference max_element_value( ForwardIterator first, ForwardIterator last )
{
    if ( first == last )
        throw std::runtime_error( "empty range" );
    return *std::max_element( first, last );
}

и радуется жизни. Кому не надо -- не добавляет, и тоже радуется жизни.
Re[22]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 14:31
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>Кому это надо добавляет себе в toolbox

_>
_>template< typename ForwardIterator >
_>typename std::iterator_traits< ForwardIterator >::reference max_element_value( ForwardIterator first, ForwardIterator last )
_>{
_>    if ( first == last )
_>        throw std::runtime_error( "empty range" );
_>    return *std::max_element( first, last );
_>}
_>

_>и радуется жизни. Кому не надо -- не добавляет, и тоже радуется жизни.

Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[23]: Почему преждевременная оптимизация - корень всех зол
От: CreatorCray  
Дата: 25.08.08 14:32
Оценка:
Здравствуйте, eao197, Вы писали:

E>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.

Но это не значит что надо туда пхать весь функционал, который только можно придумать.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[24]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 14:39
Оценка:
Здравствуйте, CreatorCray, Вы писали:

E>>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.

CC>Но это не значит что надо туда пхать весь функционал, который только можно придумать.

Хорошо, давай так: ты бы предпочел использовать:

a) только вариант max_element с необходимостью проверки возвращаемого значения;
b) вариант max_element с выбросом исключений и max_element_reference без выброса исключений

?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[23]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 25.08.08 14:47
Оценка:
Здравствуйте, eao197, Вы писали:

E>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.


Не совсем так. Стандартная библиотека это компромис между компактностью, выразительностью и функциональностью . В случае std::max_element мне кажется проведена черта в нужном месте.

При желании это решение лекго дополнить или расширить своими политиками обработки ошибки.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[25]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 25.08.08 14:53
Оценка:
Здравствуйте, eao197, Вы писали:

E>Хорошо, давай так: ты бы предпочел использовать:


E>a) только вариант max_element с необходимостью проверки возвращаемого значения;

E>b) вариант max_element с выбросом исключений и max_element_reference без выброса исключений

Я вклинюсь маленько , я бы предпочел оба варианта за исключением лишь синтаксиса , хотелось бы чтобы они различались в названиях.

P.S.

Проверять или нет возвращаемое значение решает програмист , есть очень много ситуаций когда заранее известно что массив не пустой.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[24]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 14:56
Оценка:
Здравствуйте, minorlogic, Вы писали:

E>>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.


M>Не совсем так. Стандартная библиотека это компромис между компактностью, выразительностью и функциональностью . В случае std::max_element мне кажется проведена черта в нужном месте.


M>При желании это решение лекго дополнить или расширить своими политиками обработки ошибки.


А чем ситуация с max_element отличается от оператора new, который по умолчанию бросает bad_alloc и имеет вариант new(nothrow)? Почему бы new не возвращать 0, а пользователям не проверять результат и не определять собственные политики обработки ошибок?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[26]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 15:23
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Проверять или нет возвращаемое значение решает програмист , есть очень много ситуаций когда заранее известно что массив не пустой.


Это было бы хорошо, если бы программисты не ошибались. А они ошибаются. Программист может думать, что массив не пустой. Но это может оказаться не так в силу самых разных причин, в частности, изменения требований к программе, произведенному рефакторингу или замененному алгоритму.

Один if внутри max_element, имхо, не такая уж большая цена за повышение надежности программы _без участия_ программиста. По крайней менее в тех случаях, когда скорость max_element не критична.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 25.08.08 15:28
Оценка: +1 :)
Здравствуйте, eao197, Вы писали:

E>Один if внутри max_element, имхо, не такая уж большая цена за повышение надежности программы _без участия_ программиста. По крайней менее в тех случаях, когда скорость max_element не критична.


Вы говорите только про один из вариантов использования , а стандартная библиотке статается не делать компромисов за счет снижения скорости , Попробуйте представить себе сценарий использования внутри какогонить DCT или другого цифрового алгоритма.

Аргументы ваши понятны , убедительно но недостаточны.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[25]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 25.08.08 15:32
Оценка: +1
Здравствуйте, eao197, Вы писали:

E>Как я уже говорил
Автор: eao197
Дата: 22.08.08
есть два подхода к разработке библиотек: удобный для разработчика библиотеки и удобный для пользователя библиотеки. Первый способ, обычно, требует меньше кода в библиотеке, потому-то он и удобен для разработчика.


Если уж говорить об удобстве применения, давайте попробуем данную функцию применить. Вот например выше я имплементировал несколько сортировочных алгоритмов. В алгоритме selection sort как раз можно применить max_element:
template< typename ForwardIterator >
void selection_sort( ForwardIterator first, ForwardIterator last )
{
    while( first < --last )
        std::iter_swap( last, std::max_element( first, last + 1 ) );
}

Этот код неплохо демонстрирует мощь применённого (Степановым?) подхода: различные функции стандартной библиотеки очень легко комбинируются между собой за счёт унитарного подхода. На мой взгляд очень удобно.
Re[28]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 15:36
Оценка: +1
Здравствуйте, minorlogic, Вы писали:

E>>Один if внутри max_element, имхо, не такая уж большая цена за повышение надежности программы _без участия_ программиста. По крайней менее в тех случаях, когда скорость max_element не критична.


M>Вы говорите только про один из вариантов использования , а стандартная библиотке статается не делать компромисов за счет снижения скорости , Попробуйте представить себе сценарий использования внутри какогонить DCT или другого цифрового алгоритма.


Таких вариантов использования будет, максимум, несколько процентов от всех случаев использования max_element программистами. И для таких выжимателей скорости можно было бы предоставить max_element_reference с отсутствием накладных расходов.

О том и речь, что стандартную библиотеку можно было бы спроектировать с учетом удобства для большинства use case-ов, оставив низкоуровневые средства для тех, кому нужны специфические требования.

M>Аргументы ваши понятны , убедительно но недостаточны.


Да мне фиолетово. Я занимаюсь разработкой библиотек для программистов и убедился на собственном опыте, что удобство пользователя -- это одно из важнейших требований к библиотеке. Об этом и говорю -- может кому-нибудь пригодится, чтобы на своих шишках не приходилось до этой простой истины доходить.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[26]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.08.08 15:39
Оценка:
Здравствуйте, skeptik_, Вы писали:

E>>Как я уже говорил
Автор: eao197
Дата: 22.08.08
есть два подхода к разработке библиотек: удобный для разработчика библиотеки и удобный для пользователя библиотеки. Первый способ, обычно, требует меньше кода в библиотеке, потому-то он и удобен для разработчика.


_>Если уж говорить об удобстве применения, давайте попробуем данную функцию применить. Вот например выше я имплементировал несколько сортировочных алгоритмов. В алгоритме selection sort как раз можно применить max_element:

_>
_>template< typename ForwardIterator >
_>void selection_sort( ForwardIterator first, ForwardIterator last )
_>{
_>    while( first < --last )
_>        std::iter_swap( last, std::max_element_reference( first, last + 1 ) );
_>}
_>


И всех делов. Не говоря уже о том, что max_element_reference гораздо точнее отражает суть происходящего, чем max_element.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 25.08.08 16:04
Оценка:
Здравствуйте, eao197, Вы писали:

E> Не говоря уже о том, что max_element_reference гораздо точнее отражает суть происходящего, чем max_element.


Для меня -- нет. max_element_reference ассоциируется у меня с T&.
Re[19]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 03:29
Оценка:
Здравствуйте, eao197, Вы писали:

S>>В языке никаких проблем сделать nothrow я не вижу.


E>А он уже есть nothrow, но используется пока только для new.


void f(const std::nothrow_t&);
//...
f(std::nothrow);
Re[23]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 04:12
Оценка:
Здравствуйте, eao197, Вы писали:
...
E>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.

здесь
Автор:
Дата: 19.07.08
это обсуждали.
Re[3]: Почему преждевременная оптимизация - корень всех зол?
От: Pavel Dvorkin Россия  
Дата: 26.08.08 05:44
Оценка:
Здравствуйте, vayerx, Вы писали:

V>Здравствуйте, bexab, Вы писали:


B>>Наверное в том, что корректно работающую программу проще переделать в быструю, чем быструю в корректно работающую.

V>Согласен. Оптимизировать/рефакторить программу многократно проще, когда она полностью работает и ее код покрыт тестами.

При условии, что для этой оптимизации не требуется полностью изменить алгоритм и структуры данных программы. А вот если потребуется — пишите все с начала.
With best regards
Pavel Dvorkin
Re[20]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 06:54
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Здравствуйте, eao197, Вы писали:


S>>>В языке никаких проблем сделать nothrow я не вижу.


E>>А он уже есть nothrow, но используется пока только для new.


ЮЖ>
ЮЖ>void f(const std::nothrow_t&);
ЮЖ>//...
ЮЖ>f(std::nothrow);
ЮЖ>


1. Это что?
2. Где в стандартной библиотеке C++ еще используется nothrow, кроме operator new?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[21]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 07:22
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Здравствуйте, eao197, Вы писали:


S>>>>В языке никаких проблем сделать nothrow я не вижу.


E>>>А он уже есть nothrow, но используется пока только для new.


ЮЖ>>
ЮЖ>>void f(const std::nothrow_t&);
ЮЖ>>//...
ЮЖ>>f(std::nothrow);
ЮЖ>>


E>1. Это что?

Вариант реализации вот этого:
// Бросает исключение в случае пустой последовательности.
T max_element( FI begin, FI end );
// Не бросает исключений, но вызывает abort.
T max_element( FI begin, FI end, nothrow );

Правда здесь все только на уровне соглашений.

E>2. Где в стандартной библиотеке C++ еще используется nothrow, кроме operator new?

Там где имена функций/операторов одинаковы для throw и nothrow версий. Собственно только в new/delete.
Re[22]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 07:25
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

E>>1. Это что?

ЮЖ>Вариант реализации вот этого:
ЮЖ>
ЮЖ>// Бросает исключение в случае пустой последовательности.
ЮЖ>T max_element( FI begin, FI end );
ЮЖ>// Не бросает исключений, но вызывает abort.
ЮЖ>T max_element( FI begin, FI end, nothrow );
ЮЖ>

ЮЖ>Правда здесь все только на уровне соглашений.

Понятно. Именно об этом я и говорил, просто не было времени искать в документации, к какому конкретно типу относится nothrow, поэтому указал в прототипе nothrow без типа.

E>>2. Где в стандартной библиотеке C++ еще используется nothrow, кроме operator new?

ЮЖ>Там где имена функций/операторов одинаковы для throw и nothrow версий. Собственно только в new/delete.

Вот об этом и речь. Хотя такое же соглашение можно было применить и для max_element.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[23]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 07:42
Оценка: +1
Здравствуйте, eao197, Вы писали:

E>>>2. Где в стандартной библиотеке C++ еще используется nothrow, кроме operator new?

ЮЖ>>Там где имена функций/операторов одинаковы для throw и nothrow версий. Собственно только в new/delete.

E>Вот об этом и речь. Хотя такое же соглашение можно было применить и для max_element.


А зачем нужна throw-версия для max_element ? После выброса исключения там два варианта: поймать и обработать, поймать и перевыбросить другое(более высокоуровневое) исключение. Первый случай сразу можно заменить на nothrow версию(с явной обработкой перед попыткой вызова), во-втором случае можно сразу выкинуть исключение необходимого типа.
Re[25]: Почему преждевременная оптимизация - корень всех зол
От: CreatorCray  
Дата: 26.08.08 08:04
Оценка:
Здравствуйте, eao197, Вы писали:

E>>>Я, по наивности, считал, что задача библиотек (особенно стандартных) -- избавлять программиста от написания вот такого вот кода.

CC>>Но это не значит что надо туда пхать весь функционал, который только можно придумать.

E>Хорошо, давай так: ты бы предпочел использовать:


E>a) только вариант max_element с необходимостью проверки возвращаемого значения;

E>b) вариант max_element с выбросом исключений и max_element_reference без выброса исключений

В конкретном случае, если нет готового и известного мне на данный момент max_element, идеально подходящего под нужды задачи, я напишу свой, который будет делать то, что мне нужно. И уж точно не буду морочить себе голову какой из них кошернее. И совершенно точно не буду искать библиотеку, в которой есть такой вариант max_element — это не тот функционал, ради которого стоит так заморачиваться.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[24]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 26.08.08 08:11
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>А зачем нужна throw-версия для max_element ? После выброса исключения там два варианта: поймать и обработать, поймать и перевыбросить другое(более высокоуровневое) исключение.

Вообще-то три.
ЮЖ>Первый случай сразу можно заменить на nothrow версию(с явной обработкой перед попыткой вызова), во-втором случае можно сразу выкинуть исключение необходимого типа.
Как насчет "проигнорировать и позволить вызывающему коду разобраться с проблемой"?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[25]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 08:49
Оценка:
Здравствуйте, Sinclair, Вы писали:
...
ЮЖ>>Первый случай сразу можно заменить на nothrow версию(с явной обработкой перед попыткой вызова), во-втором случае можно сразу выкинуть исключение необходимого типа.
S>Как насчет "проигнорировать и позволить вызывающему коду разобраться с проблемой"?

Если исключение вызвано невозможностью выполнения постусловий, то здесь генерация исключений оправдана. В случае с max_element нарушены предусловия. Именно с этой точки зрения throw вариант — избыточен. Если кому-нибудь все же необходимо такое поведение — пишут свой кидающий вариант.
Re[24]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 10:07
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

E>>>>2. Где в стандартной библиотеке C++ еще используется nothrow, кроме operator new?

ЮЖ>>>Там где имена функций/операторов одинаковы для throw и nothrow версий. Собственно только в new/delete.

E>>Вот об этом и речь. Хотя такое же соглашение можно было применить и для max_element.


ЮЖ>А зачем нужна throw-версия для max_element ?


Еще раз: программисты ошибаются. ОШИБАЮТСЯ!
Это означает, что даже если программист думает, что max_element вызывается для непустой последовательности, то наивное использование max_element:
some_type max_value = *max_element(sequence.begin(), sequence.end());

может оставлять программу в неопределенном состоянии.

И я не верю, что _нормальный_ программист будет писать в своем коде так:
iterator max_value_it = max_element(sequence.begin(), sequence.end());
if( iterator != sequence.end() )
  {
    some_type max_value = *max_value_it;
  }


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

Для фанатов производительности и изящного STL-стиля стандартная библиотека должна так же предоставлять небросающий вариант под именем max_element_reference (или max_element_pointer, или max_element_iterator), который возвращает итераторы.

Но я еще нигде не видел убедительных доказательств того, что лишний if в начале max_element, проверяющий последовательность на пустоту, способен привести к существенным накладным расходам.

Так же я не понимаю аргументов вида -- кому нужно, пусть сами проверяют возвращаемые значения, реализуют собственные политики обработки ошибок или пишут собственные варианты max_element. Это все работа, которую разработчики вынуждены проделывать снова и снова. А значит ее можно было бы сделать один раз -- в стандартной библиотеке. Либо же они ее вообще не делают, не проверяют результат max_element и оставляют в своих программах очередные бомбы замедленного действия.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[25]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 10:27
Оценка: +1
Здравствуйте, eao197, Вы писали:
...
ЮЖ>>А зачем нужна throw-версия для max_element ?

E>Еще раз: программисты ошибаются. ОШИБАЮТСЯ!

Не спорю...
E>Это означает, что даже если программист думает, что max_element вызывается для непустой последовательности, то наивное использование max_element:
E>
E>some_type max_value = *max_element(sequence.begin(), sequence.end());
E>

E>может оставлять программу в неопределенном состоянии.

...
E>А вот если max_element будет выбрасывать исключение в случае пустой последовательности, то программа окажется во вполне определенном состоянии -- раскрутка стека по исключению.
Это фиктивное состояние, которое возникло при ошибке. И которое потенциально может быть "проглочено" вышестояшим catch(exception&). Т.е. программа не упадет, а сделает вид что все хорошо. Только от бага в ней это не спасает.

E>Но я еще нигде не видел убедительных доказательств того, что лишний if в начале max_element, проверяющий последовательность на пустоту, способен привести к существенным накладным расходам.


Если посмотреть с другой колокольни
Автор: Юрий Жмеренецкий
Дата: 12.04.08
, то это логическая ошибка.

E>Так же я не понимаю аргументов вида -- кому нужно, пусть сами проверяют возвращаемые значения, реализуют собственные политики обработки ошибок или пишут собственные варианты max_element. Это все работа, которую разработчики вынуждены проделывать снова и снова. А значит ее можно было бы сделать один раз -- в стандартной библиотеке.

Контраргументы приведены в здесь
Автор:
Дата: 19.07.08
. Более точных сообщений указать не могу, у меня тут локальный цейтнот наступил.
Re[26]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 10:35
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

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

ЮЖ>Это фиктивное состояние, которое возникло при ошибке. И которое потенциально может быть "проглочено" вышестояшим catch(exception&). Т.е. программа не упадет, а сделает вид что все хорошо. Только от бага в ней это не спасает.

Ну все, приплыздец. Я просто не знаю, что против этого возразить. Функция max_element выбрасывает исключение, поскольку она не может работать в условиях пустой последовательности. Программа проглатывает это исключение и делает вид, что все нормально... Какой смысл вообще говорить о таких программах?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 11:20
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Юрий Жмеренецкий, Вы писали:


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

ЮЖ>>Это фиктивное состояние, которое возникло при ошибке. И которое потенциально может быть "проглочено" вышестояшим catch(exception&). Т.е. программа не упадет, а сделает вид что все хорошо. Только от бага в ней это не спасает.

E>Ну все, приплыздец. Я просто не знаю, что против этого возразить. Функция max_element выбрасывает исключение, поскольку она не может работать в условиях пустой последовательности. Программа проглатывает это исключение и делает вид, что все нормально... Какой смысл вообще говорить о таких программах?


Ну а как же это:
E>Еще раз: программисты ошибаются. ОШИБАЮТСЯ!

Сначала все работает хорошо, в max_element всегда(!) передаются валидные данные, поэтому обработчика нет. Порефакторили, _ошиблись_, где-то стоит корневой обработчик который молча проглотил, возможно скинув в лог информацию. Но программа продолжает работать дальше. Возможно такое ?

Кроме того, в условиях когда все функции(а-ля max_element) начинают кидать исключения по любому поводу, становится существенно сложнее писать код со strong guarantee.
Re[28]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 11:32
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Сначала все работает хорошо, в max_element всегда(!) передаются валидные данные, поэтому обработчика нет. Порефакторили, _ошиблись_, где-то стоит корневой обработчик который молча проглотил, возможно скинув в лог информацию. Но программа продолжает работать дальше. Возможно такое ?


Возможно, но это все гораздо лучше разыменования невалидного итератора.

ЮЖ>Кроме того, в условиях когда все функции(а-ля max_element) начинают кидать исключения по любому поводу, становится существенно сложнее писать код со strong guarantee.


Это не повод считать существующий вариант max_element мегаудачным решением.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[29]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 11:46
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Сначала все работает хорошо, в max_element всегда(!) передаются валидные данные, поэтому обработчика нет. Порефакторили, _ошиблись_, где-то стоит корневой обработчик который молча проглотил, возможно скинув в лог информацию. Но программа продолжает работать дальше. Возможно такое ?


E>Возможно, но это все гораздо лучше разыменования невалидного итератора.

Чем лучше ? тем что у нас система в непредсказуемом состоянии, от которой можно ожидать все что угодно?

ЮЖ>>Кроме того, в условиях когда все функции(а-ля max_element) начинают кидать исключения по любому поводу, становится существенно сложнее писать код со strong guarantee.


E>Это не повод считать существующий вариант max_element мегаудачным решением.

По крайней мере к нему легко прикручивается любое поведение, хотя это уже не аргумент...
Re[30]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 11:55
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>>>Сначала все работает хорошо, в max_element всегда(!) передаются валидные данные, поэтому обработчика нет. Порефакторили, _ошиблись_, где-то стоит корневой обработчик который молча проглотил, возможно скинув в лог информацию. Но программа продолжает работать дальше. Возможно такое ?


E>>Возможно, но это все гораздо лучше разыменования невалидного итератора.

ЮЖ>Чем лучше ? тем что у нас система в непредсказуемом состоянии, от которой можно ожидать все что угодно?

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

А вот разыменование невалидного итератора может привести к наведенной ошибке, которая может проявится через неопределенное время в непредсказуемом месте. Вам бы хотелось разбираться с падением банковской системы, которая должна работать в режиме 24x7 под нагрузкой в несколько тысяч транзакций в секунду из-за того, что месяц назад при некорректном использовании max_element был испорчен какой-то байтик в памяти?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[31]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 13:18
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>>>Сначала все работает хорошо, в max_element всегда(!) передаются валидные данные, поэтому обработчика нет. Порефакторили, _ошиблись_, где-то стоит корневой обработчик который молча проглотил, возможно скинув в лог информацию. Но программа продолжает работать дальше. Возможно такое ?


E>>>Возможно, но это все гораздо лучше разыменования невалидного итератора.

ЮЖ>>Чем лучше ? тем что у нас система в непредсказуемом состоянии, от которой можно ожидать все что угодно?

E>Я исхожу из тезиса, что выброшенное исключение дает C++ программисту простой способ прервать проблемную ситуацию и восстановить работоспособность программы где-то наверху.

Восстановить работоспособность не всегда возможно, баги(а мы о них) разные бывают.
Здесь я говорю только об исключениях, которые возникают в случае невыполнения предусловий.

E>Либо же завершить программу с более-менее явной диагностикой.

Тут всплывает одна проблема — обеспечение целостности данных, которыми программа оперировала в момент возникновения бага. Если раскручивать стек, то _возможно_ что будут выполнены некоторые операции, которые нарушат целостность. Тут опять всплывает строгая гарантия.

E>А вот разыменование невалидного итератора может привести к наведенной ошибке, которая может проявится через неопределенное время в непредсказуемом месте.

Некорректная работа в случае замалчивания о произошедшей ошибке может привести к такому же результату.

E>Вам бы хотелось разбираться с падением банковской системы, которая должна работать в режиме 24x7 под нагрузкой в несколько тысяч транзакций в секунду из-за того, что месяц назад при некорректном использовании max_element был испорчен какой-то байтик в памяти?

Вот почему-то все думают что если я использую nothrow версию, то я не проверяю параметры... Это неверно. Они не проверяются только если их значения можно гарантировать, основываясь на текущем состоянии. Это _другой_ подход. На пост и предусловиях, assert'ax, тестировании и документации, на существовании контрактов.
Разыменование невалидного итератора — эта ситуация которой не может быть вообще. Исходя из пост и предусловий можно доказывать корректность программы(несколько преувеличено, но я думаю что понятно о чем я). В Вашем случе — баг рассматривается как нечто, которое может вполне себе спокойно существовать в работающей программе.

Для обеспечения совсем уж 100% надежности применяются другие методы, например N-version programming.
Re[32]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 13:43
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

E>>Вам бы хотелось разбираться с падением банковской системы, которая должна работать в режиме 24x7 под нагрузкой в несколько тысяч транзакций в секунду из-за того, что месяц назад при некорректном использовании max_element был испорчен какой-то байтик в памяти?

ЮЖ>Вот почему-то все думают что если я использую nothrow версию, то я не проверяю параметры...

Вы может и проверяете. Я не всегда проверяю. Из-за чего временами приходится выискивать баги, связанные с битой памятью.

ЮЖ>Разыменование невалидного итератора — эта ситуация которой не может быть вообще. Исходя из пост и предусловий можно доказывать корректность программы(несколько преувеличено, но я думаю что понятно о чем я).


Нет, я не понимаю. Так же я не понимаю, о каких пред- и постусловиях можно говорить в C++ -- в C++ это разве что благая воля программиста (использование assert-ов или условий проверки).

ЮЖ>В Вашем случе — баг рассматривается как нечто, которое может вполне себе спокойно существовать в работающей программе.


Боюсь, что это не только в моем случае. Это, насколько я могу судить, повсеместное явление.
Более того, люди даже разрабатывают способы разработки программ, которые выживают в условиях присутствия багов — Making reliable distributed systems <b>in the presence of sodware errors</b> И достигают немалых успехов.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[33]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 14:43
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Юрий Жмеренецкий, Вы писали:


E>>>Вам бы хотелось разбираться с падением банковской системы, которая должна работать в режиме 24x7 под нагрузкой в несколько тысяч транзакций в секунду из-за того, что месяц назад при некорректном использовании max_element был испорчен какой-то байтик в памяти?

ЮЖ>>Вот почему-то все думают что если я использую nothrow версию, то я не проверяю параметры...

E>Вы может и проверяете. Я не всегда проверяю.

Я не говорю о том чтобы проверять всегда.

ЮЖ>>Разыменование невалидного итератора — эта ситуация которой не может быть вообще. Исходя из пост и предусловий можно доказывать корректность программы(несколько преувеличено, но я думаю что понятно о чем я).


E>Нет, я не понимаю.

здесь

Например:
/// \pre: a > 0
void f1(int a);

/// \pre: a > 1
void f2(int a) 
{
  if(a > 0) // <-- эта проверка здесь лишняя, предусловие дает гарантию что a > 0.
  {
    f1(a); 
  }
}

И также для постусловий. Плюс ослабление/усиление.


E>Так же я не понимаю, о каких пред- и постусловиях можно говорить в C++

О самых обыкновенных...

E> -- в C++ это разве что благая воля программиста (использование assert-ов или условий проверки).

Или я вопроса не понял.

ЮЖ>>В Вашем случе — баг рассматривается как нечто, которое может вполне себе спокойно существовать в работающей программе.

E>Боюсь, что это не только в моем случае. Это, насколько я могу судить, повсеместное явление.
Это не радует );
Re[34]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 15:02
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>>>Вот почему-то все думают что если я использую nothrow версию, то я не проверяю параметры...


E>>Вы может и проверяете. Я не всегда проверяю.

ЮЖ>Я не говорю о том чтобы проверять всегда.

Если вы не проверяете аргументы max_element всегда и не проверяете результат max_element всегда, тогда у вас нет никаких гарантий того, что однажды вы не разыменуете некорректный итератор.

ЮЖ>>>Разыменование невалидного итератора — эта ситуация которой не может быть вообще. Исходя из пост и предусловий можно доказывать корректность программы(несколько преувеличено, но я думаю что понятно о чем я).


E>>Нет, я не понимаю.

ЮЖ>здесь

ЮЖ>Например:

ЮЖ>
ЮЖ>/// \pre: a > 0
ЮЖ>void f1(int a);

ЮЖ>/// \pre: a > 1
ЮЖ>void f2(int a) 
ЮЖ>{
ЮЖ>  if(a > 0) // <-- эта проверка здесь лишняя, предусловие дает гарантию что a > 0.
ЮЖ>  {
ЮЖ>    f1(a); 
ЮЖ>  }
ЮЖ>}
ЮЖ>

ЮЖ>И также для постусловий. Плюс ослабление/усиление.

В C++ ничего этого нет. Нет никакой поддержки инваринтов/пред-/постусловий со стороны Run-Time. Разработчики могут только учитывать неформальные спецификации из документации, но не имеют никаких инструментов для проверки своих ожиданий во время исполнения.

Тогда как языки Eiffel и D проверяют инварианты/пред-/постусловия и порождают исключения, если они нарушены. А это означает, что если программа скомпилирована с сохранением предусловий, то функция f2 не будет вызвана с неправильными аргументами вне зависимости от того, знал ли программист о нарушении контракта или не знал.

E>>Так же я не понимаю, о каких пред- и постусловиях можно говорить в C++

ЮЖ>О самых обыкновенных...

Нет в C++ даже самых обыкновенных.

ЮЖ>>>В Вашем случе — баг рассматривается как нечто, которое может вполне себе спокойно существовать в работающей программе.

E>>Боюсь, что это не только в моем случае. Это, насколько я могу судить, повсеместное явление.
ЮЖ>Это не радует );

Се ля ви.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[35]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 15:43
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>>>Вот почему-то все думают что если я использую nothrow версию, то я не проверяю параметры...


E>>>Вы может и проверяете. Я не всегда проверяю.

ЮЖ>>Я не говорю о том чтобы проверять всегда.

E>Если вы не проверяете аргументы max_element всегда и не проверяете результат max_element всегда, тогда у вас нет никаких гарантий того, что однажды вы не разыменуете некорректный итератор.

Достаточно _одной_ проверки.

ЮЖ>>>>Разыменование невалидного итератора — эта ситуация которой не может быть вообще. Исходя из пост и предусловий можно доказывать корректность программы(несколько преувеличено, но я думаю что понятно о чем я).


E>>>Нет, я не понимаю.

ЮЖ>>здесь
ЮЖ>>И также для постусловий. Плюс ослабление/усиление.

E>В C++ ничего этого нет. Нет никакой поддержки инваринтов/пред-/постусловий со стороны Run-Time.


Из отсутствия поддержки инвариантов не следует что в С++ их нет.

E>Разработчики могут только учитывать неформальные спецификации из документации, но не имеют никаких инструментов для проверки своих ожиданий во время исполнения.


Зато в Compile-Time имеют:

typedef checked_value<std::string, name_policy> user_name;


Конструктор user_name проверяет аргумент(std::string) на допустимость и кидает исключения при необходимости. Изменить объект user_name можно только с помощью оператора =. Существование объекта user_name гарантирует выполнение условий, проверяемых _один_раз_ при создании. Не валидных объектов(с точки зрения name_policy) не существует. И т.п., накрутить можно все что угодно, причем полностью прозрачно.

E>Тогда как языки Eiffel и D проверяют инварианты/пред-/постусловия и порождают исключения, если они нарушены.


Про постусловия я не говорил.

А так, если сильно захотеть:
#define assert(exp) MY_ASSERT(exp) // а там throw

Хотя это плохой вариант.

E>А это означает, что если программа скомпилирована с сохранением предусловий, то функция f2 не будет вызвана с неправильными аргументами вне зависимости от того, знал ли программист о нарушении контракта или не знал.


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

E>>>Так же я не понимаю, о каких пред- и постусловиях можно говорить в C++

ЮЖ>>О самых обыкновенных...

E>Нет в C++ даже самых обыкновенных.

Можно услышать определение "самых обыкновенных" ?
Re[36]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 16:02
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

E>>Если вы не проверяете аргументы max_element всегда и не проверяете результат max_element всегда, тогда у вас нет никаких гарантий того, что однажды вы не разыменуете некорректный итератор.

ЮЖ>Достаточно _одной_ проверки.

Это какой?
Я смею утверждать, что _обычный_ программист не будет писать перед вызовом существующего max_element пустоту последовательности. И не будет проверять возвращаемое значение. Он уверен, что:
a) либо последовательность не пуста;
b) либо любое возвращаемое max_element значение удовлетворяет текущему контексту (см. пример skeptika_ с использованием max_element в функции сортировки).

Его вера, иногда, может быть ошибочна. В этих случаях есть шанс получить битую память и наведенную ошибку.

Какая _одна_ проверка способна избавить разработчика от подобной ситуции?

ЮЖ>>>здесь

ЮЖ>>>И также для постусловий. Плюс ослабление/усиление.

E>>В C++ ничего этого нет. Нет никакой поддержки инваринтов/пред-/постусловий со стороны Run-Time.


ЮЖ>Из отсутствия поддержки инвариантов не следует что в С++ их нет.


Точно так же можно заявить, что из отсутствия поддержки ООП в C не следует, что в C нет ООП.

E>>Разработчики могут только учитывать неформальные спецификации из документации, но не имеют никаких инструментов для проверки своих ожиданий во время исполнения.


ЮЖ>) Зато в Compile-Time имеют:


ЮЖ>
ЮЖ>typedef checked_value<std::string, name_policy> user_name;
ЮЖ>


ЮЖ>Конструктор user_name проверяет аргумент(std::string) на допустимость и кидает исключения при необходимости. Изменить объект user_name можно только с помощью оператора =. Существование объекта user_name гарантирует выполнение условий, проверяемых _один_раз_ при создании. Не валидных объектов(с точки зрения name_policy) не существует. И т.п., накрутить можно все что угодно, причем полностью прозрачно.


С этим согласен. Но это не имеет никакого отношения к обсуждавшемуся дизайну std::max_element.

E>>А это означает, что если программа скомпилирована с сохранением предусловий, то функция f2 не будет вызвана с неправильными аргументами вне зависимости от того, знал ли программист о нарушении контракта или не знал.


ЮЖ>А программисту сложно почитать документацию и выяснить контракт? Или он будет наугад аргументы подставлять, авось заведется?


1. Программисты ошибаются. Даже если читают документацию. А читают они ее не так уж часто, иначе не появилось бы выражение RTFM.

2. Условия меняются. Либо контракты обновляют поставщики библиотек в новых версиях. Либо новые версии ПО начинают несоблюдать контракты. Вспомните Ариан 5 -- очень хороший пример эволюции ПО, когда корректностью контрактов в новом окружении для старого ПО никто не озадачился.

E>>>>Так же я не понимаю, о каких пред- и постусловиях можно говорить в C++

ЮЖ>>>О самых обыкновенных...

E>>Нет в C++ даже самых обыкновенных.

ЮЖ>Можно услышать определение "самых обыкновенных" ?

Вот, например. Более полно о контрактах лучше читать толмуд Бертрана Мейера.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[37]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 26.08.08 16:12
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Юрий Жмеренецкий, Вы писали:


E>>>Если вы не проверяете аргументы max_element всегда и не проверяете результат max_element всегда, тогда у вас нет никаких гарантий того, что однажды вы не разыменуете некорректный итератор.

ЮЖ>>Достаточно _одной_ проверки.

E>Это какой?


Например вот такой:

template< typename RandomAccessIterator >
void selection_sort( RandomAccessIterator first, RandomAccessIterator last )
{
    while( first < --last ) // <-- max_element никогда не будет вызван с пустым интервалом
        std::iter_swap( last, std::max_element( first, last + 1 ) );
}
Re[38]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 16:23
Оценка:
Здравствуйте, skeptik_, Вы писали:

E>>>>Если вы не проверяете аргументы max_element всегда и не проверяете результат max_element всегда, тогда у вас нет никаких гарантий того, что однажды вы не разыменуете некорректный итератор.

ЮЖ>>>Достаточно _одной_ проверки.

E>>Это какой?


_>Например вот такой:


_>
_>template< typename RandomAccessIterator >
_>void selection_sort( RandomAccessIterator first, RandomAccessIterator last )
_>{
_>    while( first < --last ) // <-- max_element никогда не будет вызван с пустым интервалом
_>        std::iter_swap( last, std::max_element( first, last + 1 ) );
_>}

_>


Ага. Во всех C++ программах функция std::max_element вызывается всего в одном месте -- в selection_sort. И именно это использование max_element абсолютно безопасно.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[39]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 26.08.08 16:30
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, skeptik_, Вы писали:


E>>>>>Если вы не проверяете аргументы max_element всегда и не проверяете результат max_element всегда, тогда у вас нет никаких гарантий того, что однажды вы не разыменуете некорректный итератор.

ЮЖ>>>>Достаточно _одной_ проверки.

E>>>Это какой?


_>>Например вот такой:


_>>
_>>template< typename RandomAccessIterator >
_>>void selection_sort( RandomAccessIterator first, RandomAccessIterator last )
_>>{
_>>    while( first < --last ) // <-- max_element никогда не будет вызван с пустым интервалом
_>>        std::iter_swap( last, std::max_element( first, last + 1 ) );
_>>}

_>>


E>Ага. Во всех C++ программах функция std::max_element вызывается всего в одном месте -- в selection_sort. И именно это использование max_element абсолютно безопасно.


Что за бред? Я вроде русским языком написал: например. В других местах она тоже не в вакууме вызывается. Я тут провел поиск по диску, нашёл вот max_element например в двух местах в Crypto 5.1, так там условие непустоты интервала является предусловием уже для вызывающей функции.
Re[40]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 16:32
Оценка:
Здравствуйте, skeptik_, Вы писали:

E>>Ага. Во всех C++ программах функция std::max_element вызывается всего в одном месте -- в selection_sort. И именно это использование max_element абсолютно безопасно.


_>Что за бред? Я вроде русским языком написал: например. В других местах она тоже не в вакууме вызывается. Я тут провел поиск по диску, нашёл вот max_element например в двух местах в Crypto 5.1, так там условие непустоты интервала является предусловием уже для вызывающей функции.


Я тоже русским языком написал:

2. Условия меняются. Либо контракты обновляют поставщики библиотек в новых версиях. Либо новые версии ПО начинают несоблюдать контракты.

То, что сейчас применение max_element в Crypto безопасно может оказаться не так в какой-то следующей версии.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[37]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 26.08.08 17:09
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Юрий Жмеренецкий, Вы писали:


E>>>Если вы не проверяете аргументы max_element всегда и не проверяете результат max_element всегда, тогда у вас нет никаких гарантий того, что однажды вы не разыменуете некорректный итератор.

ЮЖ>>Достаточно _одной_ проверки.

E>Это какой?

E>Я смею утверждать, что _обычный_ программист не будет писать перед вызовом существующего max_element пустоту последовательности. И не будет проверять возвращаемое значение. Он [b]уверен[b], что:
E>a) либо последовательность не пуста;
E>b) либо любое возвращаемое max_element значение удовлетворяет текущему контексту (см. пример skeptika_ с использованием max_element в функции сортировки).
Уверенность не может быть сама по себе. Она "выводится" из предусловий — где-то компилятором(checked_value), где-то документацией + assert + unit test для него в debug'e.

E>Его вера, иногда, может быть ошибочна. В этих случаях есть шанс получить битую память и наведенную ошибку.

E>Какая _одна_ проверка способна избавить разработчика от подобной ситуции?
Одна — в смысле единственная, может быть и две, но выполнены они будут один раз.
Может быть непосредственно перед вызовом max_element, может быть выше по стеку.

ЮЖ>>>>здесь

ЮЖ>>>>И также для постусловий. Плюс ослабление/усиление.

E>>>В C++ ничего этого нет. Нет никакой поддержки инваринтов/пред-/постусловий со стороны Run-Time.

ЮЖ>>Из отсутствия поддержки инвариантов не следует что в С++ их нет.
E>Точно так же можно заявить, что из отсутствия поддержки ООП в C не следует, что в C нет ООП.

Вобщем, опять этот плохой С++? Да, нет поддержки со стороны run-time(assert даже не предлагаю =) ). А какая она должна быть ? Во-первых сами пред/пост условия писать где-то надо, типы исключений указывать надо. Для вложенных вызовов функций, для которых не доступен код, придется воскрешать throw-spec.
Имхо, проще это статически в типах выразить(по возможности).

E>>>Разработчики могут только учитывать неформальные спецификации из документации, но не имеют никаких инструментов для проверки своих ожиданий во время исполнения.

...
E>С этим согласен. Но это не имеет никакого отношения к обсуждавшемуся дизайну std::max_element.
Это имеет отношение к фразе про проверку ожиданий.

E>>>А это означает, что если программа скомпилирована с сохранением предусловий, то функция f2 не будет вызвана с неправильными аргументами вне зависимости от того, знал ли программист о нарушении контракта или не знал.


ЮЖ>>А программисту сложно почитать документацию и выяснить контракт? Или он будет наугад аргументы подставлять, авось заведется?

E>1. Программисты ошибаются. Даже если читают документацию. А читают они ее не так уж часто, иначе не появилось бы выражение RTFM.
Значит они от своих ошибок маленький feedback получают. Ну возникло исключение InvalidParam, и все хорошо. Развращает такой подход... Вот если бы перевелось не туда миллионов 10$, или спутник бы упал, тогда по три раза читать будут.

E>2. Условия меняются.

Да они всегда меняются...

E>Либо контракты обновляют поставщики библиотек в новых версиях.

Это если им не интересна backward compatibility, или происходит "устаканивание" интерфейсов, т.е. библиотека еще сырая.

E>Либо новые версии ПО начинают несоблюдать контракты. Вспомните Ариан 5 -- очень хороший пример эволюции ПО, когда корректностью контрактов в новом окружении для старого ПО никто не озадачился.

Вот это "хороший" feedback для всей отрасли...

E>>>Нет в C++ даже самых обыкновенных.

ЮЖ>>Можно услышать определение "самых обыкновенных" ?

E>Вот, например. Более полно о контрактах лучше читать толмуд Бертрана Мейера.


По ссылке:
Хотя Бертран Мейер советует писать так, чтобы программа работала вообще без каких-либо проверок в финальной версии.

Вот он, assert во всей красе...


PS: мое имхо
Автор: Юрий Жмеренецкий
Дата: 12.04.08
про Design by Contract. Я эту ссылку уже давал, но судя по некоторым вопросам она осталась незамеченной.
Re[38]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.08.08 20:27
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>PS: мое имхо
Автор: Юрий Жмеренецкий
Дата: 12.04.08
про Design by Contract. Я эту ссылку уже давал, но судя по некоторым вопросам она осталась незамеченной.


Я просто не согласен с озвученной в первом посте той темы мнением. А спорить на тему DbC нет возможности.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[25]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.08.08 07:20
Оценка:
Здравствуйте, eao197, Вы писали:


E>Еще раз: программисты ошибаются. ОШИБАЮТСЯ!

Пока что вся эта дискуссия показывает недостатки плюсов как языка по сравнению с полноценным ФП.

Если я правильно понимаю, на ФЯ написать некорректную реализацию max_element практически нереально.
Потому, что непустые последовательности там радикально отличаются от пустых. В итоге программист вынужден явно обработать все случаи:0, 1, и больше элементов.

А все эти припрыгивания с лишним сравнением (которое предположительно снизит производительность для вырожденных случаев) и надеждой на корректную обработку неочевидных контрактов — соревнования в эквилибристике.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[26]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 27.08.08 07:30
Оценка:
Здравствуйте, Sinclair, Вы писали:

E>>Еще раз: программисты ошибаются. ОШИБАЮТСЯ!

S>Пока что вся эта дискуссия показывает недостатки плюсов как языка по сравнению с полноценным ФП.

Я в этой дискуссии пытаюсь понять вот что: почему C++ники отвергают тот факт, что в C++ возможны ошибки, которые могут приводить к неприятным и неочевидным багам (порча памяти и, как следствие, наведенная ошибка в другом месте)? А уже как следствие этого, почему им не нравится решение, которое от таких ошибок защищает.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 27.08.08 07:55
Оценка: +1 -1 :)
Здравствуйте, eao197, Вы писали:

E>Я в этой дискуссии пытаюсь понять вот что: почему C++ники отвергают тот факт, что в C++ возможны ошибки, которые могут приводить к неприятным и неочевидным багам (порча памяти и, как следствие, наведенная ошибка в другом месте)? А уже как следствие этого, почему им не нравится решение, которое от таких ошибок защищает.

Потому что эквилибристика — их вторая натура.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[28]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 27.08.08 08:00
Оценка: +1 :))
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, eao197, Вы писали:


E>>Я в этой дискуссии пытаюсь понять вот что: почему C++ники отвергают тот факт, что в C++ возможны ошибки, которые могут приводить к неприятным и неочевидным багам (порча памяти и, как следствие, наведенная ошибка в другом месте)? А уже как следствие этого, почему им не нравится решение, которое от таких ошибок защищает.

S>Потому что эквилибристика — их вторая натура.

Не их -- наша!
C++ forever!!!


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 27.08.08 08:35
Оценка:
Здравствуйте, eao197, Вы писали:

E>Я в этой дискуссии пытаюсь понять вот что: почему C++ники отвергают тот факт, что в C++ возможны ошибки, которые могут приводить к неприятным и неочевидным багам (порча памяти и, как следствие, наведенная ошибка в другом месте)? А уже как следствие этого, почему им не нравится решение, которое от таких ошибок защищает.


Это тебе только кажется. Твой подход имеет право на жизнь и даже в стандартной библиотеке , но выло выбрано другое решенеи. Какие использовались критерии я уже говорил. Плохо ли выбранное решение ? думаю что нет.

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

Т.е. Это "странное" отношение к дизайну , некое религиозное. У рассмотренных (и у ваших) решений есть свои преимущества и недостатки.


P.S. Меня кстати в стандартной библиотеке немного удивляет отсутствие класса Range который инкапсулирует пару итераторов. С таким классом валидация диапазонов может происходить на этапе конструирования.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[28]: Почему преждевременная оптимизация - корень всех зол
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 27.08.08 08:37
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>[] для полного низкоуровнего контроля существуют другие языки []


Какие?
Re[29]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 27.08.08 08:47
Оценка:
Здравствуйте, Alxndr, Вы писали:

M>>[] для полного низкоуровнего контроля существуют другие языки []


A>Какие?


Жаба ? С шарп ?
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[30]: Почему преждевременная оптимизация - корень всех зол
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 27.08.08 09:01
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Здравствуйте, Alxndr, Вы писали:


M>>>[] для полного низкоуровнего контроля существуют другие языки []


A>>Какие?


M>Жаба ? С шарп ?


Вероятно, имелся в виду "контроль исполнения"?
Re[38]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 27.08.08 09:58
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Уверенность не может быть сама по себе. Она "выводится" из предусловий — где-то компилятором(checked_value), где-то документацией + assert + unit test для него в debug'e.


Ничего из этого не может гарантировать отсутствие ошибок в программе.

ЮЖ>Одна — в смысле единственная, может быть и две, но выполнены они будут один раз.

ЮЖ>Может быть непосредственно перед вызовом max_element, может быть выше по стеку.

Если выше по стеку, то сложно этой проверке доверять после проведения рефакторингов.

E>>>>В C++ ничего этого нет. Нет никакой поддержки инваринтов/пред-/постусловий со стороны Run-Time.

ЮЖ>>>Из отсутствия поддержки инвариантов не следует что в С++ их нет.
E>>Точно так же можно заявить, что из отсутствия поддержки ООП в C не следует, что в C нет ООП.

ЮЖ>Вобщем, опять этот плохой С++? Да, нет поддержки со стороны run-time(assert даже не предлагаю =) ). А какая она должна быть ?


Посмотрите на Eiffel. Ну или на D, хотя там в постусловиях нет old, если не ошибаюсь.

ЮЖ>типы исключений указывать надо.


Не, типы исключений не надо. А вот nothrow-спецификатор очень бы не помешал.

E>>1. Программисты ошибаются. Даже если читают документацию. А читают они ее не так уж часто, иначе не появилось бы выражение RTFM.

ЮЖ>Значит они от своих ошибок маленький feedback получают. Ну возникло исключение InvalidParam, и все хорошо. Развращает такой подход... Вот если бы перевелось не туда миллионов 10$, или спутник бы упал, тогда по три раза читать будут.

Ариан 5 взорвался на старте. А спустя несколько лет Mars Climate Orbiter потерпел крушение по аналогичным причинам (неправильное переиспользование кода). Так что не похоже, что даже крах спутников учит программистов читать документацию.

E>>Либо контракты обновляют поставщики библиотек в новых версиях.

ЮЖ>Это если им не интересна backward compatibility

Бывает и так.

E>>Либо новые версии ПО начинают несоблюдать контракты. Вспомните Ариан 5 -- очень хороший пример эволюции ПО, когда корректностью контрактов в новом окружении для старого ПО никто не озадачился.

ЮЖ>Вот это "хороший" feedback для всей отрасли...

См. выше.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[31]: Почему преждевременная оптимизация - корень всех зол
От: minorlogic Украина  
Дата: 27.08.08 10:18
Оценка:
Здравствуйте, Alxndr, Вы писали:

A>Вероятно, имелся в виду "контроль исполнения"?


Я имелл ввиду очень узкий контекст , а именно обращение к несуществующему элементу в массиве
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[10]: Итератор
От: SergeCpp Россия http://zoozahita.ru
Дата: 27.08.08 11:10
Оценка:
Здравствуйте, skeptik_!

_>Да пожалуйста. Разница с msvc 9.0 в том, что у них условие заключает в себя цикл, а у меня стоит в начале (это я уже потом посмотрел)

_>
_>template< typename ForwardIterator >
_>ForwardIterator max( ForwardIterator first, ForwardIterator last )
_>{
_>    if ( first == last )
_>        return first;

_>    ForwardIterator result = first;
_>    while( ++first != last )
_>        if ( *result < *first )
_>            result = first;
_>    return result;
_>}
_>

А если на входе first > last?

Или эти итераторы по кольцу гуляют (++first)?
http://zoozahita.ruБездомные животные Екатеринбурга ищут хозяев
Re[11]: Итератор
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 27.08.08 11:15
Оценка: +2
Здравствуйте, SergeCpp, Вы писали:

SC>А если на входе first > last?


От этого так же сложно защититься, как и от того, что first и last принадлежат _разным_ последовательностям.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[26]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 27.08.08 11:59
Оценка: 4 (1)
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, eao197, Вы писали:


E>>Еще раз: программисты ошибаются. ОШИБАЮТСЯ!

S>Пока что вся эта дискуссия показывает недостатки плюсов как языка по сравнению с полноценным ФП.
Мне тоже яблоки больше груш нравятся.

S>Если я правильно понимаю, на ФЯ написать некорректную реализацию max_element практически нереально.

S>Потому, что непустые последовательности там радикально отличаются от пустых. В итоге программист вынужден явно обработать все случаи:0, 1, и больше элементов.
Это и есть предусловия.

S>А все эти припрыгивания с лишним сравнением (которое предположительно снизит производительность для вырожденных случаев)

Производительность здесь вообще не является главным критерием(это скорее бонус).

Во-первых, каждую проверку необходимо поддерживать. Если сегодня есть 'a > 0', а завтра нужно сделать 'a > 1', то необходимо править _все_ вхождения.

Во-вторых, это банальная логика — прежде чем прыгнуть в басейн, я проверю уровень воды, а вы прыгните в любом случае, плюс необходимо будет добавить реакцию на исключение — "прыгнуть не получилось". Зачем ? А потом огрмное количство кода занимается обработкой таких вот фиктивных ошибок. А ведь этот код опять же, надо поддерживать.

Да, бывают такие места где проверить не получается(или это сложно) — там приходится прыгать.

eao197 пропагандирует defensive programming, где все(функции) друг другу не доверяют. Я, в принципе, применяю этот же подход, только более "крупномасштабно": функции разростаются до неких trusted regions, где данные могут существовать только если удовлетворяют некоторым условиям, а проверки происходят на их границах. Это снижает количество проверок, локализует места появления багов, делает логику более чистой, но за это необходимо платить некоторую цену — в данном случае соблюдение контрактов. Где-то помогает типизация, где-то тестирование. С++ не навязывает своих решений.

S>и надеждой на корректную обработку [b]неочевидных контрактов[b] — соревнования в эквилибристике.

Вот кому неочевидно, тому остается только надеятся.
Re[39]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 27.08.08 12:16
Оценка:
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Уверенность не может быть сама по себе. Она "выводится" из предусловий — где-то компилятором(checked_value), где-то документацией + assert + unit test для него в debug'e.


E>Ничего из этого не может гарантировать отсутствие ошибок в программе.

Использование DbC позволяет уменьшить количество потенциальних мест их появления.

ЮЖ>>Одна — в смысле единственная, может быть и две, но выполнены они будут один раз.

ЮЖ>>Может быть непосредственно перед вызовом max_element, может быть выше по стеку.

E>Если выше по стеку, то сложно этой проверке доверять после проведения рефакторингов.

Если рефакторинг ломает некоторые контракты, то все места их "использования" должны быть проверены каким-либо способом.

ЮЖ>>Вобщем, опять этот плохой С++? Да, нет поддержки со стороны run-time(assert даже не предлагаю =) ). А какая она должна быть ?


E>Посмотрите на Eiffel. Ну или на D, хотя там в постусловиях нет old, если не ошибаюсь.

Для несколькх языков смотрел, мне интересно как это должно выглядеть в С++.

ЮЖ>>типы исключений указывать надо.

E>Не, типы исключений не надо. А вот nothrow-спецификатор очень бы не помешал.
Что должно происходитить при нарушениях контракта ?

E>Ариан 5 взорвался на старте. А спустя несколько лет Mars Climate Orbiter потерпел крушение по аналогичным причинам (неправильное переиспользование кода). Так что не похоже, что даже крах спутников учит программистов читать документацию.

Не все могут учиться на чужом опыте...
Re[28]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 27.08.08 12:21
Оценка: :)
Здравствуйте, minorlogic, Вы писали:

M>P.S. Меня кстати в стандартной библиотеке немного удивляет отсутствие класса Range который инкапсулирует пару итераторов.


Отсутствие чего-либо в стандартной библиотеке удивляет наверное всех.
Re[40]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 27.08.08 12:24
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Использование DbC позволяет уменьшить количество потенциальних мест их появления.


Может. Но вот нет в C++ DbC. Поэтому использование defensive programming для библиотек мне представляется более надежной техникой.

E>>Если выше по стеку, то сложно этой проверке доверять после проведения рефакторингов.

ЮЖ>Если рефакторинг ломает некоторые контракты, то все места их "использования" должны быть проверены каким-либо способом.

Вспоминается чья-то мудрость: тесты могут показать наличие ошибок в программе, но не могут гарантировать их отсутствие.
Поэтому даже использование unit-тестирования и regression-тестирования не может доказать, что рефакторинг не привнес в программу новых ошибок.

ЮЖ>Для несколькх языков смотрел, мне интересно как это должно выглядеть в С++.


В C++ этого уже не будет. Если только не использовать каких-нибудь внешних нестандартных генераторов/преобразователей кода.

E>>Ариан 5 взорвался на старте. А спустя несколько лет Mars Climate Orbiter потерпел крушение по аналогичным причинам (неправильное переиспользование кода). Так что не похоже, что даже крах спутников учит программистов читать документацию.

ЮЖ>Не все могут учиться на чужом опыте...

О том и речь.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[41]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 27.08.08 13:07
Оценка:
Здравствуйте, eao197, Вы писали:

E>Поэтому использование defensive programming для библиотек мне представляется более надежной техникой.

Уже теплее. А внутри библиотек ?

E>>>Если выше по стеку, то сложно этой проверке доверять после проведения рефакторингов.

ЮЖ>>Если рефакторинг ломает некоторые контракты, то все места их "использования" должны быть проверены каким-либо способом.

E>Вспоминается чья-то мудрость: тесты могут показать наличие ошибок в программе, но не могут гарантировать их отсутствие.

E>Поэтому даже использование unit-тестирования и regression-тестирования не может доказать, что рефакторинг не привнес в программу новых ошибок.
Есть такое. Но чем тогда поможет использование defensive programming и поддержка DbC на уровне языка(не использование, а именно поддержка) ?
Ничем...

ЮЖ>>Для несколькх языков смотрел, мне интересно как это должно выглядеть в С++.

E>В C++ этого уже не будет.
Подвижки были:
Proposal to add Design by Contract to C++
Proposal to add Contract Programming to C++
Re[28]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 27.08.08 14:42
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>P.S. Меня кстати в стандартной библиотеке немного удивляет отсутствие класса Range который инкапсулирует пару итераторов. С таким классом валидация диапазонов может происходить на этапе конструирования.


Papers n1871, n2068 от Thorsten Ottosen -- planned for a future TR.
Re[42]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 27.08.08 15:04
Оценка: +1
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>>>Для несколькх языков смотрел, мне интересно как это должно выглядеть в С++.

E>>В C++ этого уже не будет.
ЮЖ>Подвижки были:
ЮЖ>Proposal to add Design by Contract to C++
ЮЖ>Proposal to add Contract Programming to C++

Уже два года как ведутся в рубрике "Not ready for C++0x, but open to resubmit in future".
Re[27]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.08.08 03:09
Оценка: 2 (1)
Здравствуйте, Юрий Жмеренецкий, Вы писали:

Ю
S>>Если я правильно понимаю, на ФЯ написать некорректную реализацию max_element практически нереально.
S>>Потому, что непустые последовательности там радикально отличаются от пустых. В итоге программист вынужден явно обработать все случаи:0, 1, и больше элементов.
ЮЖ>Это и есть предусловия.
Ну, на самом деле не совсем. Это скорее инварианты. Просто с точки зрения ФП, списки бывают двух существенно разных типов: пустые — [], и сконструированные из [head, tail].
Если программист хочет, чтобы max принимала только второй вид списков, то компилятор защитит его от передачи пустого списка.
Дальше, когда программист попытается сделать рекурсию, ему компилятор не даст напрямую сделать max(tail), потому что tail не гарантирован от []. Значит, придется вручную разрулить ситуацию при помощи pattern matching.

Поскольку список — immutable, я как-то стесняюсь назвать такую типизацию предусловием.
С тем же успехом можно считать, что ссылка в С++ — это указатель с предусловием "не равен NULL".


ЮЖ>Производительность здесь вообще не является главным критерием(это скорее бонус).

Если производительность не является главным критерием, то все пред, пост и прочие условия явно пишутся в коде в виде ассертов.
Но почему-то хардкорные плюсовики со страшной силой критикуют проверку диапазонов на каждый чих в управляемых языках.
ЮЖ>Во-первых, каждую проверку необходимо поддерживать. Если сегодня есть 'a > 0', а завтра нужно сделать 'a > 1', то необходимо править _все_ вхождения.
Вот это мне непонятно. Вхождения чего? Мы говорим о повторно используемой функции и об уровне ее доверия по отношению к вызывающему коду.
ЮЖ>Во-вторых, это банальная логика — прежде чем прыгнуть в басейн, я проверю уровень воды, а вы прыгните в любом случае, плюс необходимо будет добавить реакцию на исключение — "прыгнуть не получилось". Зачем ?
У вас правильные выводы из неправильной логики. Понимаете, функция прыжка — одна, а функций, которые ее используют — много. Заложить проверку в функцию прыжка — гарантировать определенное поведение. Вынуждать делать проверку всех клиентов — не иметь никаких гарантий.
ЮЖ>А потом огрмное количство кода занимается обработкой таких вот фиктивных ошибок. А ведь этот код опять же, надо поддерживать.
Никогда не видел ситуации, где бы обработкой занималось "огромное количество кода". Как правило, стратегий обработки ошибок значительно меньше, чем самих ошибок. Ну природа так устроена. Поэтому классификация исключений — вполне себе нормальный метод структурирования. Если в каком-то конкретном случае обработка ошибочной ситуации происходит прямо по месту вызова, то никто не обязывает делать catch — проверяйте бассейн перед прыжком. Более того, в простых случаях компилятор даже может заинлайнить код, устранить избыточную проверку и выбросить тот фрагмент, который бы бросал исключение в случае ошибки.
Вот, к примеру, в дотнете точно известно, что происходит при разыменовании нулевого указателя: NullReferenceException. Но при этом catch(NullReferenceException) в природе не встречается.
Зато нормой является на границе "региона доверия" проверить аргументы и выбросить ArgumentNullException.
Важно, что эта норма — не обязательная. Если нулевой аргумент будет передан в незащищенную функцию, сценарий будет практически таким же — с той разницей, что место обнаружения может оказаться далеко от места пресупления.
Но то, что вы предлагаете — это UB вместо NullReferenceException, и приятная возможность проверить аргументы превращается в обязанность.

ЮЖ>Да, бывают такие места где проверить не получается(или это сложно) — там приходится прыгать.


ЮЖ>eao197 пропагандирует defensive programming, где все(функции) друг другу не доверяют. Я, в принципе, применяю этот же подход, только более "крупномасштабно": функции разростаются до неких trusted regions, где данные могут существовать только если удовлетворяют некоторым условиям, а проверки происходят на их границах.

Вот это, разумеется, правильный ответ. Но никаких средств поддержки таких регионов в С++ нет. Максимум защиты — это выделение контракта в отдельный класс, занимающийся ассертами и передачей управления приватной реализации, которая уже работает без проверок.
ЮЖ>Это снижает количество проверок, локализует места появления багов, делает логику более чистой, но за это необходимо платить некоторую цену — в данном случае соблюдение контрактов. Где-то помогает типизация, где-то тестирование. С++ не навязывает своих решений.

S>>и надеждой на корректную обработку [b]неочевидных контрактов[b] — соревнования в эквилибристике.

ЮЖ>Вот кому неочевидно, тому остается только надеятся.
Ну, я бы просто предпочел перейти на язык программирования, который позволяет заменить надежды гарантиями. Потому, что понятие "очевидности" не распространяется на программы размером больше 1000 строк.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[42]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 28.08.08 08:54
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

E>>Поэтому использование defensive programming для библиотек мне представляется более надежной техникой.

ЮЖ>Уже теплее. А внутри библиотек ?

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

Но разговор-то шел о max_element, который как раз располагается на границе.

E>>Поэтому даже использование unit-тестирования и regression-тестирования не может доказать, что рефакторинг не привнес в программу новых ошибок.

ЮЖ>Есть такое. Но чем тогда поможет использование defensive programming и поддержка DbC на уровне языка(не использование, а именно поддержка) ?
ЮЖ>Ничем...

Ну что тут сказать. У меня совершенно противоположное мнение.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[28]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 28.08.08 14:30
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Юрий Жмеренецкий, Вы писали:


S>Ю

S>>>Если я правильно понимаю, на ФЯ написать некорректную реализацию max_element практически нереально.
S>>>Потому, что непустые последовательности там радикально отличаются от пустых. В итоге программист вынужден явно обработать все случаи:0, 1, и больше элементов.
ЮЖ>>Это и есть предусловия.
S>Ну, на самом деле не совсем. Это скорее инварианты.
Согласен, я сначала хотел о другом написать, а выделение забыл убрать.

ЮЖ>>Производительность здесь вообще не является главным критерием(это скорее бонус).

S>Если производительность не является главным критерием, то все пред, пост и прочие условия явно пишутся в коде в виде ассертов.
Про постусловия мы пока не говорим, а предусловия — да, выражаются в виде ассертов(с точки зрения С++).

ЮЖ>>Во-первых, каждую проверку необходимо поддерживать. Если сегодня есть 'a > 0', а завтра нужно сделать 'a > 1', то необходимо править _все_ вхождения.

S>Вот это мне непонятно. Вхождения чего?
"проверку диапазонов на каждый чих" по стеку. Ведь при подходе, когда каждая функция не доверяет никому приходится проверять все предусловия ?


ЮЖ>>Во-вторых, это банальная логика — прежде чем прыгнуть в басейн, я проверю уровень воды, а вы прыгните в любом случае, плюс необходимо будет добавить реакцию на исключение — "прыгнуть не получилось". Зачем ?

S>У вас правильные выводы из неправильной логики. Понимаете, функция прыжка — одна, а функций, которые ее используют — много.
Посмотрите с другой стороны: не со стороны функций, а со стороны данных к которым она применяется. Ведь проверять уровень воды можно не только перед прыжком. Я даже не пойду в бассейн, если он закрыт. Проверка в другом месте: Предже чем бассейн будет открыт для посещений в нем необходимо проверить уровень воды.

S>Заложить проверку в функцию прыжка — гарантировать определенное поведение.

Сама по себе попытка прыжка в пустой бассейн — не есть определенное поведение. Вы создаете фиктивное поведение для заведомо ошибочных ситуаций.

S>Вынуждать делать проверку всех клиентов — не иметь никаких гарантий.

Проще гарантировать наличие полного бассейна(сокращается количество мест, из-за ошибок в которых может возникнуть UB), чем выполнять проверки каждый раз при попытке прыгнуть в него.

ЮЖ>>А потом огрмное количство кода занимается обработкой таких вот фиктивных ошибок. А ведь этот код опять же, надо поддерживать.

S>Никогда не видел ситуации, где бы обработкой занималось "огромное количество кода". Как правило, стратегий обработки ошибок значительно меньше, чем самих ошибок.
Чем дальше оттягивается момент проверок, тем больше происходит изменений состояния, которые необходимо откатить. Это лишний код("возвращаться из бассейна домой, если он закрыт").

S>Ну природа так устроена. Поэтому классификация исключений — вполне себе нормальный метод структурирования.

Классификация исключений здесь не играет какой-либо значимой роли.

S>Вот, к примеру, в дотнете точно известно, что происходит при разыменовании нулевого указателя: NullReferenceException. Но при этом catch(NullReferenceException) в природе не встречается.

Такие категоричные заявления опровергаются одним контпримером =)

S>Зато нормой является на границе "региона доверия" проверить аргументы и выбросить ArgumentNullException.

S>Важно, что эта норма — не обязательная. Если нулевой аргумент будет передан в незащищенную функцию, сценарий будет практически таким же — с той разницей, что место обнаружения может оказаться далеко от места пресупления.
Разница может быть огромной. Необходимы гарантии того, что выполняемый код не наломает дров.
Да и для откатов может потребоваться значительной количество любых ресурсов. Эта цена одной проверки выше.

S>Но то, что вы предлагаете — это UB вместо NullReferenceException,

Опять двадцать пять. Еще раз: так или иначе я проверю все аргументы которым я не доверяю. На тех же границах регионов. Этим я гарантирую что везеде где они используются они удовлетворяют предусловиям. Я могу дать гарантии даже для несуществующих компонентов что они получат валидные данные. А у вас по системе будут гулять пустые бассейны. И любой кто их использует должен будет их проверять.

S>и приятная возможность проверить аргументы превращается в обязанность.

Это маленькая цена по сравнению с преимуществами, которые дает эта возможность.

ЮЖ>>... Но никаких средств поддержки таких регионов в С++ нет.

Сговорились с eao197 ?)

S>Максимум защиты — это выделение контракта в отдельный класс, занимающийся ассертами и передачей управления приватной реализации, которая уже работает без проверок.

Так иногда и делается, только вот ассерты != проверки !

S>>>и надеждой на корректную обработку [b]неочевидных контрактов[b] — соревнования в эквилибристике.

ЮЖ>>Вот кому неочевидно, тому остается только надеятся.
S>Ну, я бы просто предпочел перейти на язык программирования, который позволяет заменить надежды гарантиями.
Аха, сначала обеспечиваем наличие в системе пустых бассейнов, в которые можно прыгать, а потом гарантируем что в них никто не прыгнет. Зашибись. И для этого еще требуем поддержку от языка... Это борьба с симптомами, а не с причиной.
Re[43]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 28.08.08 14:35
Оценка: +1
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Юрий Жмеренецкий, Вы писали:


E>>>Поэтому использование defensive programming для библиотек мне представляется более надежной техникой.

ЮЖ>>Уже теплее. А внутри библиотек ?

E>А внутри библиотек -- это уже тема отдельного разговора. Сам я редко использую defensive programming внутри библиотеки.


E>Но разговор-то шел о max_element, который как раз располагается на границе.

В этом случае придется защищаться и от того что 'first > last' и от того что итераторы принадлежат разным доменам.
Здесь я не согласен с тем что max_element располагается на границе.
Re[9]: Почему твой вопрос глупый...
От: Erop Россия  
Дата: 29.08.08 16:20
Оценка:
Здравствуйте, minorlogic, Вы писали:

M>Интереснее было бы если бы вы привели тут итоговый код

Ничего интересного. Ты не привёл точной спецификации.
Например, ты не укзал где искать, что делать, если множество, где искать, пустое, не укзал что возвращаем -- сам максимум или какую-то ссылку/индекс/итератор максимального элемента, если второе, то что делаем, если максимум достигается не на одном элементе. Ну и т. д.

Почему я этого требую? Да потому, что как-то кто-то тут уже предлагал такие "тесты". Всего вышеоговоренного не оговорил, в результате люди написали ожну функцию, а "экзаменатор" сделал умный вид, и сказал, что хотел совсем другую
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[26]: А зачем проверять после?
От: Erop Россия  
Дата: 29.08.08 16:33
Оценка: +3
Здравствуйте, minorlogic, Вы писали:

M>Проверять или нет возвращаемое значение решает програмист , есть очень много ситуаций когда заранее известно что массив не пустой.


А когда и зачем надо звать max_element если массив может быть пуст? Зачем проверять факт пустоты массива после вызова max_element, а не до?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Почему твой вопрос глупый...
От: minorlogic Украина  
Дата: 29.08.08 18:07
Оценка:
Здравствуйте, Erop, Вы писали:

E>Почему я этого требую? Да потому, что как-то кто-то тут уже предлагал такие "тесты". Всего вышеоговоренного не оговорил, в результате люди написали ожну функцию, а "экзаменатор" сделал умный вид, и сказал, что хотел совсем другую


Это не экзамен, демонстрационный пример. Жаль что ты не увидел то что я пытался донести.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[27]: А зачем проверять после?
От: minorlogic Украина  
Дата: 29.08.08 18:07
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, minorlogic, Вы писали:


M>>Проверять или нет возвращаемое значение решает програмист , есть очень много ситуаций когда заранее известно что массив не пустой.


E>А когда и зачем надо звать max_element если массив может быть пуст? Зачем проверять факт пустоты массива после вызова max_element, а не до?


И это тоже может выбирать програмист.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[19]: Почему преждевременная оптимизация - корень всех зол
От: gear nuke  
Дата: 30.08.08 14:12
Оценка:
Здравствуйте, eao197, Вы писали:

E>Мне сложно назвать мегаудачным решение, при котором миллионы пользователей вынуждены проверять условие, которое мог проверить и обработать один разработчик max_element. Поскольку мне кажется очень странным использование max_element в стиле:

E>
E>std::vector< int > v;
E>... какие-то действия, которые, по мнению разработчика, заполняют v...
E>std::vector< int >::iterator m = std::max_element( v.begin(), v.end() );
E>if( m == v.end() )
E>  // Что за оно вааще?!!
E>

По-моему, если учесть выделенное, то пост-проверка не нужна. Либо кидать исключение при невозможности заполнения, либо проверять v.empty() перед поиском.

std::max_element раелизовано вполне в духе остальных STL алгоритмов, где за валидностью диапазона итераторов приходится следить пользователю (не только пустые диапазоны, но и принадлежность итераторов разным последовательностям...)

Возвращаясь к предложенному тобой набору
Автор: eao197
Дата: 23.08.08
, логичнее (?) иметь пару:
template<class Container> max_element(Container c);
template<class Container> max_element(Container c, const std::nothrow_t&);

Что ж поделать, STL не угадал наперёд путь развития C++, исключения и накопление опыта работы над ошибками... Кстати именно этот
Автор: eao197
Дата: 22.08.08
случай во время проектирования был вообще исключен (printf? дык, и уровень пользователей таких вещей видимо был другой).
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[20]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 30.08.08 20:48
Оценка:
Здравствуйте, gear nuke, Вы писали:


GN>Возвращаясь к предложенному тобой набору
Автор: eao197
Дата: 23.08.08
, логичнее (?) иметь пару:

GN>
template<class Container> max_element(Container c);
GN>template<class Container> max_element(Container c, const std::nothrow_t&);

GN>Что ж поделать, STL не угадал наперёд путь развития C++, исключения и накопление опыта работы над ошибками...

А теперь попробуй применить твою функцию в данном коде:
template< typename RandomAccessIterator >
void selection_sort( RandomAccessIterator first, RandomAccessIterator last )
{
    while( first < --last )
        std::iter_swap( last, std::max_element( first, last + 1 ) );
}

Хотя алгоритмы в виде template<class Container> void some_algo( Container& ); зачастую именно то, что нужно в конечном коде, они совершенно неприменимы для комбинирования с другими алгоритмами для написания новых алгоритмов. Поэтому надо было предлагать оба варианта, и интервальный, и контейнерный. Что впрочем буст и делает.
Re[3]: Почему преждевременная оптимизация - корень всех зол?
От: jazzer Россия Skype: enerjazzer
Дата: 30.08.08 21:39
Оценка: +1
Здравствуйте, Кэр, Вы писали:

Кэр>Здравствуйте, jazzer, Вы писали:


J>>если тормоза уже заметны, то, очевидно, это уже не преждевременная оптимизация


Кэр>Осталось ответить на вопрос — как они заметны? "На глазок"?


Да, "на глазок".
Поэтому что у пользователя будет глазок, очень похожий на твой, а тебе совсем не хочется, чтобы твои пользователи на весь мир о твоем софте кричали, что он тормозной, если, конечно, ты не Microsoft

Так что это ни разу не преждевременная оптимизация, а самая что ни на есть обычная.

А профайлер только поможет найти конкретное место, которое надо оптимизировать, не более того.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[28]: Программирование -- деятельность прагматическая? :)
От: Erop Россия  
Дата: 30.08.08 23:44
Оценка:
Здравствуйте, minorlogic, Вы писали:

E>>А когда и зачем надо звать max_element если массив может быть пуст? Зачем проверять факт пустоты массива после вызова max_element, а не до?

M>И это тоже может выбирать програмист.
Прости, конечно, но я всё равно не понял ЗАЧЕМ?...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[21]: Почему преждевременная оптимизация - корень всех зол
От: gear nuke  
Дата: 30.08.08 23:57
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>Поэтому надо было предлагать оба варианта, и интервальный, и контейнерный.


Именно это я и предлагал, извини, что не понятно.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[11]: А ты понятнее объясняй и сам внимательнее читай собе
От: Erop Россия  
Дата: 31.08.08 13:13
Оценка: 18 (1) +1
Здравствуйте, minorlogic, Вы писали:

M>Это не экзамен, демонстрационный пример. Жаль что ты не увидел то что я пытался донести.

Видимо пример плохой?

А вообщето тебе написали, IMHO, вполне нормальное решение с assert. Оно решает "проблему пустой коллекции", по крайней мере не хуже твоего решения. На мой вкус, так вообе лучше. Ну а ты стал с умным видом утвержать, что это де такая ошибка, и сякая ошибка.

Хотя мне, например, кажется, что
1) Специальные возврааемые значения и
2) Специальные начения входных параметров — это если и не ошибки проектирования, то точно уж кривизна диайна.

И что я вижу? Что то решение, которое ты выаёшь за эталон, действует так: "возвраает итратор максимального элемента, либо возвращает end, если диапазон пуст". А решение, которое ты счёл неправильным, устроено так: "возвращает максимальный элемент непустой коллекции".
IMHO нет специального случая на входе и специального значения на выходе...

В любом случае ты так и не ответил чем код
IT res = max_element( beg, end );
if( res != end ) {
    process( res );
}
лучше кода
if( beg != end ) {
    process( max_element( beg, end ) ); 
}


Тем что в первом варианте лишняя проверка выполняется и логика проверки корректности входных данных вывернутая?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[21]: А в чём проблемы?
От: Erop Россия  
Дата: 31.08.08 13:22
Оценка:
Здравствуйте, skeptik_, Вы писали:

_>А теперь попробуй применить твою функцию в данном коде:

_>
_>template< typename RandomAccessIterator >
_>void selection_sort( RandomAccessIterator first, RandomAccessIterator last )
_>{
_>    while( first < --last )
_>        std::iter_swap( last, std::max_element( first, last + 1 ) );
_>}
_>


А в чём проблема? Если уж first < last, то first < last + 1 тем более
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[22]: А в чём проблемы?
От: skeptik_  
Дата: 31.08.08 14:23
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, skeptik_, Вы писали:


_>>А теперь попробуй применить твою функцию в данном коде:

_>>
_>>template< typename RandomAccessIterator >
_>>void selection_sort( RandomAccessIterator first, RandomAccessIterator last )
_>>{
_>>    while( first < --last )
_>>        std::iter_swap( last, std::max_element( first, last + 1 ) );
_>>}
_>>


E>А в чём проблема? Если уж first < last, то first < last + 1 тем более

Читай внимательнее, речь о функции
template<class Container>
typename Container::value_type& max_element( Container& c )
{
    if ( c.empty() )
        throw range_error();
    typename Container::iterator result = c.begin();
    for( typename Container::iterator i = result; i < c.end(); ++i )
        if ( *result < *i )
            result = i;
    return *result;
}
Re: Почему преждевременная оптимизация - корень всех зол?
От: EyeOfHell Россия eyeofhell.habr.ru
Дата: 31.08.08 20:15
Оценка:

Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?


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

Естественно, из этого правила есть исключения — компьютерные игры, рендеринг, компрессия, обработка изображений и так далее. Но это достаточно узкоспециализированные области и там свои требования.

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


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

Вот у меня недавно проект был. Сделал бету, запустил тесты — тормоза. Посмотрел по профайлеру — равномерно размазаны. Огорчился. Потестировал глубже — оказалось бага в алгоритме, код вызывался просто чаще чем нужно. Исправил две строки, скорость стала как полагается по спецификации.

А если бы с самого начала все оптимизировал... Было бы грустно, печально и долго. Вот.
Re[4]: Почему преждевременная оптимизация - корень всех зол?
От: Кэр  
Дата: 02.09.08 02:52
Оценка: +3 -1
Здравствуйте, jazzer, Вы писали:

J>>>если тормоза уже заметны, то, очевидно, это уже не преждевременная оптимизация

Кэр>>Осталось ответить на вопрос — как они заметны? "На глазок"?

J>Да, "на глазок".

J>Поэтому что у пользователя будет глазок, очень похожий на твой,
J>...
J>Так что это ни разу не преждевременная оптимизация, а самая что ни на есть обычная.
Перечитайте оригинальную цитату:
http://rsdn.ru/forum/message/3066911.1.aspx
Автор: drol
Дата: 18.08.08


Перечитайте вот эту ссылку:
http://www.flounder.com/optimization.htm

Ваш "глазок" сможет детектировать только общую проблему. Очень (очень!) редко анализ работы программы и ее кода сам по себе подскажет, где решение проблемы. Поможет тут только профайлер запущенный на реальных данных. Разговоры про оптимизацию без замеров профайлера — пустое сотрясание воздуха. И уж точно не разговор инженеров.

J>А профайлер только поможет найти конкретное место, которое надо оптимизировать, не более того.

Ну да. Всего навсего покажет что является проблемой. Куда уж ему до "глазка"

J>а тебе совсем не хочется, чтобы твои пользователи на весь мир о твоем софте кричали, что он тормозной, если, конечно, ты не Microsoft

Если вы хотите, чтобы ваши шутки ценились за остроумие — шутите умно и смешно. Если конечно вы не Петросян
Re[5]: Почему преждевременная оптимизация - корень всех зол?
От: Юрий Жмеренецкий ICQ 380412032
Дата: 02.09.08 04:29
Оценка: -1
Здравствуйте, Кэр, Вы писали:
...
J>>А профайлер только поможет найти конкретное место, которое надо оптимизировать, не более того.
Кэр>Ну да. Всего навсего покажет что является проблемой. Куда уж ему до "глазка"

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

Учитывая правило 80/20, локализация проблемных мест обычно не вызывает каких-либо серьезных затруднений (при достаточном уровне "понимания" проекта, иначе мы с очень большой долей вероятности будем оптимизировать не то).
Re[6]: Почему преждевременная оптимизация - корень всех зол?
От: Кэр  
Дата: 02.09.08 04:47
Оценка: +1
Здравствуйте, Юрий Жмеренецкий, Вы писали:

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

ЮЖ>Учитывая правило 80/20, локализация проблемных мест обычно не вызывает каких-либо серьезных затруднений (при достаточном уровне "понимания" проекта, иначе мы с очень большой долей вероятности будем оптимизировать не то).

Оригинальные рассуждения. Программирование вообще штука опасная — мало ли чего можно накодировать. Если мы не доверяем самим себе, боясь узнать реальные данные от профайлера — они де нас могут обмануть; то я уж не знаю, как дальше можно работать. Разве что уповая на абстрактные правила 80/20.
Re[7]: Почему преждевременная оптимизация - корень всех зол?
От: Юрий Жмеренецкий ICQ 380412032
Дата: 02.09.08 20:30
Оценка:
Здравствуйте, Кэр, Вы писали:

Кэр>Здравствуйте, Юрий Жмеренецкий, Вы писали:


Кэр> Если мы не доверяем самим себе, боясь узнать реальные данные от профайлера — они де нас могут обмануть;

Я совсем про другое писал.
Re[8]: Почему преждевременная оптимизация - корень всех зол?
От: Sinclair Россия https://github.com/evilguest/
Дата: 03.09.08 04:17
Оценка: 1 (1) +1
Здравствуйте, Юрий Жмеренецкий, Вы писали:


Кэр>> Если мы не доверяем самим себе, боясь узнать реальные данные от профайлера — они де нас могут обмануть;

ЮЖ>Я совсем про другое писал.
Ну. Ты писал что а) используя данные от профайлера, есть риск оптимизировать не то. А что, не используя данные профайлера, этот риск как-то уменьшается? За счет чего?
Далее, ты писал, что "обычно" легко идентифицировать проблемные места. Практика показывает, что нифига не легко. Даже при 100% понимании проекта. Потому, что скорость может теряться вовсе не там, где кажется. Вон недавно в веб программировании парень пытался понять, почему страничка долго грузится. Ему уж успели насоветовать советов по экономии трафика. А оказалось, что Bottleneck — в том, как IE парсит CSS. Ну и что можно было сделать без помощи профайлера?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Почему преждевременная оптимизация - корень всех зол?
От: Юрий Жмеренецкий ICQ 380412032
Дата: 03.09.08 11:00
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Юрий Жмеренецкий, Вы писали:



Кэр>>> Если мы не доверяем самим себе, боясь узнать реальные данные от профайлера — они де нас могут обмануть;

ЮЖ>>Я совсем про другое писал.
S>Ну. Ты писал что а) используя данные от профайлера, есть риск оптимизировать не то. А что, не используя данные профайлера, этот риск как-то уменьшается?
Например, уперлись в функцию распределения памяти. Дальше что ? ее будем оптимизировать? это же данные от профайлера...
Или: для повышения производительности для надо менять асимтотику алгиритма, а мы по результатам профилирования будем оптимизировать конкретную функцию.

S>Далее, ты писал, что "обычно" легко идентифицировать проблемные места. Практика показывает, что нифига не легко. Даже при 100% понимании проекта.

Если это(проект) что-то большое, сложное и непонятное — значит нефиг лезть оптимизировать.

S>Потому, что скорость может теряться вовсе не там, где кажется. Вон недавно в веб программировании парень пытался понять, почему страничка долго грузится. Ему уж успели насоветовать советов по экономии трафика.

Значит это не 100% понимание всех потенциально проблемных мест. Имхо.

S>А оказалось, что Bottleneck — в том, как IE парсит CSS.

Во-первых: надо знать детали — при каких условиях возникла эта ситуация — сразу после написания модуля или при внесении изменений и т.д и т.п.

Во-вторых: если он спрашивал, значит предварительные замеры не принесли результата. Или что еще хуже — наверняка были попытки оптимизировать не то. Ну не верю я в то, что первое что сделал тот парень — задал вопрос на rsdn.

В-третьих: Чтобы померить это сначала надо понять где мерить, а не тыкать замеры где-попало: вот при этом у нас получается больше результатов — больше риск уйти в оптимизацию.

PS: Про IE & CSS — Пару лет назад слышал похожую историю в виде анекдота, правда там фигурировал объем html'a.
Re[10]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 03.09.08 11:57
Оценка: +1
Здравствуйте, Юрий Жмеренецкий, Вы писали:

S>>Ну. Ты писал что а) используя данные от профайлера, есть риск оптимизировать не то. А что, не используя данные профайлера, этот риск как-то уменьшается?

ЮЖ>Например, уперлись в функцию распределения памяти. Дальше что ? ее будем оптимизировать? это же данные от профайлера...
Что значит "уперлись в функцию распределения памяти"? Что в ней мы проводим 20% времени? Или что она вызывается больше всего раз?
Ок, теперь ясно понятно, что нужно что-то с этим делать. Например, выделять память заранее блоками, чтобы снизить количество вызовов. Или ускорять ее реализацию. Всё зависит от конкретного случая.
ЮЖ>Или: для повышения производительности для надо менять асимтотику алгиритма, а мы по результатам профилирования будем оптимизировать конкретную функцию.
Ну и зачем вы будете оптимизировать конкретную функцию, если надо менять асимптотику алгоритма? Более того — как ты поймешь, что дело в асимптотике без профайлера? С профайлером всё как раз понятно — запускаем на разных объемах, смотрим различия в профилях. Статическим анализом оценить асимптотику большинства полезных алгоритмов невозможно.

ЮЖ>Если это(проект) что-то большое, сложное и непонятное — значит нефиг лезть оптимизировать.

Отлично. Дальше, в принципе, можно не общаться. Мне как-то много лет уже не удается поучаствовать в маленьких, простых и понятных проектах.

S>>Потому, что скорость может теряться вовсе не там, где кажется. Вон недавно в веб программировании парень пытался понять, почему страничка долго грузится. Ему уж успели насоветовать советов по экономии трафика.

ЮЖ>Значит это не 100% понимание всех потенциально проблемных мест. Имхо.
Ну естественно не 100%! А откуда его взять, это понимание? А? Без инструментов?
Это значит, SQL оптимизировать — не глядя в план? Web — не пользуясь фиддлером? А как тогда? Медитативно? Можно, но очень дорого.
S>>А оказалось, что Bottleneck — в том, как IE парсит CSS.
ЮЖ>Во-первых: надо знать детали — при каких условиях возникла эта ситуация — сразу после написания модуля или при внесении изменений и т.д и т.п.
Детали — важны. И результат профилирования и есть эти детали.
ЮЖ>Во-вторых: если он спрашивал, значит предварительные замеры не принесли результата.
Ну естественно, предварительные замеры были сделаны по твоей технологии: "на глазок". На сервере работает быстро, а на клиенте — медленно.
ЮЖ>Или что еще хуже — наверняка были попытки оптимизировать не то. Ну не верю я в то, что первое что сделал тот парень — задал вопрос на rsdn.
Мы не вопросы веры обсуждаем.
ЮЖ>В-третьих: Чтобы померить это сначала надо понять где мерить,
Ну как это где? Где тормозит, там и надо мерить. А ты где меришь?
ЮЖ>а не тыкать замеры где-попало: вот при этом у нас получается больше результатов — больше риск уйти в оптимизацию.
Риск уйти в оптимизацию бывает только если не пользоваться профайлером. Типа "ой, наверное асимптотика не та, давайте алгоритм поменяем". "Ой, нет, не помогло. Давайте что-нибудь еще подкрутим".
ЮЖ>PS: Про IE & CSS — Пару лет назад слышал похожую историю в виде анекдота, правда там фигурировал объем html'a.
При чем тут анекдоты? Добро пожаловать в реальный мир
Автор: tokaplan
Дата: 21.08.08
.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Почему преждевременная оптимизация - корень всех зол?
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 03.09.08 12:35
Оценка: 15 (1) +1
А>Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?

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


Уже когда-то писал по этой теме, но решил и сюда вставить свои пять копеек:

"Я также знал, но забыл афоризм Хоара о том, что преждевременная оптимизация — корень всех зол в программировании".
Дональд Кнут, The Errors of TeX.

"Корректность лучше быстроты. Простота лучше сложности. Ясность лучше хитроумия. Безопасность лучше ненадежности".
Саттер, Александреску, "Стандарты программирования на С++"

"Гораздо, гораздо проще сделать корректную программу быстрой, чем быструю — корректно".
те же Саттер и Александреску

и так далее, и так далее.
Подобных цитат можно привести огромное количество. Подобные мысли встречаются в работах Мейера, Фаулера, Страуструба, банды четырех, Бека, Макконнелла, Ханта и Томаса. Общая суть которых сводиться к тому, что первое в деле разработки промышленного ПО — это качество, расширяемость, удобочитаемость кода и т.д., производительность же важна, но не в коем случае нельзя накидываться на нее с самого начала.

Но кроме всего этого, у некоторых авторов (уже приведенные выше Саттер и Александреску, а также Бентли) вводят понятие "пессимизации":
"То, что просто для вас, — просто и для кода. При прочих равных условиях, в особенности — сложности и удобочитаемости кода, ряд эффективных шаблонов проектирования и идиом кодирования должны естественным образом "стекать с кончиков ваших пальцев" и быть не сложнее в написании, чем их пессимизированные альтернативы. Это не преждевременная оптимизация, а избежание излишней пессимизации.".

При этом, в общем случае пессимизация зависит от среды, платформы, языка. Можно привести несколько примеров для C++ и .Net.

С++:
Под преждевременной писсимизацией в С++ понимается:
— передача параметров по значению, там где применима передача параметров по ссылке;
— использование постфиксной версии ++ там, где с тем же успехом можно воспользоваться префиксной версией;
— использование присваивания в конструкторах вместо списка инициализации (кстати, использование списка инициализации облегчает поддержку, в добавок к тому, что он еще и эффективнее, см. Мейерса).

Но при этом главный упор делается но то, что нужно использовать более эффективные конструкции при прочих равных условиях, т.е. более эффективные варианты не ухудшают ни дизайн, ни сложность поддержки. Часто можно встретить совет: используйте вызов функции empty() для контейнеров, вместо size() == 0, т.к. в некоторых случаях empty() будет эффективней, но кроме того эта функция лучше передает намерения программиста, она явно говорит, что размер мне не нужен, мне нужно знать пуст контейнер или нет.

Точно также Мейерс дает советы по выбору типа контейнера в зависимости от той задачи, которую необходимо решить. Если предметная область говорит, что количество данных в контейнере исчисляется тысячами и постоянно нужен поиск, то в первой итерации лучше выбрать std::set, для повышения скорости поиска. Но при этом, главное, на что делается акцент: пусть этот контейнер будет всего-лишь деталью реализации, чтобы в последствии вы могли изменить его тип, если профайлер скажет вам, что с производительностью при поиске есть какие-то проблемы.

В .Net есть свои идиомы:
— переопределение функции GetHashCode. Нужно возвращать значение, вероятность дублирования которого относительно мала. Если сделать, чтобы эта функция возвращала константу хэш-таблица выродиться в простой список;
— использование StringBuilder для динамического создания строки из множества кусков;
— использование оператора as вместо is, для определения типа объекта.

Еще раз подчеркиваю, все вышеперечисленное не является преждевременной оптимизацией, это всего-лишь разумное использование средств, которые предоставляет та или иная среда тому или иному разработчику.
Re[11]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 03.09.08 16:39
Оценка: -2 :))
Здравствуйте, Sinclair, Вы писали:

ЮЖ>>Например, уперлись в функцию распределения памяти. Дальше что ? ее будем оптимизировать? это же данные от профайлера...

S>Что значит "уперлись в функцию распределения памяти"? Что в ней мы проводим 20% времени? Или что она вызывается больше всего раз?
S>Ок, теперь ясно понятно, что нужно что-то с этим делать.
Ааа, теперь понял. Пляшем от профайлера. Надо что-то делать, а что не известно. Так же как и почему мы туда уперлись, и кто виноват...


ЮЖ>>Или: для повышения производительности для надо менять асимтотику алгиритма, а мы по результатам профилирования будем оптимизировать конкретную функцию.

S>Ну и зачем вы будете оптимизировать конкретную функцию, если надо менять асимптотику алгоритма?
Я имел ввиду "а мы, руководствуясь твоими принципами", т.е. гипотетические "мы". Я иногда себя ставлю на место собеседника и пытаюсь делать то о чем он говорит, попутно рассуждая к чему это приведет.

S>Более того — как ты поймешь, что дело в асимптотике без профайлера?

В яблочко! Вот она отправная точка. Издалека:

В соседней ветке этого-же топика я уже высказывал свою позицию по поводу проверки параметров (про бассейн в часности), иногда употребляя такие слова как "уверенность", "гарантия" и т.п. Повторюсь по пунктам, чтобы было понятно откуда растут ноги:

Любая "функциональность"(F) обладает контрактом — это значит что:
1) Контракт "превыше всего". Если написано "Не влезай — убъет" — то это и означает то что написано. Кто влез, — тот умер. Без разговоров. Кто не поял — тот умер, кто не умеет читать — тот умер. Нарушение контракта это очень серьезно. UB, форматирование винчестера, вечный цикл — все что угодно.

2) Если в контракте написано что "Если клиент(пользователь) выполнил A, то F выполнит B" — это опять же, означает то что написано. Причем F гарантирует это. Да, так бывает, если этого захотеть.

3) Самое сложное. Контракт должен покрывать все возможные случаи(в разумных пределах). Это действительно сложно. Например, как показывает практика, далеко не каждый с первого раза может написать полные постусловия для операции вставки в set.

Что мы имеем исходя из этого всего:

Никто не мешает нам включить в контракт требования по сложности (так, например, местами делает стандарт С++), да и константы в коридор поставить никто не мешает.

Ну и собственно самые сливки: если вся система построена на таких F, с четко выраженнымы контрактами(включая контракты по сложности), которым следуют все клиенты, то все точки входа/выхода(в очень широком смысле) имеют не что иное как, опять же, контракт.

S>Ну естественно не 100%! А откуда его взять, это понимание? А? Без инструментов?

А вот оно понимание(см. выше). У меня есть гарантии: контракт. Мне не нужны никакие инструменты для этого(для понимания), у меня есть контракт. На всю систему целиком.

ЮЖ>>Во-первых: надо знать детали — при каких условиях возникла эта ситуация — сразу после написания модуля или при внесении изменений и т.д и т.п.

S>Детали — важны.
Безусловно.

ЮЖ>>И результат профилирования и есть эти детали.

Это второстепенные детали.

ЮЖ>>Во-вторых: если он спрашивал, значит предварительные замеры не принесли результата.

S>Ну естественно, предварительные замеры были сделаны по твоей технологии: "на глазок".
На авторство я не претендую.

ЮЖ>>На сервере работает быстро, а на клиенте — медленно.

Значит совсем не тестировали.

ЮЖ>>Или что еще хуже — наверняка были попытки оптимизировать не то. Ну не верю я в то, что первое что сделал тот парень — задал вопрос на rsdn.

S>Мы не вопросы веры обсуждаем.
Хорошо, сократим до "наверняка были попытки оптимизировать не то". Хотя это в принципе можно назвать предположением, и ты будешь прав...

ЮЖ>>В-третьих: Чтобы померить это сначала надо понять где мерить,

S>Ну как это где?
Возвращаясь к IE: например, связка db-appserver(или что там) или webserver-client.
Тем более что такое "тормоза" формально ? да постусловия это. И там должен быть свой эквивалент assert'a(не буквально конечно) в виде performance тестов или еще как.

S>Где тормозит, там и надо мерить.

Зачем мерить там где тормозит ?

S>А ты где меришь?

в assert'ах. Опять же не буквально, но я думаю теперь понятно откуда ноги растут у отключения assert'ов в релизе ?

ЮЖ>>а не тыкать замеры где-попало: вот при этом у нас получается больше результатов — больше риск уйти в оптимизацию.

S>Риск уйти в оптимизацию бывает только если не пользоваться профайлером.
Я знаю когда возможно, то о чем ты говоришь. Это "очень bad way". Твоя альтернатива — просто "bad way". Имхо.

S>Типа "ой, наверное асимптотика не та, давайте алгоритм поменяем". "Ой, нет, не помогло. Давайте что-нибудь еще подкрутим".

Если система построена с учетом принципов, описанных выше, то этой ситуации быть не может, потому как выделенное — абсурд.
Хотя описанное возможно при рефакторинге legacy кода. При недостаточно его понимании случается "ой, нет не помогло", Все бы хорошо, но вот неожиданное "ой" говорит о некомпетентности.


ЮЖ>>PS: Про IE & CSS — Пару лет назад слышал похожую историю в виде анекдота, правда там фигурировал объем html'a.

S>При чем тут анекдоты?
При том что это оказывается популярные грабли, раз уже стали анекдотом.
Re[11]: Почему преждевременная оптимизация - корень всех зол
От: skeptik_  
Дата: 03.09.08 16:41
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Юрий Жмеренецкий, Вы писали:


S>>>Ну. Ты писал что а) используя данные от профайлера, есть риск оптимизировать не то. А что, не используя данные профайлера, этот риск как-то уменьшается?

ЮЖ>>Например, уперлись в функцию распределения памяти. Дальше что ? ее будем оптимизировать? это же данные от профайлера...
S>Что значит "уперлись в функцию распределения памяти"? Что в ней мы проводим 20% времени? Или что она вызывается больше всего раз?
S>Ок, теперь ясно понятно, что нужно что-то с этим делать. Например, выделять память заранее блоками, чтобы снизить количество вызовов. Или ускорять ее реализацию. Всё зависит от конкретного случая.
Или заменить map на vector, а присвоение на swap. Не всё так очевидно. Это реальный случай кстати.
Re[12]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.09.08 03:10
Оценка: +1
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>3) Самое сложное. Контракт должен покрывать все возможные случаи(в разумных пределах). Это действительно сложно. Например, как показывает практика, далеко не каждый с первого раза может написать полные постусловия для операции вставки в set.


ЮЖ>Что мы имеем исходя из этого всего:


ЮЖ>Никто не мешает нам включить в контракт требования по сложности (так, например, местами делает стандарт С++), да и константы в коридор поставить никто не мешает.

ЮЖ>Ну и собственно самые сливки: если вся система построена на таких F, с четко выраженнымы контрактами(включая контракты по сложности), которым следуют все клиенты, то все точки входа/выхода(в очень широком смысле) имеют не что иное как, опять же, контракт.


Юра, почитай хотя бы Кнута. Про оценки сложности алгоритмов сортировки, к примеру. Там приведены примеры ситуаций, когда из контрактов F() и G() контракт на G(F()) люди выводят годами.

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


S>>Ну естественно не 100%! А откуда его взять, это понимание? А? Без инструментов?

ЮЖ>А вот оно понимание(см. выше). У меня есть гарантии: контракт. Мне не нужны никакие инструменты для этого(для понимания), у меня есть контракт. На всю систему целиком.
В общем, я понял: ты работаешь только с примитивными вычислительными программами, где 100% точные требования к софту известны за пять лет до начала разработки и утверждены комитетами. При этом размер задачи настолько незначителен, что для ее решения достаточно одного программиста.

Ему не нужно отлаживать программу — за него ошибки устранил Контракт(тм).
Ему не нужно оптимизировать программу — за него оптимальность гарантировал Контракт(тм).
Если его не устраивает производительность — он смотрит в табличку Контрактов(тм) и меняет одну функцию на другую, с таким же Контрактом по поведению, но более удачным по сложности. Впрочем, о чем это я? Если это суперпрограммист, то он никогда не выберет функцию с неудачным контрактом.

В общем, фантастические мечты — это не ко мне. Ты лучше про это Лукьяненко вот напиши.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 04.09.08 07:53
Оценка:
Здравствуйте, Sinclair, Вы писали:
...
S>Юра, почитай хотя бы Кнута. Про оценки сложности алгоритмов сортировки, к примеру.
Тише, Антон, тише. я тоже могу послать почитать.

S>Там приведены примеры ситуаций, когда из контрактов F() и G() контракт на G(F()) люди выводят годами.

Это всего лишь подтверждает тот факт, что из всех правил бывают исключения. У нас кое-какие(где-то больше, где-то меньше) контракты и свойства автоматически выводятся. Дальше что ? Объявим ересью ? Геделя вспомним ?

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

Они вырожденные не в этом смысле. Есть проблемы, но они совершенно другого рода.

S>>>Ну естественно не 100%! А откуда его взять, это понимание? А? Без инструментов?

ЮЖ>>А вот оно понимание(см. выше). У меня есть гарантии: контракт. Мне не нужны никакие инструменты для этого(для понимания), у меня есть контракт. На всю систему целиком.
S>В общем, я понял:
Нет, — придумал. т.к. не можешь понять откуда у менять есть контракт на всю систему (это между прочим не 100% гарантия работоспособности или отсутствия ошибок). это нечто другое.

S>где 100% точные требования к софту известны за пять лет до начала разработки и утверждены комитетами.

По крайней мере одно требование всегда известно до начала разработки. Цена ошибки.

S>При этом размер задачи настолько незначителен, что для ее решения достаточно одного программиста.

Угу, со своими компиляторами(не шарп, и не С++), с разработкой одного функционала несколькими независимыми группами(казалось бы, зачем?), с тестированием по 4-8 месяцев, которое даже остановить-то проблематично.

S>Ему не нужно отлаживать программу — за него ошибки устранил Контракт(тм).

S>Ему не нужно оптимизировать программу — за него оптимальность гарантировал Контракт(тм).
S>Если его не устраивает производительность — он смотрит в табличку Контрактов(тм) и меняет одну функцию на другую, с таким же Контрактом по поведению, но более удачным по сложности. Впрочем, о чем это я? Если это суперпрограммист, то он никогда не выберет функцию с неудачным контрактом.
S>В общем, фантастические мечты — это не ко мне.

Аха, давай спустимся на землю. Чего мы имеем:
* Самый главный(или один из них) интрумент — оптимизатор. Мереем все подряд ибо может тормозить все что угодно, попутно мотивируя бесконтрольной "большой системой", которую мы не знаем, но все равно лезем в нее.
* Ассерты оставляем в релизе(хотя это уже не ассерты, а черти что).
* Не доверяем своему коду до такой степени, что в ужасе начинаем проверять все параметры всех функций. Кстати, причина — из-за того что внешие данные могут приити откуда угодно. Потому что:
* Контрактов естественно нет(даже если есть — то с очень странными целями).
* добавить по вкусу.
Реальность ? да. Наелся я такого, спасибо.

S>ты работаешь только с примитивными вычислительными программами

Сразу бы и спрашивал сколько сантиметров. Хотя я сюда не за этим пришел. "Дальше, в принципе, можно не общаться" (c)
Re[14]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.09.08 08:32
Оценка: +1
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Это всего лишь подтверждает тот факт, что из всех правил бывают исключения. У нас кое-какие(где-то больше, где-то меньше) контракты и свойства автоматически выводятся. Дальше что ? Объявим ересью ? Геделя вспомним ?

Объявим бесполезными с практической точки зрения.
Поясняю на пальцах: вот есть у нас IM клиент. Например, Office Communicator. Довольно сложная софтина, с запутанными call stack, тащит за собой кучу библиотек, для которых никаких контрактов сложности дать не удается. Ну вот какой, к примеру, контракт может быть у парсера XML? В каких терминах он будет выражен?
Ок, хорошо, давайте попробуем обконтрактить передачу данных по TCP/IP. Да хотя бы чтение из файлухи заведомо не дает никаких гарантий.
И что мы теперь будем с ним делать, с таким софтом? Искать программиста, который "реально разбирается во всех тонкостях" всего подряд?
А остальным даже подойти не дадим? Спасибо, до свидания.

ЮЖ>Они вырожденные не в этом смысле. Есть проблемы, но они совершенно другого рода.

Какого рода?

S>>При этом размер задачи настолько незначителен, что для ее решения достаточно одного программиста.

ЮЖ>Угу, со своими компиляторами(не шарп, и не С++), с разработкой одного функционала несколькими независимыми группами(казалось бы, зачем?), с тестированием по 4-8 месяцев, которое даже остановить-то проблематично.
А, ну так надо было с самого начала и говорить, что речь идет о нишевой разработке. На специальном языке, в специальных условиях.
А остальным что делать?

ЮЖ>Аха, давай спустимся на землю. Чего мы имеем:

ЮЖ>* Самый главный(или один из них) интрумент — оптимизатор. Мереем все подряд ибо может тормозить все что угодно, попутно мотивируя бесконтрольной "большой системой", которую мы не знаем, но все равно лезем в нее.
А что такое "оптимизатор"? У тебя какие-то представления об оптимизации софта совершенно особые, не связанные с реальностью. Юра, поясню опять же, на пальцах: оптимизатор — это человек.
И естественно он не знает "систему". Потому, что сейчас невозможно уже знать "систему", она за рамки головы вылезает.
Далее, этот человек не "мереет всё подряд". Он берет некие сценарии использования, и прогоняет через профайлер. После чего получает информацию о том, как устроена производительность софта. Ему не страшно отсутствие либо наличие контрактов; ему не страшно отсутствие проверки контрактов компилятором и риск получить вранье в контракте. Ему не нужно знать наизусть систему от и до. Он видит реальную картину поведения софта в реальном окружении.
После этого у него обычно появляется понимание, куда нужно копать. В софт вносятся изменения, и цикл тестирования повторяется. Иногда приходится проводить дополнительные измерения, потому что начальные не дали нужных данных. Таким образом, безо всяких предварительных условий мы получаем нужный результат.

Остальные домыслы я поскипаю. С ними, опять же, не ко мне.

S>>ты работаешь только с примитивными вычислительными программами

ЮЖ>Сразу бы и спрашивал сколько сантиметров.
Дело не в сантиметрах. Дело в применимости подходов. Ты вот почему-то всё время делаешь таинственное лицо, и критикуешь зарекомендовавшие себя паттерны. А взамен — только лозунги и абстрактные рассуждения о каких=то контрактах, безо всяких уточнений.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[15]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 04.09.08 10:51
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Это всего лишь подтверждает тот факт, что из всех правил бывают исключения. У нас кое-какие(где-то больше, где-то меньше) контракты и свойства автоматически выводятся. Дальше что ? Объявим ересью ? Геделя вспомним ?

S>Объявим бесполезными с практической точки зрения.
S>Поясняю на пальцах: вот есть у нас IM клиент. Например, Office Communicator. Довольно сложная софтина, с запутанными call stack, тащит за собой кучу библиотек, для которых никаких контрактов сложности дать не удается. Ну вот какой, к примеру, контракт может быть у парсера XML? В каких терминах он будет выражен?
S>Ок, хорошо, давайте попробуем обконтрактить передачу данных по TCP/IP. Да хотя бы чтение из файлухи заведомо не дает никаких гарантий.

Такие описанные места называются "vulnerability window" — то о чем у нас нет достоверных данных, документации и т.п. и им уделяется максимальное внимание. Так как по определению там можно нарватся на просады производительности, то все эти места тестируются(перед использованием) в различных режимах, собирается(и документируется) статистика и делается вывод о пригодности использования в каких-то рамках. Это относится не только к производительности: все данные, входящие из таких "черных дыр" тщательно проверяются(типа как проверяется user input). и только потом поступают в систему.

Этот подход не может давать гарантированные 100% результаты, но очень сильно снижает недетерминированность системы в целом. Кроме того эти места действуют на всех как красная тряпка на быка: про них все знают, и если возникают какие либо подозрения — то они проверяются в первую очередь.

ЮЖ>>Они вырожденные не в этом смысле. Есть проблемы, но они совершенно другого рода.

S>Какого рода?

Если у нас имеется контракт, который описывает все возможные исходы, то иногда, даже несмотря на это, — нет уверенности в правильности результата. Начиная от невозможности протестировать: не с чем сравнивать например, или тестовые прогоны очень дорогие, или наличие скрытых взаимодействий. и т.п.

Кое-что из этого решает N-version programming, но это совсем крайность: делаем N реализаций одного алгоритма, запускаем, и... попадаем: а что делать с результатами?...

S>>>При этом размер задачи настолько незначителен, что для ее решения достаточно одного программиста.

ЮЖ>>Угу, со своими компиляторами(не шарп, и не С++), с разработкой одного функционала несколькими независимыми группами(казалось бы, зачем?), с тестированием по 4-8 месяцев, которое даже остановить-то проблематично.
S>А, ну так надо было с самого начала и говорить, что речь идет о нишевой разработке. На специальном языке, в специальных условиях.
S>А остальным что делать?

Представить что любая программа должна работать в режиме 24x7. Вообще любая.

Другой вариант(как бы нелепо это не звучало) — представить что ошибка в любой программе приведет к человеческим жертвам. После этого даже просто отношение меняется.

S>А что такое "оптимизатор"?

Говоря в этой ветке "оптимизатор" я имел ввиду профайлер, т.к. именно он был упомянут в первом сообщении, на которое я отвечал. Извиняюсь за подмену понятий.

S>оптимизатор — это человек.

Ок.

S>И естественно он не знает "систему". Потому, что сейчас невозможно уже знать "систему", она за рамки головы вылезает.

S>Далее, этот человек не "мереет всё подряд". Он берет некие сценарии использования, и прогоняет через профайлер.
S>После чего получает информацию о том, как устроена производительность софта. Ему не страшно отсутствие либо наличие контрактов;
Наличие не должно быть страшным =) этим надо пользоваться.

S>ему не страшно отсутствие проверки контрактов компилятором и риск получить вранье в контракте. Ему не нужно знать наизусть систему от и до. Он видит реальную картину поведения софта в реальном окружении.

S>После этого у него обычно появляется понимание, куда нужно копать.

Вот кстати, зачем обязательно в реально окружении? Почему нельзя заранее протестировать изолированные части? Что мешает? Смоделировать низкий пропускной канал, например, не проблема, тучу клиентских запросов тоже. Неужели система в "целом" начинает жить непредсказуемо?

И еще: cколько времени понадобилось вышеописанному оптимизатору? Для него в такой ситуации — тормоза могут быть где угодно(в пределах сценариев использования), система ведь большая.

В моем случае — тормоза гдето в местах обозначенных красной тряпкой. А их количство стремятся минимизировать.

S>Дело в применимости подходов.

Да тут все просто. Правило треугольника(или как там), — Время, Стоимость, Качество. Фиксировать можно две величины. Для проектов из "реального мира" зафиксированы первые две. Мне больше импонирует ситуация, когда первым компонентом является качество, а вторым может быть хоть что.
Re[16]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 04.09.08 11:24
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Да тут все просто. Правило треугольника(или как там), — Время, Стоимость, Качество. Фиксировать можно две величины. Для проектов из "реального мира" зафиксированы первые две. Мне больше импонирует ситуация, когда первым компонентом является качество, а вторым может быть хоть что.


Юрий, просто интересно: какого типа ПО вы разрабатываете?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[16]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.09.08 14:53
Оценка: +1
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Такие описанные места называются "vulnerability window" — то о чем у нас нет достоверных данных, документации и т.п. и им уделяется максимальное внимание. Так как по определению там можно нарватся на просады производительности, то все эти места тестируются(перед использованием) в различных режимах, собирается(и документируется) статистика и делается вывод о пригодности использования в каких-то рамках.

Это бессмысленная работа:
1. В любом windows-приложении такими окнами являются все системные вызовы.
2. Никакое тестирование этих "мест" без окружения не даст нужного результата. Ну вот снимаем мы, к примеру, метрики сетевых интерфейсов, а потом бац! и оказывается, что во время проигрывания видеоконтента сеть искусственно затормаживается. Если у нас приложение связано с воспроизведением видео и сетью, то мы попадаем.

ЮЖ>Этот подход не может давать гарантированные 100% результаты, но очень сильно снижает недетерминированность системы в целом. Кроме того эти места действуют на всех как красная тряпка на быка: про них все знают, и если возникают какие либо подозрения — то они проверяются в первую очередь.

Юра, что значит "проверяются в первую очередь"? Вот у меня есть такое "место": функция FileRead(). Вижу, что у меня приложение плохо шевелится. Что мне "проверять"?

ЮЖ>Если у нас имеется контракт, который описывает все возможные исходы, то иногда, даже несмотря на это, — нет уверенности в правильности результата. Начиная от невозможности протестировать: не с чем сравнивать например, или тестовые прогоны очень дорогие, или наличие скрытых взаимодействий. и т.п.

Угу. И это покрывает 99.9% всех полезных приложений.

ЮЖ>Кое-что из этого решает N-version programming, но это совсем крайность: делаем N реализаций одного алгоритма, запускаем, и... попадаем: а что делать с результатами?...

Как что? Этот подход замечателен для распила бабла. К моменту запуска все стейкхолдеры уже давно на канарах.


ЮЖ>Представить что любая программа должна работать в режиме 24x7. Вообще любая.

ЮЖ>Другой вариант(как бы нелепо это не звучало) — представить что ошибка в любой программе приведет к человеческим жертвам. После этого даже просто отношение меняется.
А, опять медитативные техники. Юра, это не ко мне. Это надо даже не знаю куда.


ЮЖ>Вот кстати, зачем обязательно в реально окружении? Почему нельзя заранее протестировать изолированные части? Что мешает? Смоделировать низкий пропускной канал, например, не проблема, тучу клиентских запросов тоже. Неужели система в "целом" начинает жить непредсказуемо?

Ну конечно, Юра! Срываю покровы: во-первых, стоимость тестирования всех изолированных частей во всех мыслимых режимах заведомо выходит за пределы коммерческих бюджетов. Во-вторых, система "в целом" всегда живет непредсказуемо — пример я уже привел: сеть отдельно и видео отдельно работают хорошо; включаем вместе — сеть тормозит. Ну и зачем было заниматься закапыванием денег в землю? Это и есть premature optimization.

ЮЖ>И еще: cколько времени понадобилось вышеописанному оптимизатору? Для него в такой ситуации — тормоза могут быть где угодно(в пределах сценариев использования), система ведь большая.

Что значит "где угодно"? Я же говорю — поводом для оптимизации является наблюдаемая проблема с производительностью, а не абстрактное желание "хочу побыстрее". Недавний пример я уже приводил.
Времени на выяснение места, где тормозит, уходит немного. Как правило, всё становится ясно в тот же день. Больше всего времени уходит на подготовку нужного тестового окружения; собственно анализ выхода профайлера — дело значительно более простое, чем копание в контрактах.

ЮЖ>В моем случае — тормоза гдето в местах обозначенных красной тряпкой. А их количство стремятся минимизировать.

Совершенно верно. Вот я приводил пример — Instant Messenger. В нем тормоза где-то в UI. Либо в сети. Либо в файлухе. Либо жрет много памяти, а это может тормозить из-за вытеснения в своп. Больше тормозить нечему. Впрочем, в нем больше ничего и нет. "Что ж вы флажками не обозначили? Как не обозначили — на выезде из Шереметьево красный флаг был."
Поэтому вместо анализа "списка тряпок" мы получаем конкретные данные.

ЮЖ>Да тут все просто. Правило треугольника(или как там), — Время, Стоимость, Качество. Фиксировать можно две величины. Для проектов из "реального мира" зафиксированы первые две. Мне больше импонирует ситуация, когда первым компонентом является качество, а вторым может быть хоть что.

К сожалению, при добавлении в квантовую механику постулатов теории относительности, вопрос "бесконечного качества" приходится отбросить по причине конечности оси "стоимость".

Поэтому, Юра, отбрось свои предрассудки и попробуй профайлер хоть раз. Я понимаю, нет ничего страшнее неизвестности, но в жизни профайлеры вовсе не так страшны. Еще не было ни одного случая, когда профайлер силой заставил разработчика оптимизировать неправильную строчку.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[17]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 04.09.08 15:06
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

S>Либо жрет много памяти, а это может тормозить из-за вытеснения в своп. Больше тормозить нечему.


Кстати о памяти. Не обязательно выходить в своп, чтобы получить тормоза. Например, можно иметь бинарное дерево поиска, размер которого в несколько раз превышает размер L2 кэша. При обращениях к узлам дерева, которые не находятся в кэше, происходит загрузка страницы памяти в кэш (медленная операция). При достаточно частых промахах мимо кэша можно получить тормоза на, казалось бы, оптимизированной для поиска структуре данных с хорошей O-асимптотикой.

Чесно говоря, я не представляю, какими контрактами или предварительными умозрительными оценками можно заранее защититься от подобной ситуации.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[17]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 04.09.08 22:33
Оценка: -1
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Такие описанные места называются "vulnerability window" — то о чем у нас нет достоверных данных, документации и т.п. и им уделяется максимальное внимание. Так как по определению там можно нарватся на просады производительности, то все эти места тестируются(перед использованием) в различных режимах, собирается(и документируется) статистика и делается вывод о пригодности использования в каких-то рамках.

S>Это бессмысленная работа:
S>1. В любом windows-приложении такими окнами являются все системные вызовы.
Ну наконец-то ты начинаешь понимать. Но вот любое windows-приложение состоит не только из системных вызовов. Из компонентов с низкой надежностью можно собирать компоненты обладающие высокой. Это для тебя новость ?

S>2. Никакое тестирование этих "мест" без окружения не даст нужного результата.

А подробнее ?

ЮЖ>>Если у нас имеется контракт, который описывает все возможные исходы, то иногда, даже несмотря на это, — нет уверенности в правильности результата. Начиная от невозможности протестировать: не с чем сравнивать например, или тестовые прогоны очень дорогие, или наличие скрытых взаимодействий. и т.п.

S>Угу. И это покрывает 99.9% всех полезных приложений.
Начало перечитай — "если у нас имеется контракт".

ЮЖ>>Кое-что из этого решает N-version programming, но это совсем крайность: делаем N реализаций одного алгоритма, запускаем, и... попадаем: а что делать с результатами?...

S>Как что? Этот подход замечателен для распила бабла.
Для тебя — может быть. Но вопрос-то в другом на самом деле.

ЮЖ>>Вот кстати, зачем обязательно в реально окружении? Почему нельзя заранее протестировать изолированные части? Что мешает? Смоделировать низкий пропускной канал, например, не проблема, тучу клиентских запросов тоже. Неужели система в "целом" начинает жить непредсказуемо?

S>Ну конечно, Юра! Срываю покровы:
Спасибо конечно.

S> во-первых, стоимость тестирования всех изолированных частей во всех мыслимых режимах заведомо выходит за пределы коммерческих бюджетов.

"заведомо" — это заблуждение. При твоем подходе, да — выходит, и ты ничего с этим не сделаешь.

S>Во-вторых, система "в целом" всегда живет непредсказуемо

Приплыздец(с). Антон, ты халтуру заказчику поставляеш. Точка. Ты даже предсказать не можешь что она делает. Ты даже не можешь утвержать что система выполняет то что от нее требуется.

S>Времени на выяснение места, где тормозит, уходит немного. Как правило, всё становится ясно в тот же день. Больше всего времени уходит на подготовку нужного тестового окружения; собственно анализ выхода профайлера — дело значительно более простое, чем копание в контрактах.

Откуда ты знаешь как происходит "копание в контрактах"? У тебя же их нет.

ЮЖ>>В моем случае — тормоза гдето в местах обозначенных красной тряпкой. А их количство стремятся минимизировать.

S>Совершенно верно. Вот я приводил пример — Instant Messenger. В нем тормоза где-то в UI. Либо в сети. Либо в файлухе. Либо жрет много памяти, а это может тормозить из-за вытеснения в своп.
S>Больше тормозить нечему.
Неверно. У тебя непредсказуемая система. Играй по своим правилам до конца.

S>Поэтому вместо анализа "списка тряпок" мы получаем конкретные данные.

Оригинальная фраза. Смысла столько же как и в "Вместо яблока мы получаем позавчера".

ЮЖ>>Да тут все просто. Правило треугольника(или как там), — Время, Стоимость, Качество. Фиксировать можно две величины. Для проектов из "реального мира" зафиксированы первые две. Мне больше импонирует ситуация, когда первым компонентом является качество, а вторым может быть хоть что.

S>К сожалению, при добавлении в квантовую механику постулатов теории относительности, вопрос "бесконечного качества"
Опять ты присваеваешь мне авторство слов, которых я не говорил. И зачем ты упомянул квантовую механику ?

S>Поэтому, Юра, отбрось свои предрассудки и попробуй профайлер хоть раз. Я понимаю, нет ничего страшнее неизвестности, но в жизни профайлеры вовсе не так страшны.

У тебя какие-то странные призывы. Такое ощущение что ты мне наркотики предлагаешь... "Это не ко мне"(c)

Все что я пытаюсь сказать, — это то что система с хоть какими-нибудь контрактами лучше чем система без контрактов. Но ты меня обвиняешь в абстракционизме.
Re[18]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 04.09.08 22:43
Оценка: -1
Здравствуйте, eao197, Вы писали:

E>Здравствуйте, Sinclair, Вы писали:


S>>Либо жрет много памяти, а это может тормозить из-за вытеснения в своп. Больше тормозить нечему.


E>Кстати о памяти. Не обязательно выходить в своп, чтобы получить тормоза. Например, можно иметь бинарное дерево поиска, размер которого в несколько раз превышает размер L2 кэша. При обращениях к узлам дерева, которые не находятся в кэше, происходит загрузка страницы памяти в кэш (медленная операция). При достаточно частых промахах мимо кэша можно получить тормоза на, казалось бы, оптимизированной для поиска структуре данных с хорошей O-асимптотикой.


E>Чесно говоря, я не представляю, какими контрактами или предварительными умозрительными оценками можно заранее защититься от подобной ситуации.


Достаточно понимать что такая ситуация имеет место быть. А если понимание присутствует до начала написания кода, то возможно это выльется в другое решение. Для этого и существует предварительный анализ сильных и слабых сторон применяемых решений. Тут вот контракты как раз и рулят.
Re[18]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.09.08 03:11
Оценка: +3
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Ну наконец-то ты начинаешь понимать. Но вот любое windows-приложение состоит не только из системных вызовов. Из компонентов с низкой надежностью можно собирать компоненты обладающие высокой. Это для тебя новость ?

Нет. Но для меня новость, что из низкопроизводительных компонент можно собирать высокопроизводительные.
ЮЖ>А подробнее ?
Я уже написал подробнее. С конкретными примерами.

ЮЖ>"заведомо" — это заблуждение. При твоем подходе, да — выходит, и ты ничего с этим не сделаешь.

При моем подходе просто не нужно тестировать производительность всех изолированных частей. Точка.

ЮЖ>Приплыздец(с). Антон, ты халтуру заказчику поставляеш. Точка. Ты даже предсказать не можешь что она делает. Ты даже не можешь утвержать что система выполняет то что от нее требуется.

Хрен там. Видишь ли, мои утверждения о системе базируются не на предсказаниях, а на измерениях.

.
ЮЖ>Неверно. У тебя непредсказуемая система. Играй по своим правилам до конца.
Я и так играю до конца.

S>>Поэтому вместо анализа "списка тряпок" мы получаем конкретные данные.

ЮЖ>Оригинальная фраза. Смысла столько же как и в "Вместо яблока мы получаем позавчера".
Юра, ты наверное используешь какой-то другой русский язык. Поясняю еще раз: вместо списка возможных узких мест мы получаем список фактических узких мест. Не все 150 вхождений FileRead в программе скажутся на ее производительности. В твоем подходе каждое из них — это красная тряпка, так?
В моем подходе анализ дает те call stack, в которых реально проводится много времени


ЮЖ>Все что я пытаюсь сказать, — это то что система с хоть какими-нибудь контрактами лучше чем система без контрактов.

Да нет, Юра. Ты пытаешься сказать, что профайлер — это плохо. На твои контракты никто не наезжал: контракты — вещь замечательная. Особенно, если их поддерживает компилятор.
ЮЖ>Но ты меня обвиняешь в абстракционизме.
Ну естественно. Потому что ты критикуешь использование профайлера для анализа производительности и оптимизации программы. Аргументируя при этом какими-то дурацкими фобиями.
А что ты предлагаешь взамен? Конкретные рецепты?
Нет. Ты предлагаешь медитативные практики:

- Представить что любая программа должна работать в режиме 24x7.
— представить что ошибка в любой программе приведет к человеческим жертвам.

Ты предлагаешь невыполнимые действия:

если вся система построена на таких F, с четко выраженнымы контрактами(включая контракты по сложности), которым следуют все клиенты, то все точки входа/выхода(в очень широком смысле) имеют не что иное как, опять же, контракт.

А теперь вдруг оказывается, что ты имел в виду, что система с какими-то контрактами лучше...
Впрочем, в этом ты тоже неправ. Потому что из разрозненных контрактов ничего полезного получить нельзя. Это очень легко доказать — ведь если у нас есть F() с полным контрактом и G() без контракта, то любая H() = { F(); G() } тоже будет без контракта. В итоге мы так и получим недетерменированное поведение всех точек входа. Ну и в чем смысл этих контрактов?
Проблема всех пуританских подходов — в том, что одна маленькая дырка портит всю картинку.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[19]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.09.08 04:27
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Достаточно понимать что такая ситуация имеет место быть. А если понимание присутствует до начала написания кода, то возможно это выльется в другое решение. Для этого и существует предварительный анализ сильных и слабых сторон применяемых решений. Тут вот контракты как раз и рулят.


А можно привести пример контракта для этого случая?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 05.09.08 05:23
Оценка: -2
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Ну наконец-то ты начинаешь понимать. Но вот любое windows-приложение состоит не только из системных вызовов. Из компонентов с низкой надежностью можно собирать компоненты обладающие высокой. Это для тебя новость ?

S>Нет. Но для меня новость, что из низкопроизводительных компонент можно собирать высокопроизводительные.
Многопоточность, кеширование...

ЮЖ>>Приплыздец(с). Антон, ты халтуру заказчику поставляеш. Точка. Ты даже предсказать не можешь что она делает. Ты даже не можешь утвержать что система выполняет то что от нее требуется.

S>Хрен там. Видишь ли, мои утверждения о системе базируются не на предсказаниях, а на измерениях.
Неа. все гораздо хуже. В непредсказуемой системе ты по результатам измерений предсказываешь дальнейшее поведение. Только вот твои предсказания в корне отличаются от моих, которые базируются на контрактах.

ЮЖ>>Неверно. У тебя непредсказуемая система. Играй по своим правилам до конца.

S>Я и так играю до конца.
Хорошо, запомним.

S>вместо списка возможных узких мест мы получаем список фактических узких мест.

Первое — А, второе B. У меня B <= A. А тебе придется анализировать все B.

S>Не все 150 вхождений FileRead в программе скажутся на ее производительности. В твоем подходе каждое из них — это красная тряпка, так?

Нет, только те компонеты, в которых она используется, и которые не дают контрактов.

ЮЖ>>Все что я пытаюсь сказать, — это то что система с хоть какими-нибудь контрактами лучше чем система без контрактов.

S>Да нет, Юра. Ты пытаешься сказать, что профайлер — это плохо.
Профайлер — не плохо, плохо бездумное использование (см ниже).

S>На твои контракты никто не наезжал:

Да ладно уже.

S>контракты — вещь замечательная. Особенно, если их поддерживает компилятор.

Да какой нафиг компилятор? Берем банальные предусловия — "Для установки операционной системы требуется наличие как минимум N Mb оперативной памяти" Куда будем вставлять компилятор?


S>Ты предлагаешь невыполнимые действия:

S>

если вся система построена на таких F, с четко выраженнымы контрактами(включая контракты по сложности), которым следуют все клиенты, то все точки входа/выхода(в очень широком смысле) имеют не что иное как, опять же, контракт.

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

S>Впрочем, в этом ты тоже неправ. Потому что из разрозненных контрактов ничего полезного получить нельзя. Это очень легко доказать — ведь если у нас есть F() с полным контрактом и G() без контракта, то любая H() = { F(); G() } тоже будет без контракта.


И что ты этим доказал ? хотел ведь это: "из разрозненных контрактов ничего полезного получить нельзя". Снабдим G контрактом и твое утверждение станет неверным.

S>В итоге мы так и получим недетерменированное поведение всех точек входа. Ну и в чем смысл этих контрактов?

Для тебя они смысла не имеют(хотя выше: "контракты — вещь замечательная"), потому как у тебя все полностью недетерминировано. А у меня есть гарантии на компоненты, на системы созданные из таких компонентов. Но. Я прекрасно отдаю себе отчет о существовании "vulnerability window" и связанных проблемах. Только вот они потому и "window" поскольку их размеры не такие большие(так бывает, если у тебя такого не бывает, это не значит что это невозможно). ПО ведь еще чем-то занимается кроме как вызывает ReadFile.

ЮЖ>>Но ты меня обвиняешь в абстракционизме.

S>Ну естественно. Потому что ты критикуешь использование профайлера для анализа производительности и оптимизации программы.
Да, критикую. Только критикую не просто использование, а бездумное использование. Смотри:

Дан use case(или набор). Для него, помимо всего прочего указываются требования по производительности(мы ведь о таких ситуациях говорим).

Реализуем:

Вариант 1: Без привлечения сторонних компонентов. Например алгорирм сортировки. Здесь, если реализация не обеспечивает заявленных требований, то это баг реализации. Попытки назвать исправление багов "оптимизацией", — запудривание мозгов.

Вариант 2: Имеются компоненты которые можно использовать. У каждого компонента есть свои pre requirements. Во-первых надо отдавать себе отчет в том, что невыполнение этих требований ни к чему хорошему не приведет. Так же у каждого компонента есть "описание" результата.

Вопрос. Как мы будем выбирать один компонент из нескольких(решающих определенную задачу)? На основе чего?
Правильный и единственный ответ: используя контракты, если их нет — придется мерить(не важно что, но это эквивалентно созданию своих контрактов).

Дальше. use case реализован.
Через некоторое время встает вопрос о повышении производительности(если это из-за багов, то см. выше). Повышение производельности здесь опять называется оптимизацией. А вот на более высоком уровне происходит изменение требований, и оптимизация выглядит просто как попытка подогнать существующее решение к новым требованиям. Это аналогично разгону компьютера вместо смены начинки. С аналогичными проблемами. Меняются режимы работы всех связанных компонентов, возникают нарушения контрактов, появляются скрытые неучтенные зависимости. Дополнительные тесты не появляются практически никогда... А ведь это происходит постоянно. В результате система становится все меньше и меньше предсказуемой, снижается общая надежность. Происходит деградация до непредсказуемого состояния, и постулируется что так и должно быть.
Это то к чему приводит твой подход с оптимизацие "по необходимости". Понятно что в практически любых ситуациях найдутся эффективные приемы работы, только вот лечить надо причину, а не симптомы.

Только не надо говорить "добро пожаловать в реальный мир" — это все равно что говорить "все побежали, и я побежал. присоединяйся".

Я вот в последнее время все больше склоняюсь к тому, что профайлер — это просто одно из средств поиска ошибок в контрактах или реализации.

PS: В паралельной ветке предлагается кидание исключений при нарушении предусловий(контракта). На самом деле неважно что должно происходить.
Важно понимать почему и когда возникают такие нарушения, и что из этого следует.
Re[20]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.09.08 06:01
Оценка: +2
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Дан use case(или набор). Для него, помимо всего прочего указываются требования по производительности(мы ведь о таких ситуациях говорим).


ЮЖ>Реализуем:


ЮЖ>Вариант 1: Без привлечения сторонних компонентов. Например алгорирм сортировки. Здесь, если реализация не обеспечивает заявленных требований, то это баг реализации. Попытки назвать исправление багов "оптимизацией", — запудривание мозгов.


ЮЖ>Вариант 2: Имеются компоненты которые можно использовать. У каждого компонента есть свои pre requirements. Во-первых надо отдавать себе отчет в том, что невыполнение этих требований ни к чему хорошему не приведет. Так же у каждого компонента есть "описание" результата.


ЮЖ>Вопрос. Как мы будем выбирать один компонент из нескольких(решающих определенную задачу)? На основе чего?

ЮЖ>Правильный и единственный ответ: используя контракты, если их нет — придется мерить(не важно что, но это эквивалентно созданию своих контрактов).

Как показывает практика
Автор: eao197
Дата: 22.08.08
производительность одной и той же hash-таблицы в зависимости от hash-функции может отличаться в разы. Вопрос. Как имея hash-таблицу со своими контрактами и hash-функцию со своими контрактами без замеров и профайлера оценить производительность?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[20]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.09.08 06:18
Оценка: +1
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Многопоточность, кеширование...

И? Многопоточность дает крайне труднопредсказуемые результаты. К примеру, на одноядерной машине CPU-bound задачи параллелить не только бессмысленно, но и вредно.
Кэширование дает труднопредсказуемые результаты, т.к. без реальных данных мы не только не знаем cache hit ratio, но и не можем предсказать влияние роста потребления памяти на другие части системы, которые на первый взгляд никак с этим не связаны. Я имел опыт подобных решений.

S>>Хрен там. Видишь ли, мои утверждения о системе базируются не на предсказаниях, а на измерениях.

ЮЖ>Неа. все гораздо хуже. В непредсказуемой системе ты по результатам измерений предсказываешь дальнейшее поведение.
Не обязательно. Дальнейшее поведение мы прогнозируем очень редко. Мы делаем всё наоборот: делаем тестовую инсталляцию, замеряем поведение, и после этого даем некоторые гарантии. Но мы не даем никаких гарантий для систем, выходящих за пределы тестовой инсталляции.
То есть если мы намерили на одной коробке 20000 пользователей, то мы гарантируем, что мы столько выдержим. Мы понимаем, что двумя коробками мы обслужим больше, но не знаем сколько именно. Факторов слишком много, чтобы их учесть. Если кого-то интересует 30000, то мы ставим две коробки, и опять мерим. Если не получилось 30000, то мы смотрим (естественно, при помощи профайлера и других инструментальных средств), где оказался боттлнек, и чиним его. Заранее сказать, где он будет, невозможно — к примеру, глючный DNS может свести на нет ширину полосы гигабитного езернета. tcp/ip вообще весь устроен так, что его поведение можно только измерить, и практически невозможно предсказать. Требовать вместо tcp/ip транспорт с QoS — это оверкилл для большинства практических случаев. Достаточно померить результаты и подкрутить то, что мешает — к примеру, починить глючный DNS.

ЮЖ>Только вот твои предсказания в корне отличаются от моих, которые базируются на контрактах.

Совершенно верно. Моим — можно верить. Потому, что у меня есть test report, в котором бесстрастная машина продемонстрировала конкретный воспроизводимый результат. В случае контрактов нужно верить тому, что процедуры вывода контрактов системы из контрактов компонентов были проведены корректно.

S>>вместо списка возможных узких мест мы получаем список фактических узких мест.

ЮЖ>Первое — А, второе B. У меня B <= A. А тебе придется анализировать все B.
Вот это мне непонятно. У меня B в любом случае меньше A, независимо от того, были ли эти А мне известны до измерения. Потому, что это — объективная реальность.
Неужели ты можешь проигнорировать часть из тех B, которые я намерил?

ЮЖ>Нет, только те компонеты, в которых она используется, и которые не дают контрактов.

Отлично, у нас есть 150 компонентов, которые используют FileRead. Или одна компонента, но она используется в 150 местах — от природы не уйдешь; если у нас есть 150 разных стеков, которые уперлись в FileRead, то их всё равно 150.
При этом 149 из них могут не влиять на производительность, потому что вызываются очень редко. И только 1 лежит на критическом пути.

ЮЖ>Профайлер — не плохо, плохо бездумное использование (см ниже).

Бездумное использование никто не предлагал. Предлагается вдумчивое использование профайлера. Если бы можно было обойтись бездумным использованием, то профайлер был бы не нужен. Впрочем, есть наработки и на эту тему: profile-guided optimization — это полностью автоматическая техника. Но мы-то считаем что она уже применена, и ее не хватило.

S>>контракты — вещь замечательная. Особенно, если их поддерживает компилятор.

ЮЖ>Да какой нафиг компилятор? Берем банальные предусловия — "Для установки операционной системы требуется наличие как минимум N Mb оперативной памяти" Куда будем вставлять компилятор?
Как куда? Всё наоборот: компилятор должен нам сказать, сколько памяти требуется для установки операционной системы.
Проверку этого условия мы вставляем в инсталлятор.
Если мы говорим об автоматической системе провижнинга операционок, то в ней такие предусловия контролируются при помощи подсистемы выделения ресурсов.

S>>Впрочем, в этом ты тоже неправ. Потому что из разрозненных контрактов ничего полезного получить нельзя. Это очень легко доказать — ведь если у нас есть F() с полным контрактом и G() без контракта, то любая H() = { F(); G() } тоже будет без контракта.


ЮЖ>И что ты этим доказал ? хотел ведь это: "из разрозненных контрактов ничего полезного получить нельзя". Снабдим G контрактом и твое утверждение станет неверным.

Что значит "снабдим"? Откуда мы возьмем контракт на G()? Его нет, G() — это твое "окно в уязвимость". Более того, у нас в системе есть 99 таких G и только 1 такая F. Сколько усилий мы потратим на снабжение контрактами всех G?

ЮЖ>Для тебя они смысла не имеют(хотя выше: "контракты — вещь замечательная"), потому как у тебя все полностью недетерминировано. А у меня есть гарантии на компоненты, на системы созданные из таких компонентов. Но. Я прекрасно отдаю себе отчет о существовании "vulnerability window" и связанных проблемах. Только вот они потому и "window" поскольку их размеры не такие большие(так бывает, если у тебя такого не бывает, это не значит что это невозможно). ПО ведь еще чем-то занимается кроме как вызывает ReadFile.

Если посмотреть на результат профайлера, то всё остальное, как правило, будет занимать пренебрежимо малое время. Давай конкретно — чем таким может заниматься софтина, чтобы ее быстродействие можно было оценить контрактом.

ЮЖ>Дан use case(или набор). Для него, помимо всего прочего указываются требования по производительности(мы ведь о таких ситуациях говорим).


ЮЖ>Реализуем:


ЮЖ>Вариант 1: Без привлечения сторонних компонентов. Например алгорирм сортировки. Здесь, если реализация не обеспечивает заявленных требований, то это баг реализации. Попытки назвать исправление багов "оптимизацией", — запудривание мозгов.


Отличный пример. Комментирую:
1. Сортировка в реальной жизни — крошечный кирпичик реальной системы, который никогда не быает частью use-case. Примеры реального use-case можно посмотреть, допустим, на tpc-c.
2. Ок, пусть будет сортировка. Что такое "требование по производительности"? На уровне пользователя это время работы.
К сожалению, для реальных случаев невозможно дать гарантий времени работы для сортировки без привлечения измерительных инструментов. С твоей точки зрения, все имеющиеся реализации — с багами. Поясняю почему: мы не знаем заранее того, какие данные будут сортироваться. Очень немного алгоритмов имеют хорошие гарантии наихудшего времени сортировки. Mean time может сильно отличаться от Worst time, и нас это может устраивать, а может и нет.

ЮЖ>Вариант 2: Имеются компоненты которые можно использовать. У каждого компонента есть свои pre requirements. Во-первых надо отдавать себе отчет в том, что невыполнение этих требований ни к чему хорошему не приведет. Так же у каждого компонента есть "описание" результата.

Покажи мне хоть какую-то прикладную библиотеку с таким "описанием" результата, по которому мы поймем, подойдет ли она по производительности.
Вот например, в рамках нашего use-case нужно отпарсить некий XML. Вход — строка (пусть в памяти), выход — DOM. Есть сотни библиотек, которые это делают. Кого выберем? Сколько будет стоить выбор в терминах затраченного времени?

ЮЖ>Вопрос. Как мы будем выбирать один компонент из нескольких(решающих определенную задачу)? На основе чего?

ЮЖ>Правильный и единственный ответ: используя контракты, если их нет — придется мерить(не важно что, но это эквивалентно созданию своих контрактов).
Непонятно. Вот у нас есть сложный use case. Его, очевидно, нужно строить из многих компонентов. Если для него есть готовые компоненты, то нет и программистской работы.
Контракт у нас есть на весь use-case. Каким образом мы выведем требуемые контракты для компонентов? Да никаким. Это еще более сложная задача, чем построить контракт для Use-case из готовых контрактов компонентов.

ЮЖ>Дальше. use case реализован.

ЮЖ>Через некоторое время встает вопрос о повышении производительности(если это из-за багов, то см. выше). Повышение производельности здесь опять называется оптимизацией. А вот на более высоком уровне происходит изменение требований, и оптимизация выглядит просто как попытка подогнать существующее решение к новым требованиям.
Совершенно верно. Более того, в 99% случаев никаких требований заранее нет. Ну то есть есть какие-то приблизительные соображения о том, что должно работать гладко. Сколько для этого нужно FPS, никто не знает. Какая будет аппаратура доступна к моменту выхода софта, никто не знает.
В каких условиях будет работать софтина — никто не знает. Требования появляются после того, как готов прототип. Например "время проведения заказа должно быть в пределах 1 секунды"

ЮЖ>Это аналогично разгону компьютера вместо смены начинки.

Непонятно, почему. Разгон и смена — это два варианта решения. Решение мы принимаем только исходя из результатов анализа.
ЮЖ>С аналогичными проблемами. Меняются режимы работы всех связанных компонентов, возникают нарушения контрактов, появляются скрытые неучтенные зависимости.
Скрытые неучтенные зависимости есть всегда.
ЮЖ> Дополнительные тесты не появляются практически никогда...
Это непонятно. Всё как раз наоборот: добавляем тесты, и на их основе принимаем решения.

ЮЖ>Это то к чему приводит твой подход с оптимизацие "по необходимости".

Да нет. Мой подход приводит к работоспособным приложениям, удовлетворяющим запросы кастомеров.

ЮЖ>Понятно что в практически любых ситуациях найдутся эффективные приемы работы, только вот лечить надо причину, а не симптомы.

Всё как раз наоборот: причину лечить как правило невозможно. Более того, это не нужно никому. Это примерно как говорить "ну что же вы, надо было с самого начала выбирать QNX для платформы. А так я ничего не могу сделать с вашим плагином к аутлуку. Его тормоза — это симптомы, а причина — в том, что в винде memory manager не дает никаких гарантий".

ЮЖ>Только не надо говорить "добро пожаловать в реальный мир" — это все равно что говорить "все побежали, и я побежал. присоединяйся".

Нет, не то же самое. Это, во-первых, robust подход — он дает результаты даже тогда, когда предварительная работа не была проведена.
Это возможность отложить расходы, и даже если в итоге они окажутся выше, чем при плановом подходе, с точки зрения конечного результата это может оказаться выгоднее.
Во-вторых, это понимание глубинного принципа рыночной экономики — satisficing. Он состоит в том, что нам важнее не абсолютная производительность/качество/итд, а достаточная.

ЮЖ>Я вот в последнее время все больше склоняюсь к тому, что профайлер — это просто одно из средств поиска ошибок в контрактах или реализации.

Совершенно верно! Это средство поиска ошибок. Это не средство исправления ошибок. Я не знаю, почему ты решил, что профайлер исправит ошибки. Он всего лишь поможет подсказать, куда смотреть.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[21]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 05.09.08 08:53
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Многопоточность, кеширование...

S>И?
Факт отстается фактом.
S>Многопоточность дает крайне труднопредсказуемые результаты. К примеру, на одноядерной машине CPU-bound задачи параллелить не только бессмысленно, но и вредно.
S>Кэширование дает труднопредсказуемые результаты, т.к. без реальных данных мы не только не знаем cache hit ratio, но и не можем предсказать влияние роста потребления памяти на другие части системы, которые на первый взгляд никак с этим не связаны. Я имел опыт подобных решений.
И что? Представь современный процессор с отключенными кэшами.

S>>>Хрен там. Видишь ли, мои утверждения о системе базируются не на предсказаниях, а на измерениях.

ЮЖ>>Неа. все гораздо хуже. В непредсказуемой системе ты по результатам измерений предсказываешь дальнейшее поведение.
S>Не обязательно. Дальнейшее поведение мы прогнозируем очень редко. Мы делаем всё наоборот: делаем тестовую инсталляцию, замеряем поведение, и после этого даем некоторые гарантии. Но мы не даем никаких гарантий для систем, выходящих за пределы тестовой инсталляции.
Антон, проснись. Это — контракты. Для них дается гарантии при соблюдении некоторых условий.
Контракт не это не только 'assert(a > 0)' — это любая документированная(не важно каким способом) особенность. Некоторые можно вывести из других, некторые нет, неважно. Важно наличие.

S>То есть если мы намерили на одной коробке 20000 пользователей, то мы гарантируем, что мы столько выдержим.

Опять часть контракта.

S>Мы понимаем, что двумя коробками мы обслужим больше, но не знаем сколько именно.

Опять часть контракта.

S>Факторов слишком много, чтобы их учесть. Если кого-то интересует 30000, то мы ставим две коробки, и опять мерим. Если не получилось 30000, то мы смотрим (естественно, при помощи профайлера и других инструментальных средств), где оказался боттлнек, и чиним его. Заранее сказать, где он будет, невозможно — к примеру, глючный DNS может свести на нет ширину полосы гигабитного езернета.

Вот ты говоришь — невозможно предсказать, и тут же приводишь в качестве примера DNS. =)

S>tcp/ip вообще весь устроен так, что его поведение можно только измерить, и практически невозможно предсказать. Требовать вместо tcp/ip транспорт с QoS — это оверкилл для большинства практических случаев.

Зависит от требований.

ЮЖ>>Только вот твои предсказания в корне отличаются от моих, которые базируются на контрактах.

S>Совершенно верно. Моим — можно верить. Потому, что у меня есть test report, в котором бесстрастная машина продемонстрировала конкретный воспроизводимый результат.
Это можно рассматривать как контракт, но только в точно таких же условиях. В таких же условиях этому можно верить, в других — нет.

S>В случае контрактов нужно верить тому, что процедуры вывода контрактов системы из контрактов компонентов были проведены корректно.

Контракты — это намного больше того, о чем ты думаешь.

ЮЖ>>Нет, только те компонеты, в которых она используется, и которые не дают контрактов.

S>Отлично, у нас есть 150 компонентов, которые используют FileRead. Или одна компонента, но она используется в 150 местах — от природы не уйдешь; если у нас есть 150 разных стеков, которые уперлись в FileRead, то их всё равно 150.
Да абсолютно все равно что там используется внутри компонента. Это детали реализации. Посмотри на это с точки зрения существования контрактов.

S>При этом 149 из них могут не влиять на производительность, потому что вызываются очень редко. И только 1 лежит на критическом пути.

Это потому что окружение другое. Кто-то вызывает FileRead.

S>>>контракты — вещь замечательная. Особенно, если их поддерживает компилятор.

ЮЖ>>Да какой нафиг компилятор? Берем банальные предусловия — "Для установки операционной системы требуется наличие как минимум N Mb оперативной памяти" Куда будем вставлять компилятор?
S>Как куда? Всё наоборот: компилятор должен нам сказать, сколько памяти требуется для установки операционной системы.
Компилятор на клиенте? =)

S>Проверку этого условия мы вставляем в инсталлятор.

Как компилятор проконтролирует это? =)

S>Если мы говорим об автоматической системе провижнинга операционок, то в ней такие предусловия контролируются при помощи подсистемы выделения ресурсов.

Неважно чем они контролируются.

S>>>Впрочем, в этом ты тоже неправ. Потому что из разрозненных контрактов ничего полезного получить нельзя. Это очень легко доказать — ведь если у нас есть F() с полным контрактом и G() без контракта, то любая H() = { F(); G() } тоже будет без контракта.


ЮЖ>>И что ты этим доказал ? хотел ведь это: "из разрозненных контрактов ничего полезного получить нельзя". Снабдим G контрактом и твое утверждение станет неверным.

S>Что значит "снабдим"?
Где твое доказательство выделенного ? Будешь манимулировать словом "разрозненных" ?

S>Откуда мы возьмем контракт на G()? Его нет, G() — это твое "окно в уязвимость". Более того, у нас в системе есть 99 таких G и только 1 такая F.

Даже одна F лучше чем 0. Окон стало меньше.

S>Давай конкретно — чем таким может заниматься софтина, чтобы ее быстродействие можно было оценить контрактом.


Например, запросы в SQL сервере. Только не надо опускаться на уровеь реализации. Ты же не говоришь что тормозит ReadFile(например). Ты не смог обеспечить предусловия(существования индексов, и т.п.). В результате full table scan. Вот они контракты. В документации.

ЮЖ>>Дан use case(или набор). Для него, помимо всего прочего указываются требования по производительности(мы ведь о таких ситуациях говорим).


ЮЖ>>Реализуем:


ЮЖ>>Вариант 1: Без привлечения сторонних компонентов. Например алгорирм сортировки. Здесь, если реализация не обеспечивает заявленных требований, то это баг реализации. Попытки назвать исправление багов "оптимизацией", — запудривание мозгов.

S>
S>Отличный пример. Комментирую:
S>1. Сортировка в реальной жизни — крошечный кирпичик реальной системы, который никогда не быает частью use-case.
Согласен, тут я промазал.

S>2. Ок, пусть будет сортировка. Что такое "требование по производительности"? На уровне пользователя это время работы.

Для пользователя алгоритма (программиста) — нет.

S>К сожалению, для реальных случаев невозможно дать гарантий времени работы для сортировки без привлечения измерительных инструментов.

Легко, например O(N^2). Это гарантия.

S>С твоей точки зрения, все имеющиеся реализации — с багами. Поясняю почему: мы не знаем заранее того, какие данные будут сортироваться. Очень немного алгоритмов имеют хорошие гарантии наихудшего времени сортировки.

))
Во-первых: В таких случаях _всегда_ исполозуется Worst time.

Во-вторых: Какие могут быть Mean/Wrost time для O(N^2) ?
Они могут быть только для конкретных реализаций. Причем все константы вынятся(попутно там с сами собой добавляются/элиминируются и т.п.) "за скобки" на верхний уровень. Вот скажи зачем мне(зная O(N^2)) знать Worst/Mean time, которые нужно мерить(!) для каждого(!) компонента. (компоненты ведь могут использоваться по отдельности).

Баг в моей интерпретации — если вместо O(N) — по факту О(N^2).

S>Mean time может сильно отличаться от Worst time, и нас это может устраивать, а может и нет.

Используя такие утверждения хороших контрактов ты не добъешся.

ЮЖ>>Вариант 2: Имеются компоненты которые можно использовать. У каждого компонента есть свои pre requirements. Во-первых надо отдавать себе отчет в том, что невыполнение этих требований ни к чему хорошему не приведет. Так же у каждого компонента есть "описание" результата.

S>Покажи мне хоть какую-то прикладную библиотеку с таким "описанием" результата, по которому мы поймем, подойдет ли она по производительности.
S>Вот например, в рамках нашего use-case нужно отпарсить некий XML. Вход — строка (пусть в памяти), выход — DOM. Есть сотни библиотек, которые это делают. Кого выберем? Сколько будет стоить выбор в терминах затраченного времени?

Но вооще то я тебя спрашивал об этом одной строкой ниже:
ЮЖ>>Вопрос. Как мы будем выбирать один компонент из нескольких(решающих определенную задачу)? На основе чего?
Жду ответа.

ЮЖ>>Правильный и единственный ответ: используя контракты, если их нет — придется мерить(не важно что, но это эквивалентно созданию своих контрактов).

S>Непонятно. Вот у нас есть сложный use case. Его, очевидно, нужно строить из многих компонентов. Если для него есть готовые компоненты, то нет и программистской работы.
S>Контракт у нас есть на весь use-case. Каким образом мы выведем требуемые контракты для компонентов? Да никаким.
Кгхм. Опять стена непонимания.

S>Это еще более сложная задача,

Надо обеспечить поиск с логарифмической сложностью(это контракт 'для use-case'). Почему ты не будешь использовать пузырек ?

S>чем построить контракт для Use-case из готовых контрактов компонентов.

ты видимо о чем-то о своем.


ЮЖ>>Дальше. use case реализован.

ЮЖ>>Через некоторое время встает вопрос о повышении производительности(если это из-за багов, то см. выше). Повышение производельности здесь опять называется оптимизацией. А вот на более высоком уровне происходит изменение требований, и оптимизация выглядит просто как попытка подогнать существующее решение к новым требованиям.
S>Совершенно верно. Более того, в 99% случаев никаких требований заранее нет.
Ууу... Как ты поймешь что делаешь то что нужно?

S>Ну то есть есть какие-то приблизительные соображения о том, что должно работать гладко.

Это заказчики так говорит.

S>Какая будет аппаратура доступна к моменту выхода софта, никто не знает.

S>В каких условиях будет работать софтина — никто не знает. Требования появляются после того, как готов прототип.
Ну слава богу.

S>Например "время проведения заказа должно быть в пределах 1 секунды"

Нормальное требование верхнего уровня.

ЮЖ>>Это аналогично разгону компьютера вместо смены начинки.

S>Непонятно, почему. Разгон и смена — это два варианта решения.
Ты сможешь разогнать O(N^2) до O(N) ?

ЮЖ>> Дополнительные тесты не появляются практически никогда...

S>Это непонятно. Всё как раз наоборот: добавляем тесты, и на их основе принимаем решения.
Стоп, стоп. я про другие тесты. которые тестируют функционал. В описанном случае меняются контракты.


ЮЖ>>Понятно что в практически любых ситуациях найдутся эффективные приемы работы, только вот лечить надо причину, а не симптомы.

S>Всё как раз наоборот: причину лечить как правило невозможно.
Причина как раз в том что выбирают O(N^2) вместо O(N) (фигурально выражаясь, для ясности).

S>Во-вторых, это понимание глубинного принципа рыночной экономики — satisficing. Он состоит в том, что нам важнее не абсолютная производительность/качество/итд, а достаточная.

Достаточное качество/итд бывает оочень разным.


S>Я не знаю, почему ты решил, что профайлер исправит ошибки. Он всего лишь поможет подсказать, куда смотреть.

Я не знаю почему ты решил что я решил...
Re[22]: Почему преждевременная оптимизация - корень всех зол
От: Sinclair Россия https://github.com/evilguest/
Дата: 05.09.08 09:54
Оценка: 1 (1) +3 -1
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Факт отстается фактом.

Где факт-то??? Факт в студию.

ЮЖ>Антон, проснись.

Я как раз не сплю
ЮЖ>Это — контракты. Для них дается гарантии при соблюдении некоторых условий.
ЮЖ>Контракт не это не только 'assert(a > 0)' — это любая документированная(не важно каким способом) особенность.
Примеры контрактов в студию.
ЮЖ>Некоторые можно вывести из других, некторые нет, неважно. Важно наличие.
Как это неважно??? Мне лично важно не наличие, а способ получения. Потому, что я не верю в контракты, которые мне спустятся как манна небесная. Если пренебречь способом получения, то можно вообще просто считать, что все программы уже написаны. Неважно, как — важно просто наличие.
Так что пример вывода контракта на производительность — в студию. Без примера продолжаю считать твою позицию эротическими снами подростка.

S>>Мы понимаем, что двумя коробками мы обслужим больше, но не знаем сколько именно.

ЮЖ>Опять часть контракта.
Что именно "часть контракта"? То, что мы ничего не знаем? Практическая ценность такого контракта = 0.

ЮЖ>Вот ты говоришь — невозможно предсказать, и тут же приводишь в качестве примера DNS. =)

Для тех, кто в танке, поясняю: это был пример непредсказуемого фактора. Этих факторов — сотни, и я знаю всего про три из них. Что делать с остальными?

ЮЖ>Зависит от требований.

А зачем нам завышенные требования? Улучшение качества еще на 5% потребует увеличения стоимости в 20 раз. Кому это нужно?

ЮЖ>Это можно рассматривать как контракт, но только в точно таких же условиях. В таких же условиях этому можно верить, в других — нет.

Правильно.

ЮЖ>Контракты — это намного больше того, о чем ты думаешь.

Ну так расскажи. Хватит делать таинственное лицо.

ЮЖ>Да абсолютно все равно что там используется внутри компонента. Это детали реализации. Посмотри на это с точки зрения существования контрактов.

Посмотрел. Есть 150 разных компонентов, контракт производительности которых "неограниченно плохая". Дальше что?

S>>При этом 149 из них могут не влиять на производительность, потому что вызываются очень редко. И только 1 лежит на критическом пути.

ЮЖ>Это потому что окружение другое. Кто-то вызывает FileRead.
Ну и? Где конструктив?

S>>Что значит "снабдим"?

ЮЖ>Где твое доказательство выделенного ?
Юра, я привел доказательство два поста назад. В чем проблема?

ЮЖ>Будешь манимулировать словом "разрозненных" ?

При чем тут слова? Юра, я тебе показал, что одна компонента без контракта "отламывает" контракты у всех, кто ее попользовал. Будем признавать, или будем фигней заниматься?

S>>Откуда мы возьмем контракт на G()? Его нет, G() — это твое "окно в уязвимость". Более того, у нас в системе есть 99 таких G и только 1 такая F.

ЮЖ>Даже одна F лучше чем 0. Окон стало меньше.
Повторяю вопрос: Откуда мы возьмем контракт на G()?

ЮЖ>Например, запросы в SQL сервере. Только не надо опускаться на уровеь реализации. Ты же не говоришь что тормозит ReadFile(например). Ты не смог обеспечить предусловия(существования индексов, и т.п.). В результате full table scan. Вот они контракты. В документации.

)
Юра, это отличный пример. Ну и расскажи мне про контракт на производительность SQL запроса. Давай конкретный пример в студию. А то, может, я и правда не понимаю, что такое "контракт"?

И про то, как ты умеешь оптимизировать запросы без профайлера, т.е. без execution plan и execution statistics. Только не торопись — я за попкорном схожу.


S>>К сожалению, для реальных случаев невозможно дать гарантий времени работы для сортировки без привлечения измерительных инструментов.

ЮЖ>Легко, например O(N^2). Это гарантия.
1. Где константа? Без константы это разговоры в пользу бедных
2. Что такое O(N)? Количество тактов? Количество вызовов процедуры сравнения? Что это?
3. У нас есть пятьдесят алгоритмов с таким хреновым контрактом. На основе чего будем выбирать?

ЮЖ>Во-вторых: Какие могут быть Mean/Wrost time для O(N^2) ?

ЮЖ>Они могут быть только для конкретных реализаций. Причем все константы вынятся(попутно там с сами собой добавляются/элиминируются и т.п.) "за скобки" на верхний уровень. Вот скажи зачем мне(зная O(N^2)) знать Worst/Mean time, которые нужно мерить(!) для каждого(!) компонента. (компоненты ведь могут использоваться по отдельности).
Как это? А какая польза от знания O(N^2)? У тебя сортировка вызывается как часть операции выбора сервера, которая производится как часть операции по восстановлению соединения, которая производится как часть операции по отправке мессаги. Вот на эту последнюю у тебя требование: успеть за 0.1 секунды.
Как понять, плохо ли O(N^2) или хорошо?

ЮЖ>Баг в моей интерпретации — если вместо O(N) — по факту О(N^2).


А в моей — если по факту 0.2 секунды. И неважно, из-за чего это — или из-за того, что сравнение вызвали О(N^2) раз, или что само сравнение заняло слишком много времени.

ЮЖ>Используя такие утверждения хороших контрактов ты не добъешся.

Меня мои контракты вполне устраивают — вся зарплата в белую, просторный кабинет, бесплатный кофе.

ЮЖ>Но вооще то я тебя спрашивал об этом одной строкой ниже:

ЮЖ>>>Вопрос. Как мы будем выбирать один компонент из нескольких(решающих определенную задачу)? На основе чего?
ЮЖ>Жду ответа.
Выберем первую попавшуюся реализацию, которая не содержит очевидных проблем.
А теперь ответь на мой вопрос.

S>>Это еще более сложная задача,

ЮЖ>Надо обеспечить поиск с логарифмической сложностью(это контракт 'для use-case'). Почему ты не будешь использовать пузырек ?
Юра, откуда взялось это "надо"? Кто его придумал такое? У меня требований к сложности поиска не было с тех пор, как я собеседование проходил в 1998 году.
Как, впрочем, и use-case типа "поиск целого числа в массиве". Если вы до сих пор занимаетесь такими юз-кейзами, то вам повезло. Остальным программистам приходится еще и делать что-то полезное.

ЮЖ>Ууу... Как ты поймешь что делаешь то что нужно?

Итеративно, Юра, итеративно. А ты как понимаешь, что делаешь то, что нужно?

S>>Ну то есть есть какие-то приблизительные соображения о том, что должно работать гладко.

ЮЖ>Это заказчики так говорит.
Ну да. А кто еще задачу ставит?


S>>Например "время проведения заказа должно быть в пределах 1 секунды"

ЮЖ>Нормальное требование верхнего уровня.

ЮЖ>>>Это аналогично разгону компьютера вместо смены начинки.

S>>Непонятно, почему. Разгон и смена — это два варианта решения.
ЮЖ>Ты сможешь разогнать O(N^2) до O(N) ?
Может, и не смогу. А вот сделать так, чтобы O(N^2) работал быстрее О(N), или незначительно медленее — очень может быть что и смогу.

ЮЖ>Стоп, стоп. я про другие тесты. которые тестируют функционал. В описанном случае меняются контракты.

У кого меняются контракты?

S>>Всё как раз наоборот: причину лечить как правило невозможно.

ЮЖ>Причина как раз в том что выбирают O(N^2) вместо O(N) (фигурально выражаясь, для ясности).
Это очень упрощенное понимание. Никто не пишет специально плохой код. Пишут код, который должен был работать как надо.
А оказалось, что баланс требований — совсем другой. Вот, к примеру, выбрали список, потому что в него добавление O(1). А пришлось перейти на массив, потому что оказалось, что добавления бывают в 1000 раз реже, чем доступ, а он в списке — O(N). А заранее сказать было невозможно — откуда ты знаешь, что будут делать пользователи сервиса, которого еще и в природе нет?
А может быть, можно не переходить на массив, а просто сделать "кэш" — хранить в списке последний элемент, к которому мы обращались, и это разгонит наши существующие обращения List за счет того, что i у нас распределены неравномерно. И вместо O(N) мы опять получим O(1), которое не по контракту, а на практике.
А главное, что практическому подходу неважно, [i]почему
был выбран список. Мы видим результат. И отматываем назад до того места, где это можно исправить.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: Почему преждевременная оптимизация - корень всех зол
От: Юрий Жмеренецкий ICQ 380412032
Дата: 05.09.08 12:43
Оценка: -2 :)
Здравствуйте, Sinclair, Вы писали:

По пунктам.

-------------

Антон, ты отрицаешь мои доводы на основе своего неудачного опыта(причем не один раз):
Показываю на пальцах:

S>"Но для меня новость, что из низкопроизводительных компонент можно собирать высокопроизводительные."

ЮЖ>>Многопоточность, кеширование...
S>...Кэширование дает труднопредсказуемые результаты... Я имел опыт подобных решений

------------

Ты сам себе противоречишь.
Показываю на пальцах:

S>"Но для меня новость, что из низкопроизводительных компонент можно собирать высокопроизводительные."

ЮЖ>>Многопоточность, кеширование...
S>...Кэширование дает труднопредсказуемые результаты...
ЮЖ>>Факт отстается фактом.
S>Где факт-то??? Факт в студию.
S>"...а просто сделать "кэш... И вместо O(N) мы опять получим O(1)"

------------


Ты не читаешь, то что я пишу.
Показываю на пальцах:

ЮЖ>>например O(N^2). Это гарантия

ЮЖ>> <много всего>, проснись. Это — контракты.
ЮЖ>> Контракт не это не только 'assert(a > 0)'
S>Примеры контрактов в студию.

------------

Я хочу верить что ты знаешь теорию сложности, но твои реплики заставляют сомневаться меня в этом.
Показываю на пальцах:

ЮЖ>>O(N^2).

S>1. Где константа? Без константы это разговоры в пользу бедных

Это на грани фола:
S>O(N^2) работал быстрее О(N), или незначительно медленее — очень может быть что и смогу.

--------------
И еще присутствуют проблемы с логикой.
Показываю на пальцах:

S>Потому что из разрозненных контрактов ничего полезного получить нельзя. Это очень легко доказать — ведь если у нас есть F() с полным контрактом и G() без контракта, то любая H() = { F(); G() } тоже будет без контракта.


Здесь доказано совершенно не то. Те берешь один частный случай и обобщаешь решение.
Для все случаев необходимо рассмотреть, как минимум, варианты {F G} и {G F}, и кроме того, {F F} и { G G }. Вот это ты пытался доказать.
Я тебе давал попытку "срулить" на слове "разрозненных", но ты эту попытку проморгал.

"Будем признавать, или будем фигней заниматься? " (c)
Впрочем, ответ мне не интересен.

--------------

Специально заикнулся про SQL, поскольку ты его знаешь, но на фоне вышесказанного я не могу надеятся на адекватное понимание(или хотя бы желание понять).

Учитывая все написанное, плюс:
S>Меня мои контракты вполне устраивают — вся зарплата в белую, просторный кабинет, бесплатный кофе.

считаю что дальнейший разговор о контрактах и их влиянии на оптимизацию не имеет смысла. В это ветке меня нет. Dixi.
Re[24]: Почему преждевременная оптимизация - корень всех зол
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.09.08 13:15
Оценка: +3
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>считаю что дальнейший разговор о контрактах и их влиянии на оптимизацию не имеет смысла. В это ветке меня нет. Dixi.


Юрий, я понимаю, что ваш разговор с Антоном отбил у вас желание его продолжать. Тем не менее, прошу вас, по возможности:
— все таки дать свое определение понятия "контракт". Поскольку я представляю себе, что такое контракт в системах с DbC. Но вот что такое контракты, которые изложены в документации или комментариях и их влияние на качество/надежность ПО я себе не очень представляю;
— прокомментировать с позиции контрактов вот этот мой вопрос: http://www.rsdn.ru/forum/message/3090969.1.aspx
Автор: eao197
Дата: 05.09.08

— озвучить, над какими типами ПО вам приходится работать. Поскольку из разговоров с вами складываются три версии: a) вы занимаетесь разработкой и/или анализом алгоритмов или b) вы занимается разработкой вычислительного ПО (научные расчеты и пр.), или c) вы занимаетесь разработкой высоконадежного ПО (грубо говоря, ПО для управления ядерными, химическими объектами или ракетами/спутниками).

Буду очень признателен, если вы все-таки ответите.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[19]: Почему преждевременная оптимизация - корень всех зол
От: Valery A. Boronin Россия linkedin.com/in/boronin
Дата: 06.10.08 01:09
Оценка:
оффтоп

S>Проблема всех пуританских подходов — в том, что одна маленькая дырка портит всю картинку.

это пять

PS по теме, что есть профайлер, когда и зачем он нужен — не понимаю о чем тут можно дискутировать столь долго
PPS Можно было бы для продолжения дискуссии в подветке сначала дождаться ответа на вопрос про хэш функции с "контрактами"
Автор: eao197
Дата: 05.09.08
— просто несмотря на гигантский объем написанного пока так и не стало яснее что за "контракты" у их адепта. Впрочем, вижу не меня одного
Автор: eao197
Дата: 05.09.08
это заставило проявить любопытство.
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Re[4]: Почему преждевременная оптимизация - корень всех зол?
От: Mirrorer  
Дата: 06.10.08 06:39
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>При условии, что для этой оптимизации не требуется полностью изменить алгоритм и структуры данных программы. А вот если потребуется — пишите все с начала.

Необязательно все. Интеграционные тесты останутся. Если интрефейс к внешним системам не менять.
Re[5]: Почему преждевременная оптимизация - корень всех зол?
От: jazzer Россия Skype: enerjazzer
Дата: 07.10.08 12:40
Оценка: +1
Здравствуйте, Кэр, Вы писали:

J>>>>если тормоза уже заметны, то, очевидно, это уже не преждевременная оптимизация

Кэр>>>Осталось ответить на вопрос — как они заметны? "На глазок"?
J>>Да, "на глазок".

Кэр>Ваш "глазок" сможет детектировать только общую проблему.

Не так. "Глазок" сможет детектировать наличие проблемы. Напоминаю, мы обсуждаем фразу "как тормоза заметны? — на глазок", а не "как понять, в какой строчке кода тормоза? — на глазок".
Я на всякий случай оставил сверху то, что говорилось, дабы не было искушения поменять предмет обсуждения.
Словосочетания "общая проблема" я вообще не понимаю.

Кэр>Очень (очень!) редко анализ работы программы и ее кода сам по себе подскажет, где решение проблемы. Поможет тут только профайлер запущенный на реальных данных.

Я где-то говорил обратное? (Кстати, где брать реальные данные для нового софта, который только разрабатывается?)

Кэр>Разговоры про оптимизацию без замеров профайлера — пустое сотрясание воздуха. И уж точно не разговор инженеров.

Т.е. если программа тормозит, то ни один инженер не должен говорить, что она тормозит и ее надо бы пооптимизировать, пока не прогонит ее под профайлером?
Интересная логика.

J>>А профайлер только поможет найти конкретное место, которое надо оптимизировать, не более того.

Кэр>Ну да. Всего навсего покажет что является проблемой. Куда уж ему до "глазка"
Совершенно верно, потому что у "глазка" другие задачи — показать, что проблема вообще существует.
И как только показано, что проблема существует — с этого момента оптимизация не является преждевременной.
Преждевременная оптимизация — это когда ты сразу пишешь код, закладывая в него какие-то свои с потолка взятые предположения о том, что будет работать быстрее, т.е. когда ты реально ни разу программу не прогнал и пресловутый "глазок" остался вообще незадействованным.

Кэр>Если вы хотите, чтобы ваши шутки ценились за остроумие — шутите умно и смешно. Если конечно вы не Петросян

Если Вы хотите, чтоб с Вами вообще общались, прекратите хамить.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Почему преждевременная оптимизация - корень всех зол?
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 07.10.08 12:57
Оценка:
Здравствуйте, jazzer, Вы писали:

Кэр>>Если вы хотите, чтобы ваши шутки ценились за остроумие — шутите умно и смешно. Если конечно вы не Петросян

J>Если Вы хотите, чтоб с Вами вообще общались, прекратите хамить.

+1

Просто шуткой про тормозной софт Microsoft ты задел инсайдера за живое
Re[7]: Почему преждевременная оптимизация - корень всех зол?
От: jazzer Россия Skype: enerjazzer
Дата: 07.10.08 13:28
Оценка:
Здравствуйте, Alxndr, Вы писали:

A>Здравствуйте, jazzer, Вы писали:


Кэр>>>Если вы хотите, чтобы ваши шутки ценились за остроумие — шутите умно и смешно. Если конечно вы не Петросян

J>>Если Вы хотите, чтоб с Вами вообще общались, прекратите хамить.

A>+1


A>Просто шуткой про тормозной софт Microsoft ты задел инсайдера за живое


А-а-а... Чувствительный нынче инсайдер пошел. Вон Саттер наоборот, сам все время хохмит на эту тему, и ничего, и вроде не последний в Microsoft человек

А я вообще сказал только то, что MS, в отличие от программистов-одиночек, совершенно начхать, что там кто кричит на форумах о них и их продуктах, пока альтернативные продукты не начнут отъедать у них ощутимую долю рынка. Собственно, даже утверждения, что у MS софт тормозной, в моих словах не было
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Почему преждевременная оптимизация - корень всех зол?
От: minorlogic Украина  
Дата: 07.10.08 17:15
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Ведь оптимизация может привести к переписыванию много чего и даже в рамках одного модуля или класса. Какой смысл в этой фразе?


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


Обычно 90% времени тратится в 10% кода , так что переписывать много не придется
... << RSDN@Home 1.2.0 alpha 4 rev. 1111>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[8]: Почему преждевременная оптимизация - корень всех зол?
От: . Великобритания  
Дата: 08.10.08 19:36
Оценка:
Здравствуйте, nikov, Вы писали:

N>Кстати, предварительная сортировка коллекций и то даст лучший результат, чем вложенные циклы.

Не всегда, возможно что затраты на потребление памяти и мусорщика перевесят код тупых циклов.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: В защиту пузырька
От: . Великобритания  
Дата: 08.10.08 19:40
Оценка:
Здравствуйте, _DAle_, Вы писали:

_DA>Не в тему, но.. всегда интересовало, почему в качестве самой простой (ну или первой в книге) сортировки приводят bubble sort. IMHO, не знающему алгоритмов сортировки школьнику придет в голову скорее алгоритм: находим минимум, меняем с первым, и т.д. Обычный selection sort, простой как топор, еще и эффективнее, чем пузырек.

Может чтобы плавно перейти от алгоритмов к их эффективности. Типа "вот вам пурызрёк — всё работает, но мееедленно, вот давайте поизобретаем что-нибудь более интересное". Показать учащимся, что не всегда факт, что заработало, говорит о том, что задача решена.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[22]: Почему преждевременная оптимизация - корень всех зол
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 09.10.08 05:38
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Легко, например O(N^2). Это гарантия.

Это пять!!!

ЮЖ>Баг в моей интерпретации — если вместо O(N) — по факту О(N^2).

А это совсем круто!

ЮЖ>Надо обеспечить поиск с логарифмической сложностью(это контракт 'для use-case'). Почему ты не будешь использовать пузырек ?

Откуда такие use-case? Это даже не use-case.

S>>Во-вторых, это понимание глубинного принципа рыночной экономики — satisficing. Он состоит в том, что нам важнее не абсолютная производительность/качество/итд, а достаточная.

ЮЖ>Достаточное качество/итд бывает оочень разным.
Достаточно качество итд — когда заказчик говорит "Good enough" и все.
Re[23]: Почему преждевременная оптимизация - корень всех зол
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 09.10.08 06:04
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>>Во-вторых, это понимание глубинного принципа рыночной экономики — satisficing. Он состоит в том, что нам важнее не абсолютная производительность/качество/итд, а достаточная.

ЮЖ>>Достаточное качество/итд бывает оочень разным.
G>Достаточно качество итд — когда заказчик говорит "Good enough" и все.

Ты может забыл, что предметные области бывают разными.
Enterprise — один мир, mission/safety critical — другой, desktop — третий и т.п. И в каждом из них это "good enough" совершенно разное.
Re[24]: Почему преждевременная оптимизация - корень всех зол
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 09.10.08 18:33
Оценка:
Здравствуйте, Alxndr, Вы писали:

A>Здравствуйте, gandjustas, Вы писали:


S>>>>Во-вторых, это понимание глубинного принципа рыночной экономики — satisficing. Он состоит в том, что нам важнее не абсолютная производительность/качество/итд, а достаточная.

ЮЖ>>>Достаточное качество/итд бывает оочень разным.
G>>Достаточно качество итд — когда заказчик говорит "Good enough" и все.

A>Ты может забыл, что предметные области бывают разными.

A>Enterprise — один мир, mission/safety critical — другой, desktop — третий и т.п. И в каждом из них это "good enough" совершенно разное.

И что? В critical программах в достаточные характеристики описываются в формально спецификации.
Re[5]: Почему преждевременная оптимизация - корень всех зол?
От: remark Россия http://www.1024cores.net/
Дата: 12.10.08 09:45
Оценка:
Здравствуйте, Mirrorer, Вы писали:

M>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>При условии, что для этой оптимизации не требуется полностью изменить алгоритм и структуры данных программы. А вот если потребуется — пишите все с начала.


M>Необязательно все. Интеграционные тесты останутся. Если интрефейс к внешним системам не менять.


Тесты — это не часть системы в данном контексте. Их можно было написать и до самой системы.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.