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++.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.