Здравствуйте, Pavel Dvorkin, Вы писали: S>>Потому что это не С++ здесь некоторые решения приняты за тебя. В частности, написать свою потокобезопасную строку намного сложнее, чем взять готовую. PD>Ну это что-то не очень ясное. Готовая отличается от моей тем, что писал ее не я, вот и все. Если это не так, это лишь значит, что МС использует нечто, что не дает мне использовать. Это, кстати, за ней не раз замечалось еще с ДОС времен.
Почему — даёт. Свой стрингбилдер можно запросто написать.
PD>А блоки памяти в большом количестве порожденные все же надо убирать ? пусть по алгоритму GC, но все же надо...
Нет, не надо. Читать RTFM про то, как работает GC. Он не занимается уборкой.
PD>Это твое утверждение можно преобразовать в эквивалентное "сделаем что-то, а потом посмотрим, что из этого получилось". Профалер же не дух святой, а просто средство посмотреть, что в итоге вышло. И не очень хорошо, что нельзя a priory сделать какие-то соображения, а можно только a posteriory смотреть, что вышло.
Можно. Можно априори. Но для того, чтобы научиться это делать, нужно сначала съесть 16кг соли с профайлером. И только после этого у тебя будет достаточно статистики для того, чтобы интуиция давала правильные подсказки. Интуиция, натренированная на С++, будет постоянно подводить в управляемой среде.
PD>А теперь по существу этой самой иммутабельности. Все же это должно быть свойство не типа , а экземпляра. Экземпляр может быть константой, порождаемой в рантайме, а тип вообще-то не должен. Если нам надо число PI вычислить , то результат должен впоследствии не изменяться, но не потому, что он float или double, а потому что он по смыслу не должен изменяться. А сам тип — не должен быть иммутабельным. Это и к строкам относится.
Нет. Это трагическое заблуждение. Свойство экземпляра даёт слишком мало информации среде исполнения для эффективной оптимизации. PD>Что же касается решения Java/.Net о константности типов, то это полурешение, со своими недостатками, о которых тут говорили. И со своими плюсами, о которых тоже говорили.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Pavel Dvorkin, Вы писали: PD>Угу. С преобразованием к верхнему регистру для каждого проезжаемого символа.
Включая те, которые вылезли за пределы N. У тебя нелимитированный gets в программе — а это классика buffer overrun. И не говори мне, что реальные программы так не пишут — вот только что ажно преподаватель попросил нас написать аналог именно этой программы на С#. Чего уж тогда от студентов ожидать.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Нет, не надо. Читать RTFM про то, как работает GC. Он не занимается уборкой.
Уборкой или не уборкой, но исследованием кучи он занимаетеся или нет ? И время на это исследование от числа объектов там зависит или тоже нет ?
S>Можно. Можно априори. Но для того, чтобы научиться это делать, нужно сначала съесть 16кг соли с профайлером. И только после этого у тебя будет достаточно статистики для того, чтобы интуиция давала правильные подсказки.
Это совсем не плюс. Фактически ты утверждаешь следующее — априорная оценка может базироваться не на свойствах алгоритма или информации о времени выполнения команд/доступа к памяти/и т.д, а только на основе прошлых экспериментов с этой системой по механизму черного ящика. Все это весьма напоминает попытку вставить палец в отверстие машины, созданной Странниками в надежде на то, что движение машины после этого будет ровным и непреодолимым, ну а автора ждет награда от великого и могучего Утеса с ногой на солнце . Я все же предпочитаю ситуацию, когда я о машине что-то знаю, а не просто сую палец в отверстие и жду, что из этого выйдет.
>Интуиция, натренированная на С++, будет постоянно подводить в управляемой среде.
Вот-вот.
PD>>А теперь по существу этой самой иммутабельности. Все же это должно быть свойство не типа , а экземпляра. Экземпляр может быть константой, порождаемой в рантайме, а тип вообще-то не должен. Если нам надо число PI вычислить , то результат должен впоследствии не изменяться, но не потому, что он float или double, а потому что он по смыслу не должен изменяться. А сам тип — не должен быть иммутабельным. Это и к строкам относится. S>Нет. Это трагическое заблуждение. Свойство экземпляра даёт слишком мало информации среде исполнения для эффективной оптимизации.
Попробуй обоснуй. Экземпляр привязан к типу, так что информация о типе всегда налицо. Чего ей не хватает ? Она может даже поместить этот объект в R/O секцию, так что все попытки его модифицировать вызовут exception
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, Sinclair, Вы писали:
S>>Нет, не надо. Читать RTFM про то, как работает GC. Он не занимается уборкой.
PD>Уборкой или не уборкой, но исследованием кучи он занимаетеся или нет ? И время на это исследование от числа объектов там зависит или тоже нет ?
Ты удивишься http://www.rsdn.ru/article/dotnet/GC.xml#E6KAC
PD>>>А теперь по существу этой самой иммутабельности. Все же это должно быть свойство не типа , а экземпляра. Экземпляр может быть константой, порождаемой в рантайме, а тип вообще-то не должен. Если нам надо число PI вычислить , то результат должен впоследствии не изменяться, но не потому, что он float или double, а потому что он по смыслу не должен изменяться. А сам тип — не должен быть иммутабельным. Это и к строкам относится. S>>Нет. Это трагическое заблуждение. Свойство экземпляра даёт слишком мало информации среде исполнения для эффективной оптимизации.
PD>Попробуй обоснуй. Экземпляр привязан к типу, так что информация о типе всегда налицо. Чего ей не хватает ? Она может даже поместить этот объект в R/O секцию, так что все попытки его модифицировать вызовут exception
R/O секцию чего? Стека? Кучи?
PD>Уборкой или не уборкой, но исследованием кучи он занимаетеся или нет ? И время на это исследование от числа объектов там зависит или тоже нет ?
Исследуюется не вся куча. Так как считается, что объекты в ненулевом поколении не изменяются, то на них ссылки учитываются только при изменении, этим кстати обусловлены тормоза при изменеии ссылок в высших поколениях.
Влад хорошо про GC написал http://rsdn.ru/article/dotnet/GC.xml#EFNAC
Ознакомься со статьей полезно.
Поэтому лучше иметь массив структур, нежели массив объектов.
И лучше иметь классы строк имеющих структуру опитимальную для характера её использования. В этом плане зоопарк приветствуется.
и солнце б утром не вставало, когда бы не было меня
C>>Небольшой тест производительности std::wstring в сравнении со StringBuilder.
Х>чем больше я вижу твоего С++ кода, тем больше понимаю почему тебе было мучительно больно на нём писать и ты перелез на C#
Говорю же, писалось на коленке за пять минут. Вам больше нечего сказать кроме перехода на личности? Или Вас так обидело, что "тормозной" дотнет порвал С++ STL, как тузик грелку?
Здравствуйте, gandjustas, Вы писали:
PD>>Попробуй обоснуй. Экземпляр привязан к типу, так что информация о типе всегда налицо. Чего ей не хватает ? Она может даже поместить этот объект в R/O секцию, так что все попытки его модифицировать вызовут exception G>R/O секцию чего? Стека? Кучи?
Просто R/O секцию. Создается в C++ #pragma dataseg(имя). Ей можно поставить атрибуты без W. Некая функция (конструктор констант , получив ее базовый адрес, ставит разрешение по записи, записывает, снимает опять. А что и как там хранить — предмет отдельного разговора. Например, куча константных объектов, которые можно туда добавлять и оттуда удалять (эти методы могут снимать защиту), но функции их изменения получат exception просто по защите на уровне процессора, так как снимать защиту не умеют.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, gandjustas, Вы писали:
PD>>>Попробуй обоснуй. Экземпляр привязан к типу, так что информация о типе всегда налицо. Чего ей не хватает ? Она может даже поместить этот объект в R/O секцию, так что все попытки его модифицировать вызовут exception G>>R/O секцию чего? Стека? Кучи?
PD>Просто R/O секцию. Создается в C++ #pragma dataseg(имя). Ей можно поставить атрибуты без W. Некая функция (конструктор констант , получив ее базовый адрес, ставит разрешение по записи, записывает, снимает опять. А что и как там хранить — предмет отдельного разговора. Например, куча константных объектов, которые можно туда добавлять и оттуда удалять (эти методы могут снимать защиту), но функции их изменения получат exception просто по защите на уровне процессора, так как снимать защиту не умеют.
Выделенное — дикий оверхед, оптимизацей в таком случае и не пахнет.
Оно нафиг не нужно, если неизменяемость доказана компилятором из системы типов.
C>>Небольшой тест производительности std::wstring в сравнении со StringBuilder.
Х>чем больше я вижу твоего С++ кода, тем больше понимаю почему тебе было мучительно больно на нём писать и ты перелез на C#
Так что скажете по делу? Этот "исправленный" код (или по прежнему есть притензии к его качеству?) ни на йоту производительнее того что был и до сих пор в разы проигрывает .NET StringBuilder на операции аккумуляции строки.
Здравствуйте, Хвост, Вы писали:
Х>Здравствуйте, criosray, Вы писали:
C>>Небольшой тест производительности std::wstring в сравнении со StringBuilder.
Х>чем больше я вижу твоего С++ кода, тем больше понимаю почему тебе было мучительно больно на нём писать и ты перелез на C#
Чего словами кидаться. Давай соптимизируй плюсовый код criosray, чтобы он был быстрее, так чтобы там stl остался.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Pavel Dvorkin, Вы писали: PD>>Угу. С преобразованием к верхнему регистру для каждого проезжаемого символа. S>Включая те, которые вылезли за пределы N. У тебя нелимитированный gets в программе — а это классика buffer overrun. И не говори мне, что реальные программы так не пишут — вот только что ажно преподаватель попросил нас написать аналог именно этой программы на С#. Чего уж тогда от студентов ожидать.
Ну да, конечно, если не чего сказать по существу, то надо перевести вопрос на что-то иное. Я этот пример привел для демонстрации совсем другого вопроса, а из твоих слов получается, что я должен был еще и этим специально заняться, только чтобы тебе не к чему было придраться. Не буду — у меня на это времени нет. Никакого отношения к сути вопроса это не имеет.
Здравствуйте, alexey_ma, Вы писали:
И>>>Можно чуть короче, явно не делать проверку на NULL:
И>>>
И>>>int* p = NULL;
И>>>int a = 1, c = 10;
И>>>int b = (p? *p : c) / 100;
И>>>
C>>То есть ради такой єлементарщины надо вводить доп. переменную? _>Так это для наглядности. На самом деле вместо указателя можно изпользовать address-of operator — & для конкретной переменной. Просто такой код не имееет смысла в С++, поскольку адресс переменной не бывает нулевой. Я вообще-то склонен согласиться с Игорем что кода вида _>
_>int* n = null
_>
_>вполне достаточно ,
Так когда будет дан аналог с указателями с++ для
int? a = 1;
int c = 10;
int? b = (a == null ? a : c) / 100;
И давайте без создания лишних сущностей — ввода доп. переменных, ок?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Уборкой или не уборкой, но исследованием кучи он занимаетеся или нет ? И время на это исследование от числа объектов там зависит или тоже нет ?
От числа объектов, в которых нет ссылки наружу, это время никак не зависит. GC знает, что где искать.
PD>Это совсем не плюс. Фактически ты утверждаешь следующее — априорная оценка может базироваться не на свойствах алгоритма или информации о времени выполнения команд/доступа к памяти/и т.д, а только на основе прошлых экспериментов с этой системой по механизму черного ящика.
Нет. Чёрный ящик — это когда ты просто меришь общее время работы машины и вносишь хаотические изменения. Профайлер позволяет тебе посмотреть внутрь машины и получить информацию о времени выполнения команд, доступа к памяти и так далее. PD>Все это весьма напоминает попытку вставить палец в отверстие машины, созданной Странниками в надежде на то, что движение машины после этого будет ровным и непреодолимым, ну а автора ждет награда от великого и могучего Утеса с ногой на солнце . Я все же предпочитаю ситуацию, когда я о машине что-то знаю, а не просто сую палец в отверстие и жду, что из этого выйдет.
Нет, не предпочитаешь. Уже несколько лет ты, вместо того, чтобы что-то узнать о машине, занимаешься попытками перенести эмпирический опыт использования другой машины, на эту.
S>>Нет. Это трагическое заблуждение. Свойство экземпляра даёт слишком мало информации среде исполнения для эффективной оптимизации.
PD>Попробуй обоснуй. Экземпляр привязан к типу, так что информация о типе всегда налицо. Чего ей не хватает ? Она может даже поместить этот объект в R/O секцию, так что все попытки его модифицировать вызовут exception
Это лучший способ просадить производительность. Система типов позволяет заенфорсить иммутабельность без рантайм-проверок — только путём статического анализа кода.
Соответственно другой код точно так же статически может быть оптимизирован — к примеру, потому, что ему не надо проверять неизменность экземпляра при каждом обращении.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, gandjustas, Вы писали:
PD>>Просто R/O секцию. Создается в C++ #pragma dataseg(имя). Ей можно поставить атрибуты без W. Некая функция (конструктор констант , получив ее базовый адрес, ставит разрешение по записи, записывает, снимает опять. А что и как там хранить — предмет отдельного разговора. Например, куча константных объектов, которые можно туда добавлять и оттуда удалять (эти методы могут снимать защиту), но функции их изменения получат exception просто по защите на уровне процессора, так как снимать защиту не умеют.
G>Выделенное — дикий оверхед, оптимизацей в таком случае и не пахнет.
Не особенно такой уж дикий. Все зависит от того, где и как это применять.
G>Оно нафиг не нужно, если неизменяемость доказана компилятором из системы типов.
Да, но оно позволяет иметь неизменяемость независимо от типа .
Здравствуйте, Геннадий Васильев, Вы писали:
ГВ>Мы же, вроде, ропы обсуждали. Да ещё и весьма узкие моменты оных.
Ну так зиппер имеет точно такое же отношение к деревьям (и, следовательно ропам), какое gap имеет к массивам.
Или о нем говорить нельзя потому, что это реальное решение проблемы?
ГВ>Я первый спросил. И вообще — ты сам сказал, что в узле достаточно хранить только длину его собственной подстроки. Вот теперь и рассказывай, как ты будешь в таком дереве что-то искать.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>Уборкой или не уборкой, но исследованием кучи он занимаетеся или нет ? И время на это исследование от числа объектов там зависит или тоже нет ? S>От числа объектов, в которых нет ссылки наружу, это время никак не зависит. GC знает, что где искать.
Хм... Что такое ссылки наружу — я не знаю, а вот про блоки памяти вроде Рихтер говорит, что он их просматривает, ну и дальше — что именно делает.
S>Нет. Чёрный ящик — это когда ты просто меришь общее время работы машины и вносишь хаотические изменения.
Ничего подобного. Отуда ты взял про хаотические изменения ? Наоборот, у меня может быть очень даже серьезный план работы с этим черным ящиком. Например, не зная, как именно протекает некая реакция (механизм), я все же могу , работая с ней в этом плане как с черным ящиком, составить вполне осмысленный план действий по изучению влияния на нее температуры, давления, света и т.д. И вообще читать про планирование эксперимента.
И вносить эти изменения я буду отнюдь не хаотически. Если, конечно, это Черный Ящик, а не эвристическая машина Машкина
>Профайлер позволяет тебе посмотреть внутрь машины и получить информацию о времени выполнения команд, доступа к памяти и так далее.
Ну и что ?
Вот допустим я, отнюдь не гуру в .Net, написал что-то, а быстродействие этого чего-то меня не устраивает. Пустил профайлер — что-то узнал. Как мне это применить для следующей задачи ? Пуд соли я не съел, и не скоро съем. Для C++ все ясно — используешь медленную функцию, поставил не лучший алгоритм N^2 вместо Nlog(N), память выделяешь не оптимально. Все так или иначе документировано и от наличия или отсутствия опыта у меня не очень зависит. Нашел bottleneck — определи суть — больше так не делай. Не потому, что профайлер показал его, а по определенной сути. В принципе я мог бы и без профалера эту суть найти, просто анализом, медленнее, конечно, будет. А ты сам говоришь — попробуешь улучшить — чего доброго ухудшишь, пока пуд соли не съешь и эмпирические правила не освоишь. Вот так не делай, не потому что суть этого плохая, а потому что прошлый раз плохо получилось
PD>>Все это весьма напоминает попытку вставить палец в отверстие машины, созданной Странниками в надежде на то, что движение машины после этого будет ровным и непреодолимым, ну а автора ждет награда от великого и могучего Утеса с ногой на солнце . Я все же предпочитаю ситуацию, когда я о машине что-то знаю, а не просто сую палец в отверстие и жду, что из этого выйдет. S>Нет, не предпочитаешь. Уже несколько лет ты, вместо того, чтобы что-то узнать о машине, занимаешься попытками перенести эмпирический опыт использования другой машины, на эту.
Да нужна она мне как корове седло, эта машина . Я бы давно все о ней узнал, если бы она могла быть всерьез полезна для моих задач. А пока что пользы
от нее — GUI слепить, без которого бы и обйтись вполне можно, да заказчик хочет "сделайте мне красиво". А для того, чем я в основном занимаюсь, эта машина так же пригодна, как эвристическая машина Машкина для предсказания погоды. Еще года 3-4 назад я замерял быстродействие по сравнению с С++ для тех примеров, которые меня интересуют. 3-5% потерю я бы еще стерпел (и то не уверен, я за каждую мсек бьюсь), а уж когда в 1.5-2 раза — всего хорошего.
S>>>Нет. Это трагическое заблуждение. Свойство экземпляра даёт слишком мало информации среде исполнения для эффективной оптимизации.
PD>>Попробуй обоснуй. Экземпляр привязан к типу, так что информация о типе всегда налицо. Чего ей не хватает ? Она может даже поместить этот объект в R/O секцию, так что все попытки его модифицировать вызовут exception S>Это лучший способ просадить производительность. Система типов позволяет заенфорсить иммутабельность без рантайм-проверок — только путём статического анализа кода.
Что-то я опять не понял. Жара, что ли, действует, у нас тут +35
Вот есть экземпляр в R/O секции. Вызываем его const (в смысле C++) метод. Поскольку этот метод срабатывает без сучка и задоринки, то что тут есть R/O, что нет — оверхед нулевой. А поскольку нормальные программы модифицировать константные объекты все же не будут, как правило, пытаться, то в итоге опять же нулевой оверхед. Ну а если кто-то будет — схлопочет exception, вот и все. И никакой проверки тут вообще не надо — пущай процессор проверяет, он и так это всегда делает. Унутре . Так уж он сделан . Страничный механизм, атрибуты страниц и т.д.
Вот на размещение и удаление объектов оверхед будет, тут придется системный сервис дергать, VirtualProtect. Но опять-таки, все зависит от того, как часто и когда его дергать... Если константы создаются пакетом, то можно и один раз. Что-то вроде WriteFileGather vs N раз WriteFile.
S>Соответственно другой код точно так же статически может быть оптимизирован — к примеру, потому, что ему не надо проверять неизменность экземпляра при каждом обращении.
Еще раз — для объекта в R/O секции вообще ничего проверять не надо.
Здравствуйте, Pavel Dvorkin, Вы писали:
G>>Выделенное — дикий оверхед, оптимизацей в таком случае и не пахнет.
PD>Не особенно такой уж дикий. Все зависит от того, где и как это применять.
Решил проверить
int _tmain(int argc, _TCHAR* argv[])
{
MEMORY_BASIC_INFORMATION mbi;
DWORD dwOld;
VirtualQuery(_tmain,&mbi, sizeof(mbi));
DWORD dwTimeStart = GetTickCount();
for( int i = 0; i < 1000000; i++)
VirtualProtect(_tmain,4096,mbi.AllocationProtect,&dwOld);
DWORD dwTimeEnd = GetTickCount();
printf("Time = %f sec\n", ((float)dwTimeEnd - dwTimeStart)/1000);
return 0;
На моей машине (Athlon 4200+ Dual) этот код в Release работает 1.015 сек. То есть на один VirtualProtect уходит микросекунда. А если еще предусмотреть пакетное создание констант , то не на каждое добавление придется VirtualProtect дергать. А уж освободить все можно вообще одним вызовом VirtualFree
Здравствуйте, gandjustas, Вы писали:
C>>>Небольшой тест производительности std::wstring в сравнении со StringBuilder. Х>>чем больше я вижу твоего С++ кода, тем больше понимаю почему тебе было мучительно больно на нём писать и ты перелез на C# G>Чего словами кидаться. Давай соптимизируй плюсовый код criosray, чтобы он был быстрее, так чтобы там stl остался.
Лучше чуточку к реальности приблизить. Скопируем полученные строки в массив:
Это — C#/.Net 2.0 (под рукой другого нет)
const int Count = 25000;
StringBuilder stringBuilder = new StringBuilder();
String[] s = new String[Count];
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < Count; i++)
{
stringBuilder.Append("c1");
s[i] = stringBuilder.ToString();
}
stopwatch.Stop();
Console.WriteLine("append: elapsed {0}", stopwatch.Elapsed);
Console.WriteLine(stringBuilder.Length);
Разрыв превращается в примерно шестикратный в пользу C++ (на 100 тысячах итераций), если тела циклов выглядят примерно так:
String s;
// ...for (int i = 0; i < Count; i++)
{
stringBuilder.Append("c1");
s = stringBuilder.ToString();
}
std::wstring ws1;
for(int i = 0; i < count; ++i)
{
ws.append(L"c1");
ws1 = ws;
}
То есть не массив заполняем строками, а копируем результат каждой итерации в одну и ту же переменную.
Да, если количество итераций увеличить до 200 тысяч, C++ отрывается ещё дальше. Но это .Net 2.0, может быть, в .Net 3.5 всё не так плохо. Для C++ включена оптимизация по скорости, инлайнирование всего, что под руку подвернётся (/Ob2) и глобальная оптимизация.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
C>Так когда будет дан аналог с указателями с++ для
C>
C>int? a = 1;
C>int c = 10;
C>int? b = (a == null ? a : c) / 100;
C>
C>И давайте без создания лишних сущностей — ввода доп. переменных, ок?
Зачем? Подобный код в плюсах не имеет смысла.
Получится что-то вроде :
int a = 0;
int c = 10;
int b = 0;
(*(&b)) = ( &a == NULL ? *(&a) : c) / 100;
А давайте MSDN почитаем :
Nullable types can represent all the values of an underlying type, and an additional null value. Nullable types are declared in one of two ways:
System.Nullable<T> variable
-or-
T? variable
Чем это от указателя отличается ?
Можно какой нибудь менее надуманный пример полезности nullable ?