Во-первых доклад интересный, спасибо. Во-вторых немного дополнений насчёт COW-строк (в районе 6:15) 1. Я не понимаю, почему за синхронизацией COW строки должна следить сама строка и зачем там появляется атомарный счётчик. Мы можем задокументировать, что она не thread-safe и переложить синхронизацию на пользователя. 2. Как указали в блоке вопросов, семантика перемещения не всегда заменяет COW, потому что речь может идти о многократно совместно используемых строках (скажем тысяча строк "John" одновременно живёт в программе) и тогда COW тупо экономит память. Тут надо было рассказать, что есть нормативные методы решать такие задачи также не изобретая велосипедов, например boost::flyweight 3. Отсутствие в стандарте COW-варианта строки как раз и означает необходимость снова и снова изобретать этот велосипед. В плане предостережения от велосипедостроения тут я бы дал ссылку на какую-нибудь заведомо хорошую реализацию "если вам всё-таки уж очень нужна COW-строчка".
> 1. Я не понимаю, почему за синхронизацией COW строки должна следить сама строка и зачем там появляется атомарный счётчик. Мы можем задокументировать, что она не thread-safe и переложить синхронизацию на пользователя. Смотрите: string a = "abc"; string b = a; Запускаем process(a) в треде 1, запускаем process(b) в треде 2. Мы имеем 2 разных переменных в двух разных тредах, но они обе указывают на одну область памяти, нужно обеспечить из-за COW thread-safe для обоих тогда когда он как раз и не нужен. И на пользователя переложить нельзя, потому что это "кишки".
Кеширование результатов математических операций актуально на старых микроконтроллерах, которые не умеют в аппаратное деление, или где нужно, допустим, очень быстро вычислять индекс массива для записи, а вычисление нетривиальное. Был такой кейс, в самом горячем месте тратилось около 20 us на вычисление индекса массива и маски, которая накладывалась на элемент этого массива. С кешем всё мероприятие стало занимать 2-3 us.
Как embedded разработчик скажу что велосипеды это все что мы пишем. Недавно я написал свой дебагер который имитирует exception-ы. Ну а насчёт строки, я просто промолчу
32:0054:501:22:15 Почему не надо писать на C++. Ты обязан знать контекст каждой используемой «ф-ции» как она зависит от третьей стороны и т.д. Похоже на разбор «кишков» языка, вместо перекладывания этих обязанностей на компилятор
Велосипеды пишут потому что STL часто не предоставляет всех необходимых возможностей. Например почему нет в STL нечто вроде result= join(thread1,thread2,waitMode) по аналогии с WaitForMultipleObjects() в WinApi. По чему в STL до сих пор не перенесли из boost алгоритм trim(). Казалось бы банальная и простая но нужная вещь. (например что бы отсекать пробелы в пользовательском вводе) тоже касается других ф-ций которые привычны для работы со строками.
Потому что стл пропагандирует подход "не плати за то, чем не пользуешься". Любые такие фичи - это усложнение смежных алгоритмов, эксепшенов, оптимизаций, всего на свете. Поэтому вместо предоставляют инструменты для писания своих штук. Не обязательно свои штуки это велосипеды. Если такое уже есть, а твоё работает хуже - то да.
55:27 еще липман в книге которая времен динозавров писал что тип инстанса может быть полиморфным или нет. byVal инстанс - не полиморфный. какой вирт метод звать мы именно поэтому знаем во время компиляции. тут не в final магия
Имелся введу указатель на some_implementation. Какраз если знаем что нет наследников и что класс final и метод имплементирован то можем вызывать сразу этот метод, так как переопределить его никто не сможет (мы final).
Зачем на 16:39 производится работа с атомарным счетчиком при каждом обращении к строке по [], если счетчик должен по сути увеличиваться только при копировании строки и уменьшаться при ее деструкции, выходе из scope'а? При работе с элементом строки через [] мы уже по определению работает с буфером, которым владеем. Не понимаю этой детали реализации.
Представь что у тебя есть 2 объекта строки std::string s1 = "bla bla bla"; std::string s2 = s1; ASSERT(s1.impl == s2.impl); // Для простоты, представим что impl - public Теперь ты хочешь промодифицировать первую строку, а вторую оставить как есть s1[0] = 'B'; ASSERT(s1 == "Bla bla bla"); ASSERT(s2 == "bla bla bla"); ASSERT(s1.impl != s2.impl); Отвечая на твой вопрос: При вызову неконстатного оператора[], должно произойти копирование объекта, иначе после инструкции s1[0] = 'B'; измененятся обе строки.
Ах да, действительно. Спасибо. В С++ получится именно так, я думал о COW вне контекста именно плюсов. Так-то можно вызвать "сделать копию" только перед первым [].
@@MacIn173 а дело не в плюсах, как раз правильно написал Konstantin Vladimirov выше: нужно тонкости синхронизации переложить в зависимости от пользовательского кейса, УНИВЕРСАЛЬНОЙ реализации COW не существует иначе получится просто неэффективное решение.
Тормозить по сравнению с чем? Если вас интересует вопрос, тормозят ли shared_ptr, то да, и очень сильно. Вы сами можете тесты на производительность написать, например, сравнивая как быстрее передавать их в аргументах функций. Разница между передачей по значению и по ссылке может достигать в 10 раз, причем boost::shared_ptr и std::shared_ptr отличаются по скорости в зависимости от компилятора.
Привет всем! сделайте плиз доброе дело? нигде не нашел как это решать на с++, тока на Паскале. Спасибо тому кто решит Спортсмен Василий участвовал в соревнованиях по хоккей болу и получил в личном зачете серебряную медаль. Известно, что участники, получившие одинаковое количество очков, награждаются одинаковыми наградами. Известно, что были разыграны золотые серебряные и бронзовые медали. В задаче не спрашиваются правила хоккей бола. Необходимо только определить, сколько очков набрал Василий. Для решения данной задачи массив лучше не использовать. Формат входного файла На первой строке дано число N (2
Программа написанная под сервис для разгадывания капчи.Программа написана на С++ 6-8 версии. Ничем не упакована и не защищена.Исходника нет. При регистрации акаунта через программу в конце нужно кликнуть подтверждение (Я не робот) . Эту капчу программа не видит - следовательно регистрацию закончить невозможно! Этот момент нужно исправить За более подробной информацией пишите в ICQ - 681354647 Бюджет 100$
Сейчас меня сожгут на костре! )) Но все эти костыли - это проклятие из-за отказа от разработки на ассемблере. И если скажут, что на нем медленно разрабатывать или сложно, то я могу ответить, что или Вы недостаточно разбираетесь в технологии или Вы пишете что-то неправильное.
Проблема в том, что одного Вас, гениального, который на асме пишет так же быстро, как на С++, недостаточно, И клонировать и раздать всем софтверным конторам тоже нельзя)))
Интернет стал отдушиной для закомплексованных идиотов, старающихся создать у окружающих впечатление собственной исключительности, в реальности не разбирающися чуть менее чем ни в чём но при этом имеющих острую жажду признания за несуществующие заслуги или достижения
Спасибо за доклад. Было очень интересно. У Антона отлично поставлена речь. Приятно слушать.
Во-первых доклад интересный, спасибо.
Во-вторых немного дополнений насчёт COW-строк (в районе 6:15)
1. Я не понимаю, почему за синхронизацией COW строки должна следить сама строка и зачем там появляется атомарный счётчик. Мы можем задокументировать, что она не thread-safe и переложить синхронизацию на пользователя.
2. Как указали в блоке вопросов, семантика перемещения не всегда заменяет COW, потому что речь может идти о многократно совместно используемых строках (скажем тысяча строк "John" одновременно живёт в программе) и тогда COW тупо экономит память. Тут надо было рассказать, что есть нормативные методы решать такие задачи также не изобретая велосипедов, например boost::flyweight
3. Отсутствие в стандарте COW-варианта строки как раз и означает необходимость снова и снова изобретать этот велосипед. В плане предостережения от велосипедостроения тут я бы дал ссылку на какую-нибудь заведомо хорошую реализацию "если вам всё-таки уж очень нужна COW-строчка".
> 1. Я не понимаю, почему за синхронизацией COW строки должна следить сама строка и зачем там появляется атомарный счётчик. Мы можем задокументировать, что она не thread-safe и переложить синхронизацию на пользователя.
Смотрите:
string a = "abc";
string b = a;
Запускаем process(a) в треде 1, запускаем process(b) в треде 2. Мы имеем 2 разных переменных в двух разных тредах, но они обе указывают на одну область памяти, нужно обеспечить из-за COW thread-safe для обоих тогда когда он как раз и не нужен. И на пользователя переложить нельзя, потому что это "кишки".
1. C++ - не Rust, который заботливо проследит, чтобы не thread-safe структуры данных не использовались в многопоточном контексте.
Кеширование результатов математических операций актуально на старых микроконтроллерах, которые не умеют в аппаратное деление, или где нужно, допустим, очень быстро вычислять индекс массива для записи, а вычисление нетривиальное.
Был такой кейс, в самом горячем месте тратилось около 20 us на вычисление индекса массива и маски, которая накладывалась на элемент этого массива. С кешем всё мероприятие стало занимать 2-3 us.
8:40 многопоточность была и на одноядерных процессорах, уже на win95/unix/linux можно было словить race condition.
1:41:10, задефайнить форс инлайн пустотой)
урааа... уже давно жду этот доклад.
Классное видео
44:00 полезные советы
Как embedded разработчик скажу что велосипеды это все что мы пишем. Недавно я написал свой дебагер который имитирует exception-ы. Ну а насчёт строки, я просто промолчу
Главное в преждевременную оптимизацию не ввязаться случайно))
Но на 8-битниках нужно конечно стараться, да
32:00 54:50 1:22:15 Почему не надо писать на C++. Ты обязан знать контекст каждой используемой «ф-ции» как она зависит от третьей стороны и т.д. Похоже на разбор «кишков» языка, вместо перекладывания этих обязанностей на компилятор
А на чем писать, если важен перформанс?
Велосипеды пишут потому что STL часто не предоставляет всех необходимых возможностей.
Например почему нет в STL нечто вроде result= join(thread1,thread2,waitMode) по аналогии с WaitForMultipleObjects() в WinApi.
По чему в STL до сих пор не перенесли из boost алгоритм trim().
Казалось бы банальная и простая но нужная вещь. (например что бы отсекать пробелы в пользовательском вводе) тоже касается других ф-ций которые привычны для работы со строками.
Потому что стл пропагандирует подход "не плати за то, чем не пользуешься". Любые такие фичи - это усложнение смежных алгоритмов, эксепшенов, оптимизаций, всего на свете.
Поэтому вместо предоставляют инструменты для писания своих штук. Не обязательно свои штуки это велосипеды. Если такое уже есть, а твоё работает хуже - то да.
неплохо
Ссылки из видео на выступления Chandler Carruth (примерно на 39:25)
ruclips.net/video/FnGCDLhaxKU/видео.html
ruclips.net/video/nXaxk27zwlk/видео.html
55:27 еще липман в книге которая времен динозавров писал что тип инстанса может быть полиморфным или нет. byVal инстанс - не полиморфный. какой вирт метод звать мы именно поэтому знаем во время компиляции. тут не в final магия
Имелся введу указатель на some_implementation. Какраз если знаем что нет наследников и что класс final и метод имплементирован то можем вызывать сразу этот метод, так как переопределить его никто не сможет (мы final).
1:27:58 было бы интересно услышать ответ на тот же вопрос, но с unordered_map
Ох, сколько бед мы поимели из-за старого кода + strict aliasing.
Зачем на 16:39 производится работа с атомарным счетчиком при каждом обращении к строке по [], если счетчик должен по сути увеличиваться только при копировании строки и уменьшаться при ее деструкции, выходе из scope'а? При работе с элементом строки через [] мы уже по определению работает с буфером, которым владеем. Не понимаю этой детали реализации.
Представь что у тебя есть 2 объекта строки
std::string s1 = "bla bla bla";
std::string s2 = s1;
ASSERT(s1.impl == s2.impl); // Для простоты, представим что impl - public
Теперь ты хочешь промодифицировать первую строку, а вторую оставить как есть
s1[0] = 'B';
ASSERT(s1 == "Bla bla bla");
ASSERT(s2 == "bla bla bla");
ASSERT(s1.impl != s2.impl);
Отвечая на твой вопрос: При вызову неконстатного оператора[], должно произойти копирование объекта, иначе после инструкции s1[0] = 'B'; измененятся обе строки.
Ах да, действительно. Спасибо. В С++ получится именно так, я думал о COW вне контекста именно плюсов. Так-то можно вызвать "сделать копию" только перед первым [].
@@MacIn173 а дело не в плюсах, как раз правильно написал Konstantin Vladimirov выше: нужно тонкости синхронизации переложить в зависимости от пользовательского кейса, УНИВЕРСАЛЬНОЙ реализации COW не существует иначе получится просто неэффективное решение.
Если бы велосипеды не переизобретались каждый год, все до сих пор ездили бы на костотрясах :)
30:45
если вылетит исключение которое не поймали то программа аварийно завершится
ну да, так и есть
Его поймали где-то выше, но при этом все равно сработает неструктор на уже удалённых данных
и правда latency от целочисленного DIV, но без кэша надо еще время на i2f добавить, а это ад
Меня мучают смутные сомнения, внутри умных указателей сейчас атомик, не будет ли это тормозить ядра, как в примере с COW строками ?
Поэтому использовать указатели с счётчиком ссылок нужно разумно, для всего остального есть юникптр
Тормозить по сравнению с чем? Если вас интересует вопрос, тормозят ли shared_ptr, то да, и очень сильно. Вы сами можете тесты на производительность написать, например, сравнивая как быстрее передавать их в аргументах функций. Разница между передачей по значению и по ссылке может достигать в 10 раз, причем boost::shared_ptr и std::shared_ptr отличаются по скорости в зависимости от компилятора.
ходила байка про class stroka из яндекса
Где взять такую толстовку?
Вступить в РГ21 стандарта? )
превратили ++ в мутанта # и java.
В продолжение темы про оптимизацию строк: ruclips.net/video/QU63wpGBvjE/видео.html
Сложна, сложна, очинь сложна.
анонимные неймспейсы зло
Трындец! Слава те Господи что кернел писан на голом Ц !!!!
Да большинство кейсов и к Си применимо.
лучше говорить про изобретение колеса, иначе заграницей вас не поймут.
Alexander Pivovarov Доклад-то по русски. Если бы говорил за границей, то да.
Привет всем! сделайте плиз доброе дело? нигде не нашел как это решать на с++, тока на Паскале.
Спасибо тому кто решит
Спортсмен Василий участвовал в соревнованиях по хоккей болу и получил в личном зачете серебряную медаль. Известно, что участники, получившие одинаковое количество очков, награждаются одинаковыми наградами. Известно, что были разыграны золотые серебряные и бронзовые медали. В задаче не спрашиваются правила хоккей бола. Необходимо только определить, сколько очков набрал Василий. Для решения данной задачи массив лучше не использовать. Формат входного файла На первой строке дано число N (2
На С++ это решается точно так же, как на паскале.
Программа написанная под сервис для разгадывания капчи.Программа написана на С++ 6-8 версии. Ничем не упакована и не защищена.Исходника нет.
При регистрации акаунта через программу в конце нужно кликнуть подтверждение (Я не робот) . Эту капчу программа не видит - следовательно регистрацию закончить невозможно! Этот момент нужно исправить
За более подробной информацией пишите в ICQ - 681354647
Бюджет 100$
предложение всё еще в силе?
Сейчас меня сожгут на костре! )) Но все эти костыли - это проклятие из-за отказа от разработки на ассемблере. И если скажут, что на нем медленно разрабатывать или сложно, то я могу ответить, что или Вы недостаточно разбираетесь в технологии или Вы пишете что-то неправильное.
так реально медленно, на плюсах тоже самое можно написать намного быстрее
Надеюсь это шутка
Проблема в том, что одного Вас, гениального, который на асме пишет так же быстро, как на С++, недостаточно, И клонировать и раздать всем софтверным конторам тоже нельзя)))
Интернет стал отдушиной для закомплексованных идиотов, старающихся создать у окружающих впечатление собственной исключительности, в реальности не разбирающися чуть менее чем ни в чём но при этом имеющих острую жажду признания за несуществующие заслуги или достижения
43:00 если warning'и не ловятся, можно бинарным поиском найти бажные файлы)