Здравствуйте, alex_public, Вы писали:
_>>>В танчиках то? ) Так они у меня установлены... ))) I>>Типа ты не понял, что речь про серверный софт
_>Вроде бы же речь шла о сочетание C++ + Python
Здравствуйте, alex_public, Вы писали:
_>·>Ты, как плюсовик, считаешь частью архитектуры разные комбинации _ptr, [], &, *. В яве это частью архитектуры не является. Всё выражается одним абстрактным понятием — ссылка. А как оно будет в итоге расположено — JIT умеет не лету корректировать для лучшей производительности. _>Всё верно. Только я как раз выражаю свои сомнения в способности современного оптимизатора сделать это лучше человека. На самом деле аналогичная ситуация была и с ручным ассемблерным кодом vs C/C++ оптимизаторы лет 20 назад. Тогда нормальный спец. по ассемблеру легко писал код эффективнее C++ компилятора. Сейчас же это почти не реально. Так вот выше обсуждаемый оптимизатор в Java в данный момент не способен создавать ничего сравнимого с человеком. Теоретически когда-нибудь может и сможет, но я сомневаюсь, что это случится в ближайшем будущем. Потому как слишком сложная и неформализованная задача.
Собственно почему java успешна в LL, это потому что оптимизатор способен создавать достаточно хороший код в большинстве случаев, а в тех местах, где это недостаточно — позволяет применять приёмы и приближая скорость к ручной оптимизации, при этом оставляя преимущества управляемой платформы.
Т.е. это очень удачный компромисс между скоростью и безопасностью.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Ikemefula, Вы писали:
_>>>>В танчиках то? ) Так они у меня установлены... ))) I>>>Типа ты не понял, что речь про серверный софт _>>Вроде бы же речь шла о сочетание C++ + Python I>Речь шла про сервер.
Что-то не припомню такого ограничения в нашей дискуссии.
Здравствуйте, ·, Вы писали:
_>>Всё верно. Только я как раз выражаю свои сомнения в способности современного оптимизатора сделать это лучше человека. На самом деле аналогичная ситуация была и с ручным ассемблерным кодом vs C/C++ оптимизаторы лет 20 назад. Тогда нормальный спец. по ассемблеру легко писал код эффективнее C++ компилятора. Сейчас же это почти не реально. Так вот выше обсуждаемый оптимизатор в Java в данный момент не способен создавать ничего сравнимого с человеком. Теоретически когда-нибудь может и сможет, но я сомневаюсь, что это случится в ближайшем будущем. Потому как слишком сложная и неформализованная задача. ·>Собственно почему java успешна в LL, это потому что оптимизатор способен создавать достаточно хороший код в большинстве случаев, а в тех местах, где это недостаточно — позволяет применять приёмы и приближая скорость к ручной оптимизации, при этом оставляя преимущества управляемой платформы. ·>Т.е. это очень удачный компромисс между скоростью и безопасностью.
Всё точно написано. Как раз неплохой компромисс. А вот при переходе с ассемблера на современный C++ никакого компромисса нет — одни преимущества. Если когда-нибудь подобное будет и с каким-то управляемым языком (в чём я крайне сомневаюсь в силу врождённых ограничений этого подхода), то возможно нативные языки будут отмирать (или останутся в каких-нибудь микроконтроллерах). Но пока они на оборот становятся более актуальными в связи с наступлением мобильной эпохи и остановкой роста производительности процессоров.
Здравствуйте, ·, Вы писали:
EP>>Вот здесь есть escape, при этом сам объект типа vector передаётся по стеку. dot>А что такого в этом векторе? Он же маленький, соответствует 4 или 8 байтной ссылке в Яве. Самое интересное это то, на что он указывает в куче.
Внутри обычно три слова — указатель на начало, конец, и конец зарезервированного.
Если нет escape — то появляются лишние индерекции.
EP>>
То есть та оптимизация которую делает EA есть даже при escape. dot>EA работает не на уровне одного метода, а для довольно большого куска кода, притом даже если у тебя методы виртуальные (что для C++ компиляторов очень неприятное обстоятельство).
EA всё равно не сработает если будешь сохранять массив в какую-нибудь структуру.
EP>>>>Выгода также может быть на не компактифицирующем heap — поэтому я про него сразу и спросил. dot>>>С компактифицирующим heap и так всё понятно, он в C++ принципиально невозможен. EP>>Возможен, я делал. Но это опять соскакивание с темы. dot>Но как? Или опять оборачиванием указателей в специальную песочницу типа как gc_root?
Да.
dot>>>Я говорю о том, что jvm может в рантайм принять решение о том, где можно разместить объект — в куче или стеке. EP>>Это понятно. Речь про размещение в куче, например большого массива, и вот для некоторых типов куч имеет смысл ставить условный delete как можно раньше (что может сделать EA). dot>В яве — не имеет смысла что-то ставить.
То есть там все кучи компактифицирующие? Нет ни одной похожей на обычную?
dot>>>>>А Object[] может грохаться только если оптимизатор поймёт, что размер его маленький и его можно разместить на стеке. EP>>>>Я на C++ использую подобные массивы — small size optimization. При этом оно работает не только для стека, но и например для массивов вложенных в другие объекты. dot>>>Ты принимаешь решение в compile time — какой размер считать small. EP>>Да, и этот размер обычно очевиден для конкретной задачи. dot>не факт, размер может варьироваться от реальных условий. И всякие стандартные vector это, вроде не умеют.
Есть готовые библиотечные. Например boost::container::small_vector или folly::small_vector.
Некоторые реализации std::string также используют этот приём.
dot>>>>>Не факт, что это принесёт хоть какую-то пользу. compile time же. EP>>>>В смысле? dot>>>JIT тоже генерит код оптимизированный под конкретную комбинацию, но имеет больше информации — т.к. runtime. EP>>1. JIT ограничен по времени — не все оптимизации доступны. Его задача в том числе работать быстро. dot>Это практически миф, особенно для долгоиграющих серверов.
Почему? Например попалась конкретная комбинация циклических виртуальных вызовов — он её начинает оптимизировать, и если будет делать это долго, то в итоге может получиться дольше чем без попыток оптимизации, причём конкретные рамки он априори не знает.
Если же настраивать его под конкретные use-case'ы, то это становится уже очень близко к PGO.
dot>JIT не оптимизирует весь код, а только самый горячий,
У меня только на компиляцию самого горячего куска уходят минуты.
dot>в отличие от обычного compile time оптимизатора или даже PGO, который старается оптимизировать абсолютно всё, даже куски которые в реальности может быть и не будут выполнены вообще.
PGO как раз таки работает по собранной статистике на реальных use-cases'ах. То есть сначала статистика, потом оптимизация.
dot>И времени на долгоиграющем сервере ему предостаточно.
Значит тратится лишнее время на прогрев, плюс наверняка какие-нибудь растапливающие костыли.
EP>>2. JIT не превращает массив указателей на классы в массив структур — а именно про такие данные идёт речь. dot>Собственно у меня есть сомнения по поводу ценности такого превращения.
Разница может быть на несколько порядков. Выше уже давал ссылку, на C# это дало замедление в ~80x.
dot>Ценным может быть превращение в структуру массивов
Не надо фантазировать. Да, превращение в структуру массивов иногда полезно, но требуется намного реже обычного массива структур.
dot>(а такое и С++ не умеет),
Умеет, я же сказал что это реализуется в библиотечном виде: описал набор полей, получил готовый SOA.
dot>>>>>Указатель это 8 байт. Если указуемое больше — то уже индирекция может помочь съэкономить на объёме горячей структуры. EP>>>>Ещё раз, индерекцию в RAM всё равно придётся делать, ты же предлагаешь ещё добавить к ней и индерекцию по кэшу. dot>>>Мы вроде о сканировании массива так, чтобы он помещался в кеш и подгружался последовательно. Когда отсканировали — берём значение рядом или индирекцией — другой вопрос. EP>>Вообще-то здесь про хеш-таблицу, а не сканирование массива. dot>Даже и хеш-таблица — всё равно. Два случая dot>- массив хеш-таблицы поместился в кеш и значения маленькие, лежат в самом массиве. dot>- массив хеш-таблицы поместился к кеш лишь потому, что значения лежат по ссылкам, т.е. индирекция используется. dot>И собственно и то и другое аналогично делается и в С++ и в Яве.
Я же уже объяснял Ещё раз, если у тебя ссылки лежат в кэше, а значения в куче, то тебе придётся делать как минимум две индерекции — одну по кэшу, а вторую по RAM — даже на happy-path.
Если же ссылки отдельно не хранятся, и вся таблица значений не умещается в кэш, то на happy-path будет только одна индерекция в сразу RAM.
dot>>>>>by-value будет тупой YG, говорю же: зашли в функцию, создали объект, передали в глубь, там ещё что-то насоздавалось, там ещё глубже, пару циклов... а потом вышли и всё грохнули из YG пачкой. EP>>>>by-value работает не только вниз/вглубь, но и вверх, и даже вбок. EP>>>>А для случае когда нужно что-то прибить пачкой — используют например регионы/арены. dot>>>Это как? Кастомные аллокаторы что-ли? EP>>Да, как один из вариантов. dot>Ну собственно не сильно отличается от Явы, там кастомное расположение данных в массиве.
Ты же сам понимаешь что отличие кардинальное
В одном случае ты просто поменял один параметр, не трогая сами данные, во втором ты вручную выворачиваешь каждый класс на изнанку, нарезаешь буфера, отказываясь от GC
dot>>>>>Для написания статьей о скорости может и сгодиться. А на практике обычно надо чтобы оно что-то полезное делало, а не быстрое. EP>>>>Так говоришь как будто быстрое означает не полезное. dot>>>Я говорю, что быстрое не означает полезное. EP>>Оно не означает ни "полезное", ни "не полезное". Ты же явно противопоставляешь полезное быстрому "что-то полезное делало, а не быстрое". dot>Компиляция C++ -> JVM или JS не полезное, пусть хоть и быстрое.
Полезное, используется в реальных проектах: http://formit360.autodesk.com/blog/ https://github.com/kripken/emscripten/wiki/Porting-Examples-and-Demos
dot>>>>>Потому и не знаешь, что принципиально невозможно. EP>>>>Что принципиально невозможно? C++ -> JVM? Возможно. Ещё раз, его даже в JS компилируют. dot>>>Возможно, но практически — бесполезно. JS — однопоточный. EP>>И что из этого следует? Нельзя сделать многопоточно на Java? dot>Можно, но думаю получится медленно, либо с ограничениями.
Почему? Какие предположения?
dot>>>Это я к тому, что при компиляции C++ -> JS проблемы с GC это самое меньшее о чём придётся беспокоиться. dot>>>Зачем это всё — вообще непонятно. Для вау-эффекта сойдёт, но практического смысла — маловато будет. EP>>Практический смысл в том, что можно будет писать быстрый код на высоком уровне, и легко портировать готовый код. dot>Может быть и можно будет. А пока — облом.
Уже используется в реальных проектах. Можешь сам пощупать: http://beta.unity3d.com/jonas/DT2/
dot>Хотя я не верю что можно будет с таким дизайном языка как в C++. Может что-то в духе C++/CLI прокатит...
Здравствуйте, alex_public, Вы писали:
_>>>Вроде бы же речь шла о сочетание C++ + Python I>>Речь шла про сервер.
_>Что-то не припомню такого ограничения в нашей дискуссии.
Ну да, LL, т.е. low latency, о чем тебе постоянно напоминает . это просто слова и ничего не значат.
Здравствуйте, Ikemefula, Вы писали:
_>>>>Вроде бы же речь шла о сочетание C++ + Python I>>>Речь шла про сервер. _>>Что-то не припомню такого ограничения в нашей дискуссии. I>Ну да, LL, т.е. low latency, о чем тебе постоянно напоминает . это просто слова и ничего не значат.
Вообще то тут речь шла уже не только о LL. Но даже если бы и говорить об этом, то у меня как раз встречается не серверная задачка из области LL. )))
Здравствуйте, alex_public, Вы писали:
_>Вообще то тут речь шла уже не только о LL. Но даже если бы и говорить об этом, то у меня как раз встречается не серверная задачка из области LL. )))
И твоя задачка докажет, что у варгейминга на серверах в основном с++ ?
EP>1. Про замыкание результаты в первом сообщении темы — ввод замыкания на C# дал десятикратное замедление и гигабайты аллокаций. На C++ результат идентичен ручному коду. Или ты хочешь сказать что C# без замыканий мог обогнать C++? — не, несерьёзно. EP>2. По поводу замены структуры на класс — я уже ссылку приводил.
EP>>>Ты не учитываешь например указатели на стэке. Предполагаю что ситуация в которой в нулевом поколении не выжил никто — маловероятна. S>> Она как раз самая, что вероятная, особенно в серверных вариантах.
EP>Приведи статистику.
S>>Мало того, за кучей может следить GC в отдельном потоке.
EP>Точно — конкурентная гадость, которая скорей всего не lock-free.
Кстати самый простой вариант для увеличения эффективности GC это выделение памяти для объектов на стеке.
Для этого компилятор может помечать переменные которые используются только в этом методе.
Помечать входные параметры которые используются только в этом методе
Помечать результат метода если память выделяется только в этом методе.
Что мы получим.
1. Для конструктора объекта может передаваться менеджер памяти который будет выделять память для объекта либо в куче либо на стеке.
Для конструктора полей будет передаваться МП на кучу.
2. Зная информацию где будет выделяться память для результата функции передавать в метод МП для стека
3. Зная о том, что в вызываемых методах параметр используется только внутри вызываемого метода мы можем помечать такой как локальный для выделения памяти на стеке.
4. Для объектов которые выделены на стеке, можно вызывать деструктор.
Так можно повысить эффективность GC. А скорее всего так и есть.
Можно пойти дальше и проверять параметры методов рекурсивно на их вхождение в параметры методов внутри метода.
Но это уже другая песня.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Например для Buddy Allocation сложность логарифмическая. Есть же в том числе и O(1) алгоритмы, например TLSF.
Забавно, когда я изобретал свой О(1)-аллокатор, то пришёл почти к тому же. Но у меня блоки не объединяются (я решил, что так проще), ну и размеры только по степеням двойки.
Правда, мне сказали, что у меня функция двоичного логарифма работает за логарифм, а не за единицу, формально это правда, но я почему-то забил на это.
Вообще у меня главная фича — это наличие realloc_inplace, для вектора это охренеть как полезно, почему раньше никто не додумался?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
EP>>Например для Buddy Allocation сложность логарифмическая. Есть же в том числе и O(1) алгоритмы, например TLSF. TB>Забавно, когда я изобретал свой О(1)-аллокатор, то пришёл почти к тому же. Но у меня блоки не объединяются (я решил, что так проще), ну и размеры только по степеням двойки.
Amortized O(1) не трудно сделать через набор free-list'ов.
TB>Правда, мне сказали, что у меня функция двоичного логарифма работает за логарифм, а не за единицу, формально это правда, но я почему-то забил на это.
Так в итоге у тебя какой алгоритм? Что-то типа Buddy Allocation?
TB>Вообще у меня главная фича — это наличие realloc_inplace, для вектора это охренеть как полезно, почему раньше никто не додумался?
Додумывались. ЕМНИП у Александреску даже было выступление на эту тему, они нечто подобное использовали в Facebook.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Amortized O(1) не трудно сделать через набор free-list'ов.
Без амортизации, просто O(1)
EP>Так в итоге у тебя какой алгоритм? Что-то типа Buddy Allocation?
Так я же сказал: TLSF (отсюда: http://peguser.narod.ru/translations/files/tlsf.pdf) без объединения и с только чисто-двоичным размером. Работает за О(1) всё.
EP>Додумывались. ЕМНИП у Александреску даже было выступление на эту тему, они нечто подобное использовали в Facebook.
А, глядишь в С++37 добавят
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, -MyXa-, Вы писали:
MX>Здравствуйте, Serginio1, Вы писали:
S>>Со свойствами проблема, но их можно динамически обернуть. То есть сделать обертку над классом для описания свойв. S>>Для простых случаев можно так. S>>[cs] S>> [ComVisible(true)] S>> [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] S>> // [Guid("33B45C9D-1AED-41F9-8880-36AB6AE84749")] S>> public interface IEventFor1C
S>> Либо пишу ручками используя анонимные типы. И подписка
MX>Не понял, для каких простых случаев, какими ручками? Ты же оборачиваешь произвольную .NET сборку в COM.