Re[14]: Inline records
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.10.09 04:19
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>При чем тут быстрые и медленные целые и плавающие точки ? Мы что обсуждаем, скорость целой арифметики по сравнению с вещественной ? Речь вовсе не об этом, а о том, что создается 2 экземпляра.

Тогда напиши явно, что ты имел в виду под "Ответ на это вопрос , возможно, заставит меня пересмотреть то, что я делаю и упростить код."
Я так понял, что ты решишь, что целые точки тебе не нужны, и откажешься от их использования. Другого способа отказаться в данном случае я не вижу.
Наверное, я что-то додумал за тебя. Ок, давай — объясни мне, как простыни бессмысленного boilerplate кода помогут тебе найти узкие места в программе. Кстати, ты каким профайлером пользуешься при оптимизации?

PD>И во втором варианте этот факт присутствует явно, а в первом это можно легко упустить из виду. Написать очень красивую конструкцию, в одну строчку, а в ней такой дьявол порылся, что в действительности там несколько промежуточных экземпляров создается, память тратится и время. Так я предпочитаю явно видеть, что они создаются, тогда я еще подумаю, надо ли.

Еще раз спрашиваю: почему в случае
double x = GetSomeFloat()

тебя не беспокоит создание промежуточных экземпляров, а в случае
(double x, double y) = GetFloatPoint()

уже начинает беспокоить? Где граница?

PD>А эффективность явного и неявного преобразования — одна и та же. По той простой причине, что код один и тот же фактически. Как ни крути, а без конструктора FPoint(IPoint&) никуда не денешься, и он в обоих случаях вызывается.

Ну, в каком-то смысле никуда не денешься. Но, поскольку компилятор C++ достаточно умён, то "вызов конструктора" превратится просто в пару-тройку ассемблерных инструкций, которые выполняют необходимые преобразования. Всё это будет агрессивно инлайниться. То есть abstraction penalty там снижен насколько возможно.

PD>Нет. Просто в С не продумали это как следует, а в С++ исправили. Или, если хочешь, в С руководствовались принципом "да позволим как можно больше", а в С++ — "не позволи то, что слишком рискованно".

Нет, ты всё же определись, есть бесплатный сыр или его нету. Если нету — то все эти новомодные трюки С++ явная мышеловка.
А если есть, то надо понять, откуда вдруг такое предубеждение против всего, чего нету в сегодняшнем С++.


PD>Или ты не в курсе про lint, или сознательно делаешь вид, что не в курсе. Там именно рекомендовалось обязательно использовать lint для такой проверки. Фактически то же самое, но проверку передали сторонней утилите. Не лучшее решение, вот и поправили.

Не, не в курсе. А что именно линт может проверить про K&R? Откуда у него информация из разных compilation unit?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[14]: еще один пример
От: Pavel Dvorkin Россия  
Дата: 14.10.09 04:19
Оценка:
На тебе совсем уж клинический пример

class IPoint{
//...
};
class FPoint
// есть конструктор FPoint(IPoint&)
};
class FPoint3D
{
// есть конструктор FPoint3D(FPoint&)
};

IPoint GetPoint()
{
//
}

Все классы нужны. Ничего удалить нельзя.

FPoint3D fp = GetPoint();

Как красиво! Но дьявол в деталях — здесь три экземпляра создается.

А можно два. Изменим class FPoint3D, добавим конструктор FPoint3D(IPoint&)



И бесплатно, заметь.

А вот если бы я написал

IPoint ip;
GetPointByRef(ip);
FPoint fp1 = ip;
FPoint3D fp3D = fp1;

то я бы сразу задал себе вопрос — зачем я тут ерундой занимаюсь!

IPoint ip;
GetPointByRef(ip);
FPoint3D fp3D = ip;
With best regards
Pavel Dvorkin
Re[15]: Inline records
От: Pavel Dvorkin Россия  
Дата: 14.10.09 04:38
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


PD>>При чем тут быстрые и медленные целые и плавающие точки ? Мы что обсуждаем, скорость целой арифметики по сравнению с вещественной ? Речь вовсе не об этом, а о том, что создается 2 экземпляра.

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

Совершенно верно. Уточню — либо вообще, либо в данном месте.

S>Наверное, я что-то додумал за тебя. Ок, давай — объясни мне, как простыни бессмысленного boilerplate кода помогут тебе найти узкие места в программе.


Я не знаю, что такое бессмысленный boilerplate код, я просто вижу здесь ненужные действия. Подчеркиваю — просто ненужные. Впрочем, лучше смотри мой новый пример, там еще резче. И делать ненужные действия — не нужно. В любом случае.

>Кстати, ты каким профайлером пользуешься при оптимизации?


1.Встроенным в VS2008, хоть и не в восторге от него.
2. QueryPerfomanceCounter + fprintf

PD>>И во втором варианте этот факт присутствует явно, а в первом это можно легко упустить из виду. Написать очень красивую конструкцию, в одну строчку, а в ней такой дьявол порылся, что в действительности там несколько промежуточных экземпляров создается, память тратится и время. Так я предпочитаю явно видеть, что они создаются, тогда я еще подумаю, надо ли.

S>Еще раз спрашиваю: почему в случае
S>
S>double x = GetSomeFloat()
S>

S>тебя не беспокоит создание промежуточных экземпляров, а в случае
S>
S>(double x, double y) = GetFloatPoint()
S>

S>уже начинает беспокоить? Где граница?

Почему ты решил, что в этом примере с double- float меня не беспокоит ? Вполне возможно, что и беспокоит. Вполне возможно, что я решу, что лучше все на double перевести. От задачи зависит. Есть лишь один маленький фактор — здесь крайне мало шансов сделать ошибку, так как преобразование от float к doublt не есть used-defined, и у меня практически нет шансов сделать неправильное преобразование. Для user-defined у меня шансы есть , а при множественных преобразованиях их много

PD>>А эффективность явного и неявного преобразования — одна и та же. По той простой причине, что код один и тот же фактически. Как ни крути, а без конструктора FPoint(IPoint&) никуда не денешься, и он в обоих случаях вызывается.

S>Ну, в каком-то смысле никуда не денешься. Но, поскольку компилятор C++ достаточно умён, то "вызов конструктора" превратится просто в пару-тройку ассемблерных инструкций, которые выполняют необходимые преобразования. Всё это будет агрессивно инлайниться. То есть abstraction penalty там снижен насколько возможно.

Я же и говорю — здесь нет разницы. А вот создать один или 2 экземпляра — есть.

PD>>Нет. Просто в С не продумали это как следует, а в С++ исправили. Или, если хочешь, в С руководствовались принципом "да позволим как можно больше", а в С++ — "не позволи то, что слишком рискованно".

S>Нет, ты всё же определись, есть бесплатный сыр или его нету. Если нету — то все эти новомодные трюки С++ явная мышеловка.

OK. Допустим, при разработке первой версии языка X было принято неудачное решение. В версии 2 его поправили. По моему определению это не есть бесплатный сыр, так как нового ничего не внесли.

S>А если есть, то надо понять, откуда вдруг такое предубеждение против всего, чего нету в сегодняшнем С++.


Очень серьезный вопрос. Да, есть такое предубеждение. Но отвечать сейчас не буду, так как за минуту не ответишь.


PD>>Или ты не в курсе про lint, или сознательно делаешь вид, что не в курсе. Там именно рекомендовалось обязательно использовать lint для такой проверки. Фактически то же самое, но проверку передали сторонней утилите. Не лучшее решение, вот и поправили.

S>Не, не в курсе. А что именно линт может проверить про K&R? Откуда у него информация из разных compilation unit?

Программа lint может обрабатывать несколько заданных входных файлов и библиотек и проверять их на совместимость.

http://lib.ru/MAN/DEMOS210/lint.txt
With best regards
Pavel Dvorkin
Re[15]: еще один пример
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.10.09 04:59
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Все классы нужны. Ничего удалить нельзя.
Ок, это я могу понять.

PD> FPoint3D fp = GetPoint();

PD>Как красиво! Но дьявол в деталях — здесь три экземпляра создается.
А с чего ты это взял? Посмотри дизассемблером на результат работы современного компилятора. Там может вообще не создаваться никаких экземпляров.

PD>А вот если бы я написал


PD> IPoint ip;

PD> GetPointByRef(ip);
PD> FPoint fp1 = ip;
PD> FPoint3D fp3D = fp1;

PD>то я бы сразу задал себе вопрос — зачем я тут ерундой занимаюсь!


PD> IPoint ip;

PD> GetPointByRef(ip);
PD> FPoint3D fp3D = ip;
Вот и я задаю тебе вопрос: зачем ты занимаешься ерундой в виде выписывания лишних строчек? Если их не удастся устранить — то об этом скажет профайлер.
А если удастся — то ты пишешь код, которого вообще "нет". Он не несёт никакой полезной информации — смысл действий от только затуманивает, на результат компиляции не влияет.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: еще один пример
От: Pavel Dvorkin Россия  
Дата: 14.10.09 05:16
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

PD>>Как красиво! Но дьявол в деталях — здесь три экземпляра создается.
S>А с чего ты это взял? Посмотри дизассемблером на результат работы современного компилятора. Там может вообще не создаваться никаких экземпляров.

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

Так что пока аргументов за то, что надо их по крайней мере в программе на ЯВУ создавать, я не вижу. Не нужны они — незачем и писать. Независимо от того, что сделает с этим или не сделает компилятор.

PD>>А вот если бы я написал


PD>> IPoint ip;

PD>> GetPointByRef(ip);
PD>> FPoint fp1 = ip;
PD>> FPoint3D fp3D = fp1;

PD>>то я бы сразу задал себе вопрос — зачем я тут ерундой занимаюсь!


PD>> IPoint ip;

PD>> GetPointByRef(ip);
PD>> FPoint3D fp3D = ip;
S>Вот и я задаю тебе вопрос: зачем ты занимаешься ерундой в виде выписывания лишних строчек? Если их не удастся устранить — то об этом скажет профайлер.

Можно поинтересоваться, как это профайлер скажет мне, удалось ли устранить строчки ? Дизассемблер — еще ладно, но профайлер ?
With best regards
Pavel Dvorkin
Re[17]: еще один пример
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.10.09 05:51
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

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

Но ты как раз предлагаешь именно их и делать!
Явное выписывание конструкторов временных объектов — это как раз неудачные действия.
PD>Тем более, что в дальнейшем небольшое изменение может привести к тому, что компилятор обработает это иначе. Лучше ненужных действий вообще не делать, тогда и смотреть не придется. .

PD>Так что пока аргументов за то, что надо их по крайней мере в программе на ЯВУ создавать, я не вижу. Не нужны они — незачем и писать. Независимо от того, что сделает с этим или не сделает компилятор.

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

PD>Можно поинтересоваться, как это профайлер скажет мне, удалось ли устранить строчки ? Дизассемблер — еще ладно, но профайлер ?

Профайлер явно покажет, сколько времени твоя программа проводит в каких фрагментах кода. Если какая-то строка была выброшена компилятором, то её профиль даст ноль затрат.

Сам по себе дизассемблер как инструмент понимания выбрасывания строчек не нужен — кошмарный на вид асм даёт часто лучшие результаты, чем "красивый" код, вылизанный руками.
Профайлер покажет ахтунг с промежуточными объектами независимо от того, сколько строчек исходного кода было посвящено этому ахтунгу — шесть или одна.
Нет ахтунга — нет повода задавать себе вопросы про временные объекты (именно поэтому я называю их лишними). Есть ахтунг — надо разбираться. Садиться и внимательно смотреть, куда девается время. Может, там надо вручную объяснить компилятору, что оба результата надо передавать через регистры, а не только первый. Может, там делаются глупости типа урезания float до int с последующим расширением обратно в double — всё это не нужно держать "в уме". Всё это станет ясным, как на ладони, после первого же запуска профайлера.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[18]: еще один пример
От: Pavel Dvorkin Россия  
Дата: 14.10.09 06:22
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


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

S>Но ты как раз предлагаешь именно их и делать!
S>Явное выписывание конструкторов временных объектов — это как раз неудачные действия.

Что-то я тебя понимать перестал. Я именно о том и говрю, что эти временные объекты можно устранить!


PD>>Так что пока аргументов за то, что надо их по крайней мере в программе на ЯВУ создавать, я не вижу. Не нужны они — незачем и писать. Независимо от того, что сделает с этим или не сделает компилятор.

S>Совершенно верно. Но из корректной логики ты неожиданным образом делаешь некорректные выводы. Там, где я хочу не писать лишний код, ты настаиваешь на борьбе со средствами сокращения этого кода.

Опять-таки передержка. Я предлагаю не уделять основное влияние размеру кода на ЯВУ (==LOC), а подумать в основном, сколько там объектов создается и все ли они нужны. Да, я не за то, чтобы число LOC. Но уменьшая число LOC, мы не сокращаем код. Это вообще-то совсем разные вещи.


PD>>Можно поинтересоваться, как это профайлер скажет мне, удалось ли устранить строчки ? Дизассемблер — еще ладно, но профайлер ?

S>Профайлер явно покажет, сколько времени твоя программа проводит в каких фрагментах кода. Если какая-то строка была выброшена компилятором, то её профиль даст ноль затрат.

Эхе-хе. Ты хоть с оптимизирующим С++ знаком ? Он тебе запросто из 5 строк сделает кусок кода так, что определить в нем, какие команды относятся к первой строке, а какие — к последней, уже никто не сможет. Нет в релизе С++ построчного анализа, в принципе нет. И отладки нет, по большому счету, хотя ее можно вести, но Quick Watch показывает порой совершенную чушь, потому что и переменной такой как ячейки памяти-то нет.

S>Сам по себе дизассемблер как инструмент понимания выбрасывания строчек не нужен — кошмарный на вид асм даёт часто лучшие результаты, чем "красивый" код, вылизанный руками.


Бывает, не спорю.

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

S>Нет ахтунга — нет повода задавать себе вопросы про временные объекты (именно поэтому я называю их лишними). Есть ахтунг — надо разбираться. Садиться и внимательно смотреть, куда девается время. Может, там надо вручную объяснить компилятору, что оба результата надо передавать через регистры, а не только первый. Может, там делаются глупости типа урезания float до int с последующим расширением обратно в double — всё это не нужно держать "в уме". Всё это станет ясным, как на ладони, после первого же запуска профайлера.

А можно про ахтунг поточнее ? Хотя бы определение дать ? Например, профайлер показал, что на эту функцию уходит 1% времени. Оптимизировать ее или нет ?
With best regards
Pavel Dvorkin
Re[19]: еще один пример
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.10.09 07:20
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Что-то я тебя понимать перестал. Я именно о том и говрю, что эти временные объекты можно устранить!
Нет. Ты говоришь, что вот такая запись:
IPoint ip;
GetPointByRef(ip);
FPoint fp1 = ip;

лучше, чем такая:
FPoint fp = GetPoint();

Потому, что в первом варианте ты явно расписываешь все промежуточные временные объекты. А я тебе объясняю, что бессмысленно говорить о промежуточных временных объектах — они являются артефактами реализации. Более того, вторая запись яснее говорит компилятору о твоих намерениях, увеличивая шансы на устранение бессмысленного кода по переливанию пустого в порожнее.

Или я тебя не так понял?

PD>Опять-таки передержка. Я предлагаю не уделять основное влияние размеру кода на ЯВУ (==LOC), а подумать в основном, сколько там объектов создается и все ли они нужны.

Не надо об этом думать. В этом коде может создаваться от нуля до двух лишних объектов. Важно об этом думать или нет — покажет профайлер.

PD>Да, я не за то, чтобы число LOC. Но уменьшая число LOC, мы не сокращаем код. Это вообще-то совсем разные вещи.

Мы сокращаем объём того, чему нужно уделять внимание.

PD>Эхе-хе. Ты хоть с оптимизирующим С++ знаком ?

Да. А вот в твоём знакомстве с ним я что-то сомневаюсь.
PD>А можно про ахтунг поточнее ? Хотя бы определение дать ? Например, профайлер показал, что на эту функцию уходит 1% времени. Оптимизировать ее или нет ?
Я тебе уже много раз всё объяснял. Если тебя устраивает, в общем, время выполнения задачи, то ничего и оптимизировать не надо. Если не устраивает, и надо отрабатывать в десять раз быстрее, то надо смотреть в профайл. Если там есть какое-то место, которое жрёт 80% времени, а эта строчка 1%, то конечно же её не надо оптимизировать. Устранение всех промежуточных объектов один хрен не поможет нам приблизиться к решению задачи. Надо оптимизировать то место, на которое уходит 80%.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[20]: еще один пример
От: Pavel Dvorkin Россия  
Дата: 14.10.09 07:58
Оценка:
Здравствуйте, Sinclair, Вы писали:

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

PD>>Что-то я тебя понимать перестал. Я именно о том и говрю, что эти временные объекты можно устранить!
S>Нет. Ты говоришь, что вот такая запись:
S>
S>IPoint ip;
S>GetPointByRef(ip);
S>FPoint fp1 = ip;
S>

S>лучше, чем такая:
S>
S>FPoint fp = GetPoint();
S>

S>Потому, что в первом варианте ты явно расписываешь все промежуточные временные объекты. А я тебе объясняю, что бессмысленно говорить о промежуточных временных объектах — они являются артефактами реализации. Более того, вторая запись яснее говорит компилятору о твоих намерениях, увеличивая шансы на устранение бессмысленного кода по переливанию пустого в порожнее.

S>Или я тебя не так понял?


Понял ты правильно. Но я тебе еще один пример привел, где после написания кода

IPoint ip;
GetPointByRef(ip);
FPoint fp1 = ip;
FPoint3D fp3D = fp1;

становится ясно, что промежуточный класс вообще не нужен, а нужен иной конструктор. Его компилятор не сделает. И вообще говоря, это может быть совсем не простым действием, а именно, не исключено, что при конструировании промежуточного объекта не будут выполняться некие действия, которые совсем не нужны, если преоьразовывать прямо из IPoint в Point3D. Ты предлагаешь надеяться, что компилятор все суммеет оптимизировать. Я в этом в общем случае далеко не уверен.

PD>>Опять-таки передержка. Я предлагаю не уделять основное влияние размеру кода на ЯВУ (==LOC), а подумать в основном, сколько там объектов создается и все ли они нужны.

S>Не надо об этом думать. В этом коде может создаваться от нуля до двух лишних объектов. Важно об этом думать или нет — покажет профайлер.

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


PD>>Эхе-хе. Ты хоть с оптимизирующим С++ знаком ?

S>Да. А вот в твоём знакомстве с ним я что-то сомневаюсь.

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

Напоминаю на всякий случай. Не для тебя, для других.

PD>Эхе-хе. Ты хоть с оптимизирующим С++ знаком ? Он тебе запросто из 5 строк сделает кусок кода так, что определить в нем, какие команды относятся к первой строке, а какие — к последней, уже никто не сможет. Нет в релизе С++ построчного анализа, в принципе нет. И отладки нет, по большому счету, хотя ее можно вести, но Quick Watch показывает порой совершенную чушь, потому что и переменной такой как ячейки памяти-то нет.


Есть что по существу возразить ? А если нет — чего стоят твои заверения, что профайлер, дескать разберется на уровне строк ?

PD>>А можно про ахтунг поточнее ? Хотя бы определение дать ? Например, профайлер показал, что на эту функцию уходит 1% времени. Оптимизировать ее или нет ?

S>Я тебе уже много раз всё объяснял. Если тебя устраивает, в общем, время выполнения задачи, то ничего и оптимизировать не надо. Если не устраивает, и надо отрабатывать в десять раз быстрее, то надо смотреть в профайл. Если там есть какое-то место, которое жрёт 80% времени, а эта строчка 1%, то конечно же её не надо оптимизировать. Устранение всех промежуточных объектов один хрен не поможет нам приблизиться к решению задачи. Надо оптимизировать то место, на которое уходит 80%.

Да, с таким подходом только и делать серьезную работу. А мне , например, заказчик выразил благодарность за то, что я оптимизировал код на 1%. И оптимизировал я не то место, где 80% — там я ничего сделать не мог, а именно то, что 2% требовало (суммарно), а теперь 1%.

Не так уж это мало — 1%. Когда ПО работает не на одном компьютере, а на сотнях
With best regards
Pavel Dvorkin
Re[21]: доведение ad absurdum
От: Pavel Dvorkin Россия  
Дата: 14.10.09 08:23
Оценка:
Вот тебе пример, доведенный до абсурда.

Дан линейный двунаправленный список. Надо его перевернуть.

Есть классы

Linked2List на базе ссылочной реализации
Array с возможностью роста
и все конструкторы

Linked2List reverseList = Linked2List(Array(sourceList));

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

Сами по себе действия

выложить список в массив
создать список из массива

вполне осмысленны.

а их конкатенация применительно к данной задаче — абсурдна. Потому что задача решается намного проще. Без всякого выкладывания в массив.

И ты будешь утверждать, что некий компилятор будет настолько оптимизирующим, что разберется в том, что массив здесь не нужен, выкладывать не будет, а всесто этого сам построит код создания из списка реверсного списка ? Код, которого у меня в программе пока что и нет вообще ?
With best regards
Pavel Dvorkin
Re[3]: Inline records
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 14.10.09 08:27
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Кортеж с именованными параметрами. От класса отличается главным образом тем, что как и кортеж поддерживает структурную идентичность. "структурная идентичность" означает, что два экземпляра двух типов имеющих одинаковую структуру (одинаковый список полей) идентичны и могут взаимозаменяемость. Кроме того у записей все поля публичны и записи могут описываться их конструктором (включающим инициализацию всех полей).


Как это — кортеж поддерживает структурную идентичность? Разве кортеж — это не отдельный тип?

class Tuple2<A,B>
class Tuple3<A,B,C>
...


В Scala — так, в Nemerle по другому?
Re[11]: Inline records
От: Юрий Жмеренецкий ICQ 380412032
Дата: 14.10.09 08:29
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Всё не совсем так. То есть, это тоже реализация, хотя и совсем другая, чем предложил Павел.

S>Он, напомню, предложил считать запись (string ret1, int ret2) FuncName(string param1, int param2) эквивалентной void FuncName(string param1, int param2, out int ret2, out string ret1).

Ясно, не уловил акцента. Но out параметры — это в любом случае не выход.

S>В твоём подходе мы требуем создавать именованный тип для возвращаемого значения.

S>Ну, то есть буст предлагает анонимный тупл с анонимными мемберами, но это всё еще не то, чего хочется.

S>Хочется, чтобы всё было в полный рост:

S>1. Возможность описывать имена компонентов тупла, чтобы пользователь меньше встревал. В подходе Павла реализуется само, через имена out-параметров. В твоём — нужно приватно наследоваться от анонимного тупла и задавать маппинг компонентов вручную
S>2. Возможность структурной эквивалентности
S>3. Еще всякие занятные возможности, которые скорее всего расходятся с идеями Влада.

Какие? Поддержка IDE?
Мне, например, импонирует возможность вводить постусловия на результат, вроде таких:

(int x, int y : x < y) F();

Здесь и до зависимых типов недалеко... Можно разрешить использование 'this' и в том числе для использования при проверки предусловий для аргументов + состояние объекта, т.е.
void Container::Remove(Key k : !this.Empty && this.Exists(k))

Можно пойти еще дальше: операция Remove принимает (как бы) тупл из двух элементов — (Container, Key):
void Container::Remove(Container this_ : !this_.Empty, Key k : this_.Exists(k))

Компилятор, встречая выражение (без скобок) 'instance.Remove' может связать все вхождения this_ в списке аргументов и, по возможности, вычислить значения некоторых предикатов (здесь — '!this_.Empty'). Специфический такой карринг.

Одновременно с каждым объектом (instance) компилятору нужно носить (образно выражаясь), список предикатов (+значение), значения которых можно вычислить исходя из постусловий (на состояние). [Для Remove выше постусловие отсутствует для упрощения]. При несответствии значений сохраненного предиката и предиката, вычисленного при обнаружении попытки вызова, следует генерировать compile-time error.

Таким образом, имея предусловие для Remove и, например, такое объявление конструктора:

(this.Empty) Container::Container();

Такой код:
Container c;
c.Remove(key);

приведет к ошибке компиляции, т.к.

Container c; 
// в этой точке - c:{ this.Empty == true }

c.Remove // в этой произойдет обнаружение несоответствия ранее вычисленному значению


С 'Exists(k)' так просто не получится — но есть два варианта: самый простой — автоматически добавлять runtime проверку (Assert или что-то еще), второй — то же что и первый, + нужно исходить из того факта, что помимо совпадения произвольного ключа возможен случай с передачей в Remove значения, полученного от этого же экземпляра контейнера (или эквивалентного находящемуся в нем) — если между этими событиями модификация контейнера не производилась — есть 100% гарантия нахождения значения с указанным ключом в контейнере (можно анализировать и более сложные случаи). В этом случае проверка не нужна. Правда в этом случае компилятор должен поддерживать аннотирование любых объектов. Вобщем получаются predicate types.

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

Т.е. так нормально:
void f(int arg1, int arg2 = x, int arg3 = y);

// Отсутствующие значения принимают значения по умолчанию
f(arg1 = a, arg3 = b);

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

Еще такой вариант использования из головы не выходит:
// Возвращает длину чего-то + что-то 
(int length, X x) f();

// В месте вызова эта длина используется как индекс 
(index, x) r = f();

Т.е. здесь фактически переименование.
Re[21]: еще один пример
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.10.09 09:04
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Понял ты правильно. Но я тебе еще один пример привел, где после написания кода


PD>IPoint ip;

PD>GetPointByRef(ip);
PD>FPoint fp1 = ip;
PD>FPoint3D fp3D = fp1;

PD>становится ясно, что промежуточный класс вообще не нужен, а нужен иной конструктор. Его компилятор не сделает.

OMG. Павел, ты становишься навязчивым. Ничего здесь не становится ясно! Зачем здесь "Иной Конструктор"?
Компилятор обычно достаточно умён для того, чтобы устранить все неиспользуемые промежуточные объекты. Он самостоятельно догадается заменить последовательность присваиваний на одно присваивание.
PD>И вообще говоря, это может быть совсем не простым действием, а именно, не исключено, что при конструировании промежуточного объекта не будут выполняться некие действия, которые совсем не нужны, если преоьразовывать прямо из IPoint в Point3D. Ты предлагаешь надеяться, что компилятор все суммеет оптимизировать. Я в этом в общем случае далеко не уверен.
Я уверен, что в общем случае надо полагаться на компилятор. А вот в частных случаях, когда компилятор не справился, есть два варианта:

1. Профайлер показал, что это имеет какое-то значение для результирующей производительности.
Вот тогда мы начинаем заморачиваться частичными специализациями и дополнительными конструкторами, чтобы помочь компилятору выполнить его работу.
Заметь, что новый конструктор FPoint3d(const IPoint& ip) автоматически будет выбран во всех местах, где написано однострочное присваивание. А твои "вручную выписанные три строки" придётся во всех местах править вручную, даже после введения такого конструктора. Epic Fail.

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


PD>Напоминаю на всякий случай. Не для тебя, для других.


PD>>Эхе-хе. Ты хоть с оптимизирующим С++ знаком ? Он тебе запросто из 5 строк сделает кусок кода так, что определить в нем, какие команды относятся к первой строке, а какие — к последней, уже никто не сможет. Нет в релизе С++ построчного анализа, в принципе нет. И отладки нет, по большому счету, хотя ее можно вести, но Quick Watch показывает порой совершенную чушь, потому что и переменной такой как ячейки памяти-то нет.


PD>Есть что по существу возразить ? А если нет — чего стоят твои заверения, что профайлер, дескать разберется на уровне строк ?

На что возразить? Вопроса никакого ты не задал. Точнее, на тот вопрос, который ты задал — я ответил. Ок, не для тебя, для других, разжую:
Нет, Павел, я ничуть не возражаю против этого потока сознания про поведение оптимизирующего компилятора.

Я возражаю против того, когда ты одной рукой пишешь "оптимизатор всё равно перепашет код так, что фактически выполняемые вычисления не удастся сопоставить с исходным кодом". А второй рукой пишешь "расписывая построчно детальный код присваиваний неявных промежуточных объектов друг другу я могу определить, где выполняются лишние вычисления".

Нужно выбрать какую-то одну из этих взаимоисключающих точек зрения. Это понятно?

PD>Не так уж это мало — 1%. Когда ПО работает не на одном компьютере, а на сотнях

Наверное, оптимизация получилась только благодаря тому, что ты не пользовался неявными преобразованиями. Ну и слава байту на этом.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[22]: доведение ad absurdum
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.10.09 09:04
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Linked2List на базе ссылочной реализации

PD>Array с возможностью роста
PD>и все конструкторы
PD>Linked2List reverseList = Linked2List(Array(sourceList));
Не вижу здесь реверса. Вижу неэффективное копирование одного списка в другой через явно указанный промежуточный массив. Разработчика — уволить, код — заменить.

PD>И ты будешь утверждать, что некий компилятор будет настолько оптимизирующим, что разберется в том, что массив здесь не нужен, выкладывать не будет, а всесто этого сам построит код создания из списка реверсного списка ? Код, которого у меня в программе пока что и нет вообще ?

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

Если твой пример доработать до правдоподобия, то это будет выглядеть примерно так:
var reverseList = sourceList.Reverse();

Здесь, допустим, выбирается неэффективный дефолтный extension method который устроен примерно так:
public static L Reverse<L, T>(this L source)
  where L: IEnumerable<T>
(
    T[] temp = source.ToArray();
    Array.Reverse(temp); 
    if (typeof(L).IsAssignableFrom(temp.GetType)
        return (L) temp;
    else
        return (L)Activator.CreateInstance(typeof(L), temp); 
)

Великая сила этого метода — в том, что он прекрасно работает с любыми потомками IEnumerable<T>, а для массивов еще и достаточно эффективен.
Cлабость этого метода — понятно в чём. Естественно, никакой компилятор не поможет нам сгенерировать эффективный разворачивальщик двунаправленного списка, если его не было.
Зато как только мы заметили такую фигню, мы тут же бежим в реализацию класса Linked2List и реализуем эффективный экземплярный вариант метода Reverse.
Теперь магическим образом компилятор перестаёт выбирать неэффективную реализаци в исходной строчке и во всех местах, где вызывался Reverse.

А вот с тем корявым кодом, который написал ты, компилятор ничего сделать, увы, не в состоянии. Потому что там явно сказано "выкладывай в массив, не умничай".
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[12]: Inline records
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.10.09 09:38
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Какие? Поддержка IDE?

Нет. В императивном языке мне нравится идея не просто "возвращать кортеж", или "возвращать кортеж в анонимный кортеж, описанный по месту", а возможность "указывать, куда девать результаты".
Ну вот если в "обычном" коде мы пишем
var i = SomeFunc(a, b);
GlobalSettings.Instance.Property = SomeOtherFunc(a, b);

то как бы хочется аналогичных мощностей для
(var i, GlobalSettings.Instance.Property) = CombinedFunc(a, b);


ЮЖ>
(int x, int y : x < y) F();

Давайте отделять структурные результаты и постусловия.
В том смысле, что эта фича, имхо, полностью ортогональна кортежам. Сначала надо научиться возвращать
int x : x >= 10 F();

А уже потом подумать про кортежи.

ЮЖ>Здесь и до зависимых типов недалеко... Можно разрешить использование 'this' и в том числе для использования при проверки предусловий для аргументов + состояние объекта, т.е.

ЮЖ>
ЮЖ>void Container::Remove(Key k : !this.Empty && this.Exists(k))
ЮЖ>

Ну вот — видишь, здесь никаких кортежей нет, а предусловия какбы есть.

ЮЖ>Можно пойти еще дальше: операция Remove принимает (как бы) тупл из двух элементов — (Container, Key):

ЮЖ>
ЮЖ>void Container::Remove(Container this_ : !this_.Empty, Key k : this_.Exists(k))
ЮЖ>

Можно, а зачем?

ЮЖ>Одновременно с каждым объектом (instance) компилятору нужно носить (образно выражаясь), список предикатов (+значение), значения которых можно вычислить исходя из постусловий (на состояние). [Для Remove выше постусловие отсутствует для упрощения]. При несответствии значений сохраненного предиката и предиката, вычисленного при обнаружении попытки вызова, следует генерировать compile-time error.

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

ЮЖ>С 'Exists(k)' так просто не получится — но есть два варианта: самый простой — автоматически добавлять runtime проверку (Assert или что-то еще), второй — то же что и первый, + нужно исходить из того факта, что помимо совпадения произвольного ключа возможен случай с передачей в Remove значения, полученного от этого же экземпляра контейнера (или эквивалентного находящемуся в нем) — если между этими событиями модификация контейнера не производилась — есть 100% гарантия нахождения значения с указанным ключом в контейнере (можно анализировать и более сложные случаи). В этом случае проверка не нужна. Правда в этом случае компилятор должен поддерживать аннотирование любых объектов. Вобщем получаются predicate types.

Получится очень просто: либо компилятор статически может проверить гарантию наличия значения по ключу, либо пользователь обязан явно описать уточнение.
То есть вот такое примерно должно иметь место:
public void Test(Dictionary<string, int> data)
{
  data["test"] = GetExternalInt(); // тип data неявно сменился
  
  int a = data["test"]; // компилятор пропускает, потому что там точно лежит int
  
  int b = data["fail"]; // компилятор ругается, потому что нет гарантии наличия ключа
  
  int? c = data["fail"]; // компилятор спокоен, потому что мы явно предусмотрели отсутствие ключа

  int d = 0;  
  if (data.Exists("fail")) // тип data неявно сменился 
    int d = data["fail"]; // компилятор спокоен, потому что в этой ветке есть гарантия наличия ключа
}


ЮЖ>Если же не рассматривать вышесказанное, то имхо, идея именования элементов туплов вполне жизнеспособна, но озвученные аналогии с именами для аргументов начинают немного хромать в присутствии аргументов по умолчанию (для полноты картины):

ЮЖ>Но аналогия для возвращаемых значений тут неприменима. Да, можно игнорировать некоторые элементы, но активное использование такой 'фичи' больше похоже на симптомы проблем с дизайном.
Не вижу никакой хромоты. Не все языки позволяют неявно игнорировать возвращаемые значения. Поэтому здесь как-то ожидается примерно такое:
(_, index, _) = SomeFunc(); // явное игнорирование 1го и 3го результатов

ЮЖ>Т.е. здесь фактически переименование.

Правильно. Вполне себе нормальное переименование.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: доведение ad absurdum
От: Pavel Dvorkin Россия  
Дата: 14.10.09 10:02
Оценка:
Здравствуйте, Sinclair, Вы писали:

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


PD>>Linked2List на базе ссылочной реализации

PD>>Array с возможностью роста
PD>>и все конструкторы
PD>>Linked2List reverseList = Linked2List(Array(sourceList));
S>Не вижу здесь реверса. Вижу неэффективное копирование одного списка в другой через явно указанный промежуточный массив. Разработчика — уволить, код — заменить.

Ну не видишь, и не надо. Подумай сам, может ли тут быть реверс. Может быть, и догадаешься. Его можно даже двумя способами сделать

PD>>И ты будешь утверждать, что некий компилятор будет настолько оптимизирующим, что разберется в том, что массив здесь не нужен, выкладывать не будет, а всесто этого сам построит код создания из списка реверсного списка ? Код, которого у меня в программе пока что и нет вообще ?


Остальное skipped, ввиду того, что ты ушел в сторону. Вопрос не в том, как именно делать Reverse и какие тут extension (это пиши как хочешь), а в том. что не может компилятор за тебя этот код оптимизировать. Я же ясно сказал — ad absurdum. Пример не для того сделан, чтобы его улучшать (это я и сам бы мог), а просто для того, чтобы показать тебе еще раз твою ошибку в утверждении , что компилятор сможет сам все оптимизировать.
With best regards
Pavel Dvorkin
Re[22]: еще один пример
От: Pavel Dvorkin Россия  
Дата: 14.10.09 10:24
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>OMG. Павел, ты становишься навязчивым.


Ну а ты делаешь вид, что являешься непонятливым.

> Ничего здесь не становится ясно! Зачем здесь "Иной Конструктор"?

S>Компилятор обычно достаточно умён для того, чтобы устранить все неиспользуемые промежуточные объекты.

Подменяешь понятия. Устранить неиспользуемые — сможет. Вообще не используемые. Но здесь не о том речь
Я тебе привел пример ad absurdum. Еще раз — не обсуждаем качество его реализации. Но в нем делается создание промежуточного массива и компилятор не сможет устранить его.

>Он самостоятельно догадается заменить последовательность присваиваний на одно присваивание.


Это да. Потому что примитивно. А вот заменить самостоятельно выкладывания списка в массив и обратно не сможет.

S>Я уверен, что в общем случае надо полагаться на компилятор. А вот в частных случаях, когда компилятор не справился, есть два варианта:


S>1. Профайлер показал, что это имеет какое-то значение для результирующей производительности.

S>Вот тогда мы начинаем заморачиваться частичными специализациями и дополнительными конструкторами, чтобы помочь компилятору выполнить его работу.
S>Заметь, что новый конструктор FPoint3d(const IPoint& ip) автоматически будет выбран во всех местах, где написано однострочное присваивание. А твои "вручную выписанные три строки" придётся во всех местах править вручную, даже после введения такого конструктора.

Нет. Они будут написаны один раз, после чего (цитирую себя)

PD>то я бы сразу задал себе вопрос — зачем я тут ерундой занимаюсь!


и заменил.


S>2. Профайлер показал, что это никакого значения для результирующей производительности не имеет.

S>Ну и хрен тогда с ними, с этими промежуточными объектами. Нет повода тратить своё и чужое время на ненужную работу.





PD>>>Эхе-хе. Ты хоть с оптимизирующим С++ знаком ? Он тебе запросто из 5 строк сделает кусок кода так, что определить в нем, какие команды относятся к первой строке, а какие — к последней, уже никто не сможет. Нет в релизе С++ построчного анализа, в принципе нет. И отладки нет, по большому счету, хотя ее можно вести, но Quick Watch показывает порой совершенную чушь, потому что и переменной такой как ячейки памяти-то нет.


PD>>Есть что по существу возразить ? А если нет — чего стоят твои заверения, что профайлер, дескать разберется на уровне строк ?

S>На что возразить? Вопроса никакого ты не задал. Точнее, на тот вопрос, который ты задал — я ответил. Ок, не для тебя, для других, разжую:
S>Нет, Павел, я ничуть не возражаю против этого потока сознания про поведение оптимизирующего компилятора.

S>Я возражаю против того, когда ты одной рукой пишешь "оптимизатор всё равно перепашет код так, что фактически выполняемые вычисления не удастся сопоставить с исходным кодом". А второй рукой пишешь "расписывая построчно детальный код присваиваний неявных промежуточных объектов друг другу я могу определить, где выполняются лишние вычисления".


Так,ясно. Что я пишу и что не пишу — это один вопрос. А вот насчет того, что профайлер, по твоему мнению, может потом сопоставить профилируемый код со строчками текста, мы кажется, разобрались. Не может все-таки. Возразить тебе не удалось, решил поэтому на меня перевести, этот твой прием я хорошо знаю. Не получится. Констатирую : рассуждения твои о возможности профайлера определить, какие строки исполнялись, а какие нет, надо признать неудовлетворительными. В результате падают и все твои прочие выводы, на этой основе сделанные.
PD>>Не так уж это мало — 1%. Когда ПО работает не на одном компьютере, а на сотнях
S>Наверное, оптимизация получилась только благодаря тому, что ты не пользовался неявными преобразованиями.

Оптимизировал я не свой код, а он был на С, так что не могло там быть неявных преобразований. Да и не все ли равно тебе, как я оптимизировал ? Ты лучше на вопрос ответь — нужно ли оптимизировать, если удастся выиграть 1% ? Опять пытаешься уйти от вопроса.
With best regards
Pavel Dvorkin
Re[22]: доведение ad absurdum
От: palm mute  
Дата: 14.10.09 10:54
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:


PD>И ты будешь утверждать, что некий компилятор будет настолько оптимизирующим, что разберется в том, что массив здесь не нужен, выкладывать не будет, а всесто этого сам построит код создания из списка реверсного списка ? Код, которого у меня в программе пока что и нет вообще ?


Есть такие компиляторы, в которых оптимизатор — программируемый. Разработчики библиотек могут посказывать компилятору, какие выражения и как можно упрощать. Например, можно создать правило, что list.reverse().reverse() == list — вуаля, избавились от двух ненужных вызовов и двух лишних копий списка. Glasgow Haskell Compiler — как раз такой компилятор, и в важных библиотеках этим пользуются.
Re[24]: доведение ad absurdum
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.10.09 11:00
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Ну не видишь, и не надо. Подумай сам, может ли тут быть реверс.
Я подумал.
PD>Может быть, и догадаешься. Его можно даже двумя способами сделать
За оба — разработчика уволить. Здесь мы видим нарушение транзитивности конструкторов.

PD>Остальное skipped, ввиду того, что ты ушел в сторону. Вопрос не в том, как именно делать Reverse и какие тут extension (это пиши как хочешь), а в том. что не может компилятор за тебя этот код оптимизировать. Я же ясно сказал — ad absurdum. Пример не для того сделан, чтобы его улучшать (это я и сам бы мог), а просто для того, чтобы показать тебе еще раз твою ошибку в утверждении , что компилятор сможет сам все оптимизировать.

Я не делал такого утверждения. Я делал совсем другое утверждение. Что характерно, все твои примеры подтверждают мои тезисы и опровергают твои. За что большое спасибо.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[23]: еще один пример
От: Sinclair Россия https://github.com/evilguest/
Дата: 14.10.09 11:00
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Подменяешь понятия. Устранить неиспользуемые — сможет. Вообще не используемые. Но здесь не о том речь

PD>Я тебе привел пример ad absurdum. Еще раз — не обсуждаем качество его реализации. Но в нем делается создание промежуточного массива и компилятор не сможет устранить его.
Здесь речь именно о том. Ты вспомни контекст разговора — речь шла про туплы и про способы возврата нескольких аргументов.

Я тебе продемонстрировал причины, по которым предлагаемые тобой варианты "записи на гипотетическом языке" не стоит делать эквивалетными.

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

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

Я, однако, честно пытался объяснять тебе очевидные последствия тех или иных решений, которые возникают при дизайне языка. Видимо — зря, потому что ты только пытаешься увести разговор в сторону. Приводить фрагменты безумного кода, чтобы доказать мне неспособность компилятора справляться с простейшими случаями.
Зачем это всё? Чтобы только уйти от обсуждения основной темы?

PD>Это да. Потому что примитивно. А вот заменить самостоятельно выкладывания списка в массив и обратно не сможет.

1. Теоретически, в частных случаях — может.
2. Нас не интересует в данном контексте общий случай алгоритмической оптимизации. Всё, что мы обсуждаем — способность компилятора устранить конструирование временных объектах при возврате нескольких значений.


PD>Нет. Они будут написаны один раз, после чего (цитирую себя)

PD>и заменил.
По прежнему не понимаю, почему нельзя написать их 0 раз, сэкономив время себе, компилятору, и процессору.

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

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

PD>Не может все-таки. Возразить тебе не удалось, решил поэтому на меня перевести, этот твой прием я хорошо знаю. Не получится. Констатирую : рассуждения твои о возможности профайлера определить, какие строки исполнялись, а какие нет, надо признать неудовлетворительными. В результате падают и все твои прочие выводы, на этой основе сделанные.

Отлично. Увёл, значит, разговор в сторону. Теперь то, повлияют ли лишние строчки boilerplate-кода, написанные вручную, на скорость работы программы, зависит только от того, сможет ли профайлер сопоставить им какие-либо данные. Ну-ну. Удачи.

PD>Оптимизировал я не свой код, а он был на С, так что не могло там быть неявных преобразований. Да и не все ли равно тебе, как я оптимизировал ? Ты лучше на вопрос ответь — нужно ли оптимизировать, если удастся выиграть 1% ? Опять пытаешься уйти от вопроса.

В большинстве случаев — не нужно. 1% — это типичная погрешность измерений. Допускаю, что где-то, в отдельных случаях, это может играть какую-то роль.
Но опять же, получается, что полезность возврата одним махом множества значений теперь зависит только от того, надо ли оптимизировать 1%. Ну не бред ли?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.