Здравствуйте, Шахтер, Вы писали:
Ш>Да, но без COW копии будут создаваться всегда. Т.е. экономия всё равно есть, пусть и не 100%. А вообще -- не пользуйтесь stl! Ш>Мне кажется, что немутирующие строки с подсчетом ссылок для приложений полезнее.
Здравствуйте, MaximE, Вы писали:
ME>Шахтер wrote:
>> Здравствуйте, c-smile, Вы писали: >> >> CS>Здравствуйте, Шахтер, Вы писали: >> >> Ш>>При копировании вектора создаётся копия данных. При копировании строк накручивается счётчик ссылок. >> >> CS>Это ты про std::string ? >> >> Ну почему. Про любую вменяемую реализацию строк.
ME>Большинство "вменяемых" стандартных строк уже не используют reference counting (Mad COW Disease).
Опять "эксперты" постарались? А тебе не кажется что это не Mad COW Disease, а в Mad Expert Disease? Рассуждения про многопоточность -- типичное горе от "ума". От стандартных строк не требуется thread-safety. Да и самого понятия "поток" в стандарте нет. Вообще странно, никто не требует от целочисленных типов, например, thread-safety. Так почему некотрые "эксперты" стараются засунуть мьютексы в реализацию строк?
А вообще пора вернуться к теме. В оригинальном примере применение строк, основанных на использовании счётчика ссылок, -- это то что доктор прописал. Причем, как я понял, вполне достаточно немутирующих строк -- соответсвенно, никаких проблем с COW нет.
Здравствуйте, folk, Вы писали:
F>Здравствуйте, Шахтер, Вы писали:
Ш>>Да, но без COW копии будут создаваться всегда. Т.е. экономия всё равно есть, пусть и не 100%.
F>С COW усложнится релизация.
Это плата за устранение клонирования.
Ш>>А вообще -- не пользуйтесь stl!
F>Как так? Пользоваться самодельными контейнерами/алгоритмами? Ты зовешь нас в каменный век!
Я зову пользоваться теми средствами, которые отвечают существу задачи. Причем здесь каменный век? Если stl не предоставляет подходящего средства -- значит нужно использовать другое. И не обязательно самописное. Хотя умение делать контейнеры и писать алгоритмы -- по-моему, это часть профессиии.
Ш>>Мне кажется, что немутирующие строки с подсчетом ссылок для приложений полезнее.
F>Это да. В дополнение к контейнеру а-ля StringBuilder.
О том и речь. Классический string из stl не вполне удачно спроектирован. Некоторые напористые люди успели его впаять в стандарт. Как результат -- пользоваться им нельзя. Абзац.
Здравствуйте, Шахтер, Вы писали:
Ш>Смотри первоначальную задачу. И подумай о преимуществах и криворукости.
Да, в плане первоначальной задачи ты прав. Осталось только выяснить, в каких реализациях STL класс std::string основан на подсчёте ссылок, чтобы использовать именно эту реализацию.
PS: ничего против подсчёта ссылок в строчках не имею, уже пяток лет в Билдере юзаю AnsiString, который на нём и основан. И ничего, доволен
Здравствуйте, Шахтер, Вы писали:
ME>>Большинство "вменяемых" стандартных строк уже не используют reference counting (Mad COW Disease).
Ш>Опять "эксперты" постарались? А тебе не кажется что это не Mad COW Disease, а в Mad Expert Disease? Рассуждения про многопоточность -- типичное горе от "ума". От стандартных строк не требуется thread-safety.
Проблема в том, что в реальной жизни многопоточность присутствует. И при использовании в реализации подсчета ссылок синхронизацию просто приходится помещать в класс строки, т.к. в противном случае прикладному коду надо будет осуществлять синхронизацию буквально при каждой операции с "подозрительными" строками — и подозрительными будут, фактически, все строки, переданные "извне", т.к. синхронизация нужна будет не только при работе непосредственно с разделяемыми ресурсами, но и с любой строкой, которая могла быть скопирована из разделяемой. Например, если есть некоторая "универсальная", библиотечная, функция:
то при использовании в реализации std::string подсчета ссылок и отсутствии синхронизации, эту функцию нужно будет как-то переписать, включив в нее синхронизацию доступа к строке, т.к. потенциально строка s1 вполне могла быть когда-то скопирована из строки, использующейся параллельно другим потоком. Но т.к. эта функция библиотечная, сделать это будет очень затруднительно; даже подходящий мьютекс выбрать весьма сложно — ведь о логике работы приложения библиотека понятия не имеет...
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Здравствуйте, Шахтер, Вы писали:
ME>>>Большинство "вменяемых" стандартных строк уже не используют reference counting (Mad COW Disease).
Ш>>Опять "эксперты" постарались? А тебе не кажется что это не Mad COW Disease, а в Mad Expert Disease? Рассуждения про многопоточность -- типичное горе от "ума". От стандартных строк не требуется thread-safety.
ПК>Проблема в том, что в реальной жизни многопоточность присутствует. И при использовании в реализации подсчета ссылок синхронизацию просто приходится помещать в класс строки, ...
1) Безусловно, присутствует. Я, однако, считаю, что не следует нагружать базовые механизмы многопоточной синхронизацией. Вообще, проектирование многопоточных систем довольно сильно отличается от проектирования однопоточных, механически использовать решения, хорошо работающие в однопоточном случае, в многопоточных приложениях нельзя. Заниматься передачей строк бездумно при пересечении границ потоков не стоит.
2) По-хорошему, должен быть выбор. Не должно быть одного string класса на все случаи жизни. Разные задачи требуют разных реализаций.
Здравствуйте, Павел Кузнецов, Вы писали:
ME>>>Большинство "вменяемых" стандартных строк уже не используют reference counting (Mad COW Disease).
ПК>Проблема в том, что в реальной жизни многопоточность присутствует. И при использовании в реализации подсчета ссылок ...
... ПК>то при использовании в реализации std::string подсчета ссылок и отсутствии синхронизации, эту функцию нужно будет как-то переписать
Лично мне кажется что многопоточность и подсчет ссылок в строках это несколько ортогональные вещи.
Голая конструкция типа
static std::string mystring;
принципиально потоко-опасна какой бы механизм не был зашит в std::string.
Я к тому что поддержка многопоточности в библиотеках общего назанчения типа STL
должна предоставлять имплементацию механизмов поддержки "периметра" и инетерфейса потоков, маршаллинг/сериализация, interthread messaging
и т.д.
Т.е. std::string должна быть имплементирована максимально эффективно для работы "внутри" потока, модуля, библиотеки.
А вопросы многопоточности решаться на другом уровне и другими методами.
Самая лучшая поддержка многопоточности — это как ни странно имплементация более менее удобоваримого механизма type_info со товарищи.
Шахтер:
> 2) По-хорошему, должен быть выбор. Не должно быть одного string класса на все случаи жизни.
Конечно, всегда можно написать специальные классы базовых примитивов, в т.ч. и строк, оптимизированных под конкретное приложение. Разве что, в большинстве случаев прикладного программирования это совершенно неэффективно с точки зрения соотношения производительность/стоимость разработки. Don't fix what isn't broken. В том смысле, что в большинстве приложений копирование строк и близко не появляется в первой сотне функций, выделенных профайлером. А если появляется, то обычно более эффективным способом является не переписывание класса строки, а перепроектирование приложения.
> 3) Вместо <...> можно сделать >
Теоретически — да. На практике же, забыв в одном месте написать DetachedCopy(str,str_) вместо str=str_, наведенные, плохо воспроизводящиеся, ошибки можно отлавливать еще очень долго.
В общем, для реализаций std::string, учитывая имеющийся "богатый" интерфейс последней, от подсчета ссылок отказались если не все, то большинство разработчиков стандартных библиотек.
Posted via RSDN NNTP Server 1.9 beta
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Шахтер:
>> 2) По-хорошему, должен быть выбор. Не должно быть одного string класса на все случаи жизни.
ПК>Конечно, всегда можно написать специальные классы базовых примитивов, в т.ч. и строк, оптимизированных под конкретное приложение.
Под конкретное поведение. Поведений гораздо меньше, чем приложений. Ну, собственно, Александреску там что-то такое предлагал -- гибко настраиваемое.
ПК>Разве что, в большинстве случаев прикладного программирования это совершенно неэффективно с точки зрения соотношения производительность/стоимость разработки.
Вы неправильно считаете деньги. Это делается один раз -- хорошо. Или много раз плохо. В рамках написания очередной "экспертной" реализации stl.
ПК>Don't fix what isn't broken. В том смысле, что в большинстве приложений копирование строк и близко не появляется в первой сотне функций, выделенных профайлером.
А вот я, например, не делаю это большинство. Мне регулярно приходится заниматься задачами, где производительность принципиальна. А что касается большинства, то большинство программирует вообще на Бейсике. Для этого большинства сейчас есть .Net. Вот в этом детском бассейне оно и беззаботно развлекается. Прогресс он не стоит на месте. Для типовых задач есть куча RADостей. А над остальным приходиться думать.
Дело в конце концов не в производительности, а в принципе. Программирование -- это управление ресурсами. И начинается оно с мелочей. Если человек не может грамотно подобрать строковый класс, то извините, куда ему более серьёзные задачи решать -- не справиться.
ПК>А если появляется, то обычно более эффективным способом является не переписывание класса строки, а перепроектирование приложения.
>> 3) Вместо <...> можно сделать >>
ПК>Теоретически — да. На практике же, забыв в одном месте написать DetachedCopy(str,str_) вместо str=str_, наведенные, плохо воспроизводящиеся, ошибки можно отлавливать еще очень долго.
Интересно, и сколько таких мест будет? Имея реализацию с подсчетом ссылок, можно без труда её завернуть во враппер и сделать реализацию с клонированием. А вот назад -- фигушки.
ПК>В общем, для реализаций std::string, учитывая имеющийся "богатый" интерфейс последней, от подсчета ссылок отказались если не все, то большинство разработчиков стандартных библиотек.
Всё что вы говорите, на самом деле, лишь подтверждает, что stl плохо спроектирована.
Ш>Это каких, обычных? Если реализация string клонирует строку при копировании, это значит -- кривая реализация.
Если реализация std::string сделана с подсчётом ссылок,
то отрывать руки надо за такую реализацию.
Жил был очень многопоточный проект.
Около 50-ти потоков. Компилялся ГэЦэЦой.
Всё было более или менее хорошо, ровно до того
момента когда в сервер не воткнули второй процессор.
В общем... Не знаю как сейчас, но тогда
нам не удалось заменить в gcc(3.0) stl.
Перешли на сановский компилятор.
Те же яйца, вид в профиль — там был рогвэйв
с по умолчанию включенным счётчиком ссылок.
Теоретически отключить можно, но практически нельзя.
Зато можно STLPort подключить. Что было сделано и в общем и целом помогло...
Вариант с неиспользованием STL рассматривался... Но как "на крайний случай".
P.S. я ничего не имею непосредственно против идеологии подсчёта ссылок.
У нас есть куча классов тем или иным образом использующих подсчёт ссылок.
Проблема, по сути, была в конкретных реализациях, и дизайне класса
std::string, не предусматривающем подсчёт ссылок.
Вот и не надо было его туда прикручивать...
Шахтер wrote:
> ME>Большинство "вменяемых" стандартных строк уже не используют reference counting (Mad COW Disease). > > Опять "эксперты" постарались? А тебе не кажется что это не Mad COW Disease, а в Mad Expert Disease? Рассуждения про многопоточность -- типичное горе от "ума". От стандартных строк не требуется thread-safety. Да и самого понятия "поток" в стандарте нет. Вообще странно, никто не требует от целочисленных типов, например, thread-safety. Так почему некотрые "эксперты" стараются засунуть мьютексы в реализацию строк?
Согласен в том, что строка не должна быть потокобезопасной.
> А вообще пора вернуться к теме. В оригинальном примере применение строк, основанных на использовании счётчика ссылок, -- это то что доктор прописал. Причем, как я понял, вполне достаточно немутирующих строк -- соответсвенно, никаких проблем с COW нет.
Как раз про это и пишет Kevlin Henney в вышеупомянутой статье. Стандартный класс строк спроектирован неряшливо — перегруженный интерефейс, слишком много функционала, чтобы сделать этот класс эффективным. От того и проблема, что когда стандартную строку хотят оптимизировать при помощи COW, приходится запихивать в нее синхронизацию, так как многопоточный код пишется в расчете на то, что строка "тупая" — будет копироваться, когда ее передают по значению.
Павел Кузнецов wrote:
> Проблема в том, что в реальной жизни многопоточность присутствует. И при использовании в реализации подсчета ссылок синхронизацию просто приходится помещать в класс строки, т.к. в противном случае прикладному коду надо будет осуществлять синхронизацию буквально при каждой операции с "подозрительными" строками — и подозрительными будут, фактически, все строки, переданные "извне", т.к. синхронизация нужна будет не только при работе непосредственно с разделяемыми ресурсами, но и с любой строкой, которая могла быть скопирована из разделяемой.
Многопоточные приложения требуют более аккуратного проектирования. Результатом этого проектирования должен быть такой дизайн, когда между потоками очень узкие интерфейсы, в которых необходима синхронизация. В этом случае отпадает необходимость синхронизировать все и вся.
[]
> Всё что вы говорите, на самом деле, лишь подтверждает, что stl плохо спроектирована.
std::string никогда не входил в stl, в чем ты можешь найти подтверждение посмотрев как наскорую "прикручены" к ней итераторы. stl и стандартная библиотека не синонимы.
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>...Don't fix what isn't broken...
А если дизайн broken изначально? Или не подходит к задачам реального мира в 70% случаев?
Пример: XML/HTML — аттрибуты и их значения повторяются примерно на 70-90% в одном документе.
Слепая имплементация в стиле
element {
std::vector< std::pair<std::string,std::string>> attributes;
}
Ведет к неоправданному перерасходу ресурсов и чудовищной неэффективности.
Попытка имплементации "как должно" (интернирование строк например) средствами стандартной библиотеки
приводит к неуклюжим, неэффективным и эмпирически недоказуемым конструкциям.
Здравствуйте, c-smile, Вы писали:
CS>Лично мне кажется что многопоточность и подсчет ссылок в строках это несколько ортогональные вещи.
CS>Голая конструкция типа CS>
CS>static std::string mystring;
CS>
CS>принципиально потоко-опасна какой бы механизм не был зашит в std::string.
Пардон, может я не очень хорошо помню имплементацию COW, синхронизация нужна для безопасного изменения каунтера, что с успехом достаточно дешево можно проделать на на многих платформах. А содержимое буфера синхронизировать нет нужды, каждая операция модификации будет строить буфер по новой.
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Здравствуйте, MaximE, Вы писали:
ME>Шахтер wrote:
ME>[]
>> Всё что вы говорите, на самом деле, лишь подтверждает, что stl плохо спроектирована.
ME>std::string никогда не входил в stl, в чем ты можешь найти подтверждение посмотрев как наскорую "прикручены" к ней итераторы. stl и стандартная библиотека не синонимы.
ME>-- ME>Maxim Yegorushkin
Прошу прощения у stl. Делаем поправку -- стандартная библиотека.
Здравствуйте, _nn_, Вы писали:
__>Здравствуйте, Шахтер, Вы писали:
__>Может стоит открыть проект на RSDN и написать нормальный класс строки, aka RSDN::string
Да здесь не нужен проект. Скорее -- ФАК, как писать строки, как впрочем и другие контейнеры. Я этого добра написал столько, что теперь всё что мне нужно пишу чуть ли не с закрытими глазами: берётся код из архива, скрещивается, мутируется, дорабатывем напильником -- и готово.