Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, Ikemefula, Вы писали:
I>>"для энергопотребления и perceived performance нужно правильно делать ожидания, а не быстрые вычисления, что на C++ непросто"
I>>Сюда можно добавить работу с диском, устройствами, сетью, базой данных и тд.
I>>Вопросы перформанса уже давно стали большим, чем подсчет тактов процессора.
MTD>Опять бла-бла-бла. Ну и в чем конкретно в данных случаях преимущество перед плюсами? Или .Net чтобы данные прочитать диск не раскручивает, а из астрала их берет?
Конечного пользователя не интересует скорость вычислений. Вообще не интересует. Пользователя интересует отсутствие прерываний в работе когда программа что-то делает. Причем "что-то делает" в последнее время чаще всего обращение в интернет.
И тут становится важно: чтобы не зависал интерфейс, чтобы пользователь получал фидбек от происходящего, чтобы приложение было юзабельно при слабом соединении. При этом всем нужна плавная анимация и стабильная работа.
А еще важно чтобы при этом батарейка не кушалась если все это работает на планшете\телефоне.
На С++ это все делается сложнее чем на .NET и JS+HTML.
I>>В общем случае надо организовать корректную схему многопоточного взаимодействия, асинхронщину всякую. Вот это на с++ крайне сложно. MTD>Не сложней, чем на Java, например.
Неправда твоя. Покажи как сделать продолжения и при этом не устраивать аццкие пляски с деаллокацией памяти.
Здравствуйте, gandjustas, Вы писали:
I>>>В общем случае надо организовать корректную схему многопоточного взаимодействия, асинхронщину всякую. Вот это на с++ крайне сложно. MTD>>Не сложней, чем на Java, например. G>Неправда твоя. Покажи как сделать продолжения и при этом не устраивать аццкие пляски с деаллокацией памяти.
1. Передавать объекты по значению — вопроса деаллокации вообще не возникнет.
2. Передавать shared_ptr — все сдохнет автоматизированно.
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, gandjustas, Вы писали:
G>>Я вот оптимизировал C# код, который получал данные от железки постоянно, проводил небольшие расчеты и складывал в базу. G>>Оптимизации по памяти довольно банальные — убрать лишние аллокации, которые возникают, например, из-за замыканий. G>>Оптимизация производительности — использование правильных структур данных, особенно с учетом многопоточности. G>>Но самая главная оптимизация, которая позволила приложению нагружать процессор на 10% при 100 пакетах в секунду — все общение в внешним миром было сделано асинхронным.
MTD>Для дотнетчиков оказывается обработать 100 пакетов в секунду достижение Снимаю шляпу
Нет, это максимум что по COM порту пролетало. А вот 10% загрузки одного процессора при этом и workset в 50 мб очень даже достижение.
При этом на 100 пакетов 30 раз надо было сходить в базу и записать логи и отдать состояние десятку подключенных клиентов.
Здравствуйте, gandjustas, Вы писали:
MTD>>Для дотнетчиков оказывается обработать 100 пакетов в секунду достижение Снимаю шляпу G>Нет, это максимум что по COM порту пролетало. А вот 10% загрузки одного процессора при этом и workset в 50 мб очень даже достижение.
G>При этом на 100 пакетов 30 раз надо было сходить в базу и записать логи и отдать состояние десятку подключенных клиентов.
О, моя любимая тема! Я как раз 4 года писал похожий софт, так вот СОМ-порт — это очень-очень низкая скорость, в основном процесс будет спать в ожидании данных, 30 запросов к базе с мизерным количеством данных (ну пусть килобайта 4 чистых данных) — вообще ни о чем. У меня это крутилось на железке 300 МГц и 128 ОЗУ. Загрузка процессора там была гораздо меньше 10 процентов и памяти кушало мегабайт 10, это при том, что там еще и сложная математика которая эти данные обрабатывала, а так аналогично — база, логи, верхний уровень, опрос десятка устройств по Modbus.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, gandjustas, Вы писали:
N>>>>>На планшетах тем более ресурс, никто не хочет жить на зарядке. G>>>>Память? А причем тут зарядка? EP>>>Performance bottleneck большинства программ это взаимодействие с иерархией памяти. G>>Это ты про какие программы? G>>Среднее дсктопное приложение более 90% времени проводит в ожидании пользователя. Еще 9% в ожидании завершения IO.
EP>Я имел ввиду performance "активной" работы процессора. Плохая работа с памятью -> процессор будет дольше находится в "активном" режиме.
Угу, то есть ты имеешь ввиду 1% времени работы программы. Ты же понимаешь что изменение даже в несколько раз на этом 1% никто не заметить.
EP>>>Плохой memory layout структур данных, лишние индерекции, лишние аллокации, плохая работа с кэшем — это всё яд для производительности — этим всем грешат "управляемые среды", поэтому и производительность намного хуже. G>>Бросай читать книжки 80-х годов.
EP>Поясни
EP>>>Требуется в 10 раз больше памяти? — косвенный признак тормозов. G>>Спорный вопрос. Если в памяти кешируется результат чтения с диска, то я предпочту в 10 раз больше памяти.
EP>Речь шла об одинаковых алгоритмах и структурах в разных языках. EP>Сравнивать производительность сред/языков по разным алгоритмам и структурам как-то совсем неправильно.
Вот я и говорю бросай книжки читать. Подавляющее большинство десктопных приложений не требует ресурсоемких алгоритмов. А если требует то важна не сама скорость работы, а perceived performance.
Например ты делаешь приложение, которое делает graph layout — довольно сложные алгоритмы. Как ты думаешь что больше приглянется пользователям: молчаливый расчет всего за 10 сек потом отображение результата, или рисование узлов графа по мере вычисления позиций в течение 15 секунд?
100% пользователей предпочтут второе, хотя реально оно в 1,5 раз медленнее.
Или недавний пример: MS пилит typescript — типизированное надмножество JS. До версии 0.8 пасер был синхронный и от этого дико тормозил на больших проектах. В 0.9 сделали его асинхронным, что по сути сделало его более медленным при сборке всего проекта, но позволило парсить фалы по частям в студии.
При замедлении алгоритма perceived performance растет.
В C++ увы такими оптимизациями сложно заниматься, потому что требуется совмещать продолжения и детерминированную финализацию.
EP>>>Чтобы делать быстрый код в "управляемых средах" — нужно работать против языка, отказываться от многих средств выражения идей, спускаясь на крайне низкий уровень (даже ниже чем C). G>>Покажи пример чтоли?
EP>Например возьми java, и сравни скорость создания массива int, допустим 32M элементов, и создание массива (размером 16M) объектов в каждом из которых содержатся два int, т.е.: EP>
EP>class Point2D
EP>{
EP> public int x,y;
EP>}
EP>
EP>Это простейшая абстракция, на которую в java будет сильное penalty как по памяти, по скорости создания (на 1-3 порядка), так и по скорости доступа.
Ну Java вообще беден как язык, а в C# можно и массив структур сделать. Но это не самое важное.
Самое важное тут: как ты будешь получать этот массив и как обрабатывать. Если у тебя обработка ограниченного количества элементов за раз, то может вообще нет смысла держать в памяти все 32М, а читать с диска, на лету обрабатывать и выводить.
G>>Я вот оптимизировал C# код, который получал данные от железки постоянно, проводил небольшие расчеты и складывал в базу. G>>Оптимизации по памяти довольно банальные — убрать лишние аллокации, которые возникают, например, из-за замыканий. G>>Оптимизация производительности — использование правильных структур данных, особенно с учетом многопоточности. G>>Но самая главная оптимизация, которая позволила приложению нагружать процессор на 10% при 100 пакетах в секунду — все общение в внешним миром было сделано асинхронным. G>>Где тут низкий уровень? G>>И это кстати пример программы, которая работает все время.
EP>То что ты достиг скорости приемлемой для твоей задачи, вовсе не означает что программа использует ресурсы эффективно (что естественно не является самоцелью), и что её производительность нельзя улучшить на пару порядков.
А зачем? Цель не оптимизация сама по себе, цель — чтобы программа работала достаточно быстро.
EP>Да, использование алгоритмических оптимизаций, уменьшение сложности — это всё важно, и особо не зависит от языка.
Во-во
EP>Но я имею в виду то, что сравнивая одинаковые алгоритмы на разных языках — на C++ гораздо легче написать код который выжимает максимум из железа, в то время как в "управляемых средах" это будет работа против языка, отказ от абстракций (см пример выше) и т.п.
А зачем максимум из железа?
Я же говорю — у тебя понятия на уровне 80-х годов. Кода в одно время работала одна программа и железо было очень слабое.
Сейчас средний ноут работает на 5% мощности, больше ему не надо. Только игрушки, конвертация видео или майнинг биткоинов могут нагрузить.
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, gandjustas, Вы писали:
G>>Почти все десктопные приложения довольно древние, разработаны в году 2005 и ранее. G>>А вот приложения для w8 по большей части .NET (WinRT) и JavaScript.
MTD>Ну раз так, то уверен, будет не сложно назвать хотя бы десяток популярных десктопных приложений на .Net? Прошу.
Открой Windows Market и смотри, там половина как минимум на .NET и JS. Можешь зайти в раздел "поплуярное".
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, gandjustas, Вы писали:
G>>А вот для энергопотребления и perceived performance нужно правильно делать ожидания, а не быстрые вычисления, что на C++ непросто.
MTD>Это ты о чем вообще? Сказать ОС, что не будить процесс до наступления некоего события одной функцией это сложность?
На C++ вообще-то да. Покажи как на C++ будет выглядеть программа, которая: по нажатию кнопки получает данные из сети, потом их обрабатывает, пишет в базу и отправляет в сеть.
При этом обработка минимальная, а все остальное время программа должна спать. При этом надо отправку в сеть и запись в базу сделать параллельно.
Ну и надо не забывать что пока эти пляски происходят пользователь может еще раз нажать кнопку отправки.
Кстати желательно при всем этом не плодить сотни потоков.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, gandjustas, Вы писали:
I>>>>В общем случае надо организовать корректную схему многопоточного взаимодействия, асинхронщину всякую. Вот это на с++ крайне сложно. MTD>>>Не сложней, чем на Java, например. G>>Неправда твоя. Покажи как сделать продолжения и при этом не устраивать аццкие пляски с деаллокацией памяти.
J>1. Передавать объекты по значению — вопроса деаллокации вообще не возникнет. J>2. Передавать shared_ptr — все сдохнет автоматизированно.
Я понимаю что в принципе это все можно сделать, но...
J>хз что из этого ты называешь "аццкими плясками"
Просто покажи пример кода.
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, gandjustas, Вы писали:
MTD>>>Для дотнетчиков оказывается обработать 100 пакетов в секунду достижение Снимаю шляпу G>>Нет, это максимум что по COM порту пролетало. А вот 10% загрузки одного процессора при этом и workset в 50 мб очень даже достижение.
G>>При этом на 100 пакетов 30 раз надо было сходить в базу и записать логи и отдать состояние десятку подключенных клиентов.
MTD>О, моя любимая тема! Я как раз 4 года писал похожий софт, так вот СОМ-порт — это очень-очень низкая скорость, в основном процесс будет спать в ожидании данных.
тут самое интересное что надо максимально часто опрашивать железку, поэтому паузы между пакетами не допустимы.
Если бы просто был опрос железки по запросу извне, то было бы все в разы проще.
Здравствуйте, gandjustas, Вы писали:
G>тут самое интересное что надо максимально часто опрашивать железку, поэтому паузы между пакетами не допустимы. G>Если бы просто был опрос железки по запросу извне, то было бы все в разы проще.
Вообще никакой разницы. Хоть такой код пиши:
while (true)
{
Send(packet);
if (TimedRead(packet, timeout) == SUCCESS)
{
DoSomething(packet);
}
}
В случаее СОМ-порта, львиную долю времени процесс будет спать на ожидании событий ввода-вывода, что для тебя выражается в загрузке процессора аж процента на 1-2.
Здравствуйте, Mystic, Вы писали:
M>Чем Ada не вариант? Если брать стандарт 2012 года? Или ее диалект SPARK?
Ada — совершенно стандартный язык с унылым паскалеподобным синтаксисом. Обычное процедурное программирование, обычное ООП, ничего такого там нет. Те же D, Go, Rust куда интереснее.
Единственное что может заинтересовать в Аде — это встроенное параллельное программирование, "tasks". Хотя и там ничего особенного.
Здравствуйте, gandjustas, Вы писали:
G>Покажи как на C++ будет выглядеть программа, которая: по нажатию кнопки получает данные из сети, потом их обрабатывает, пишет в базу и отправляет в сеть. G>При этом обработка минимальная, а все остальное время программа должна спать. При этом надо отправку в сеть и запись в базу сделать параллельно. G>Ну и надо не забывать что пока эти пляски происходят пользователь может еще раз нажать кнопку отправки. G>Кстати желательно при всем этом не плодить сотни потоков.
Здравствуйте, MTD, Вы писали:
I>>Ты получил внятный ответ — популярные десктоп приложения были написаны еще задолго до 2005го года. Дотнет на тот момент, если не понятно,еще пешком под стол ходил.
MTD>Стало быть их нет? C 2002 года, за 11 лет, всего одно приложение — Paint.NET? В тоже время сколько новых популярных приложений на умирающих плюсах появилось?
Кстати, да, сколько? Сколько новых популярных десктопных приложений появилось на плюсах за последние годы? Кажется, большинство популярных — все сиквелы к старинным продуктам, появившимся еще в прошлом веке. Игры разве что новые выходят, и то там внутри отнюдь не новые движки обычно, очередные обновления старых.
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, gandjustas, Вы писали:
G>>Покажи как на C++ будет выглядеть программа, которая: по нажатию кнопки получает данные из сети, потом их обрабатывает, пишет в базу и отправляет в сеть. G>>При этом обработка минимальная, а все остальное время программа должна спать. При этом надо отправку в сеть и запись в базу сделать параллельно. G>>Ну и надо не забывать что пока эти пляски происходят пользователь может еще раз нажать кнопку отправки. G>>Кстати желательно при всем этом не плодить сотни потоков.
MTD>
Отлично
1) Если пользователь часто нажимает, то время ожидания растет.
2) race condition в очереди.
3) запись в базу и в сеть идет последовательно, а не параллельно.
4) нету кода, который вызывает ProcessTask, он у тебя довольно нетривальный будет.
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, gandjustas, Вы писали:
G>>тут самое интересное что надо максимально часто опрашивать железку, поэтому паузы между пакетами не допустимы. G>>Если бы просто был опрос железки по запросу извне, то было бы все в разы проще.
MTD>Вообще никакой разницы. Хоть такой код пиши:
MTD>В случаее СОМ-порта, львиную долю времени процесс будет спать на ожидании событий ввода-вывода, что для тебя выражается в загрузке процессора аж процента на 1-2.
Так вот и вопрос в том как во время ожидания делать полезную работу, не плодя потоки. У твоем коде поток большую часть времени будет ждать в методах Send и TimedRead. Как ты будешь делать полезную работу в этот момент?
Здравствуйте, NeoCode, Вы писали:
NC>Здравствуйте, Mystic, Вы писали:
NC>Ada — совершенно стандартный язык с унылым паскалеподобным синтаксисом.
Паскалеподобный синтаксис делает работу с компилятором куда более дружественной. Если ты допускаешь опечатку в коде, то сообщение об ошибке в 99% случаев говорит о том, какую ты опечатку допустил. Например, пропущена точка с запятой, или еще что. В C++ очень часто опечатка дает возможность построения новой языковой конструкции, компитятор идет дальше, останавливается когда уже дрова полные, и выдает в качестве сообщение нечто несуразное. А если заюзаны шаблоны, то и многоэтаэжное.
NC>обычное ООП
Имхо, приятное. Не надо думать об перегрузке оператора копирования и оператора присваивания и прочих низкоуровневых тонкостях. Шаблоны надо прописывать явно, компилятор ничего за тебя на додумывает, что избавляет от нечитабельных сообщений об ошибках.
Еще есть контракты, и, в случае SPARK, возможность верификации.
Как по мне, там есть все нужное, и нет ничего лишнего.
Здравствуйте, gandjustas, Вы писали:
J>>1. Передавать объекты по значению — вопроса деаллокации вообще не возникнет. J>>2. Передавать shared_ptr — все сдохнет автоматизированно. G>Я понимаю что в принципе это все можно сделать, но...
Но... что?
J>>хз что из этого ты называешь "аццкими плясками" G>Просто покажи пример кода.
arg1 по значению, arg2 по расшаренной ссылке. Можно и не по расшаренной, кстати, если нет необходимости ее шарить, а нужно просто передавать от одной функции к другой — тогда достаточно простого unique_ptr, у которого вообще никаких накладных расходов.
Здравствуйте, gandjustas, Вы писали:
G>Отлично G>1) Если пользователь часто нажимает, то время ожидания растет.
Как повезет. Чисто физически у тебя кабель один, так что если пакеты данных большие, а кликают часто, то как ни крутись, а очередь возникнет.
G>2) race condition в очереди.
Откуда?
G>3) запись в базу и в сеть идет последовательно, а не параллельно.
С чего вдруг? Очередь может иметь пул и по ним раскидывать данные.
G>4) нету кода, который вызывает ProcessTask, он у тебя довольно нетривальный будет.
Он будет тривиальный — wait/notify, просто писать лень.