• ВКонтакте снова выкладывает KPHP
    +2
    не обладает всей "мощью" оптимизаторов которые были созданы для C/C++

    Боюсь, у меня тут недостаточно экспертизы, т.к. я не копался во внутренностях оптимизаторов C++, но исходя из моей практики написания AOT-компилятора для Java, который специально делался с глобальными оптимизациями и исходя из информации, прочитанной мной из статей на эту тему, время, необходимое более-менее умным алгоритмам чтобы оптимизировать хорошо, устремляется в бесконечность. Поэтому за счёт чего может выиграть AOT-компилятор — у него время самой компиляции не ограничено, поэтому можно применить просто чуть более мощные алгоритмы, дающие чуть лучшую производительность в некоторых ситуациях (например, graph-coloring register allocator вместо linear scan register allocator).


    JIT (и даже AOT) в Java и других подобных языках работает в пределах одной функции

    JIT и AOT-компиляторы в Java очень хорошо инлайнят. Проблема только в том, что чтобы заинлайнить вызов, он должен быть мономорфным (ну или биморфным, если конкретный компилятор умеет). А алгоритмы, которые могут хорошо доказать мономорфность вызова, ну очень требовательны к ресурсам и нигде не применяются, насколько мне известно. Поэтому применяются более практичные и топорные алгоритмы, которые, увы, дают весьма консервативную оценку. Это я говорю как человек, написавший сравнительно неплохой девиртуализатор для Java. Так вот, у JIT с этим проблем нет вообще, т.к. они смотрят, какие классы БЫЛИ на callsite-е в реальности во время прогонов интерпретатора (с деоптимизацией, если предположение оказалось неверным и повторной оптимизацией под новые реалии).


    Можете привести хотя бы один такой случай как пример? Только при условии что код не использует ничего кроме стандартных возможностей языка, т.е. CPU-bound.

    Нет, не могу. У меня были примеры в моей практике, но код, увы, закрыт. А лезть в интернет и искать бенчмарки я не хочу. Так вот, в моей практике было, что числодробильный код, написанный на Java и на C++ работал с одинаковой производительностью, если его скомпилировать gcc. И C++ проигрывал Java при компиляции clang и msvc. Код на C++ писали люди, которые хорошо владеют C++ (а не просто джависты, которые дорвались до C++).

  • ВКонтакте снова выкладывает KPHP
    0
    Если бы это было так, то компиляторы ушли бы в небытиё.

    AOT-компиляторы не ушли в небытиё, не потому, что они генерируют более производительный код, а потому что в их случае нет рантаймового оверхеда, связанного с необходимостью где-то держать исходный код и/или промежуточное представление, считать профиль и т.д. А так же AOT позволяет сильно снизить время прогрева приложения. В случает, например, Java, производительность кода, порождённого AOT-компиляторами ниже, чем JIT.


    Пока же код (кроме самого простого) написанный на C/C++ или даже Java/.net/Go превосходит по скорости выполнения любой JIT для большинства языков которые его поддерживают.

    Это некорректное утверждение. Не бывает просто "более быстрого" кода, бывает код, который лучше ведёт себя в тех или иных задачах, и бывают случаи, когда Java уделывает C++ (а бывает и обратное). Вообще, C++ и Java просто разные языки, созданные для решения разных задач и под разное мышление программиста. Корректно сравнивать AOT и JIT компилятор для одного языка. И C++ уделывает Java только потому, что первый более низкоуровневый и позволяет вручную контролировать вещи, которые Java не позволяет (и поэтому, при грамотном подходе из C++ выжимается большая производительность)

  • Тёмная сторона работы в Яндекс.Маркете
    –1

    Ну а как же скорость сборки? Дев сервер на CI собирается? Сколько времени на это уходит? А как насчёт того, что IDE пересобирает только изменившиеся файлы (например, 1 из 100К файлов в проекте)? А как насчёт того, что некоторые известные нашлёпки на IDE умеют ещё и редеплой делать очень быстро?

  • Тёмная сторона работы в Яндекс.Маркете
    0
    Может это и так в каких-то других языках программирования, но это явно не про джаву.

    Ну скажем так, дьявол в деталях. В Java действительно всё с этим очень хорошо, но порой можно попасть в какие-то те самые 0.01% случаев, где начнётся ад.


    Странно что вы osx и линукс в корзину кладёте. Это вообще-то разные системы. И большинства таки либо Windows либо OsX

    Я ссылаюсь на статью автора, где указано, что проект заводится под Linux, с трудом — под Mac и вообще без надежд — в Windows. Что там у большинства в Яндексе, я могу только гадать, и вообще, не зная их реалий не могу сказать, почему так. Я лишь называю одну из возможных причин.

  • Тёмная сторона работы в Яндекс.Маркете
    +1

    Ну так написание, отладка, тестирование и поддержка этих if...else — это человекочасы, которых в конкретном случае может и не быть. Видимо, люди сопоставили тот факт, что у большинства и так linux или macos, а поддержка windows выйдет дороже, чем перевод на linux/macos тех, кто предпочитает windows.

  • Тёмная сторона работы в Яндекс.Маркете
    +2
    Очевидно что эта библиотека кросплатформенная и называется JDK. Ибо функции inotify в Java выполняет WatchService.

    Вообще-то, с WatchService всё не так хорошо. Например, иногда в Windows она норовит на файлы повесить share mode при котором другие процессы ничего с этими файлами сделать не могут. Потом в том, как приходят события в WatchService, в Windows есть свои интересные нюансы (не помню точно, какие, сталкивался с этими особенностями пару лет назад).


    Откройте какой-нибудь условную обёртку над нативыми библиотеками, например Xerial и удивитесь на скольких платформах она работает

    А если нет такой условной обёртки? Или условная обёртка не подходит под нужды? Ну например, разместить text input поверх GL окна, при этом имея полный доступ к конфигурации GL-контекста этого окна? К сожалению, ни SDL, ни GTK этого делать не позволяют, так что то, что в Windows решается штатным Windows API, в Linux делается за счёт продирания через особенности интеграции GTK с wayland или X.org.

  • Comment from a drafted post.
  • Comment from a drafted post.
  • Не все патчи одинаково полезны
    +1
    Иными словами нельзя просто так взять и выбросить создание массива, т. к согласно спецификации исполнение обязано бросить NegativeArraySizeException и ничего мы с этим поделать не можем:

    Ну или код по созданию массива можно заменить на код, который проверяет длину и кидает исключение, если она отрицательная. Это небольшой оверхед, но это всё равно намного лучше, чем создавать ненужный массив в куче.

  • Сибирская компания Excelsior стала «Excelsior at Huawei»
    +2

    Это почему-то так не работает. Крупные компании вливают триллионы бабла и получается известная субстанция. Тут работает неизмеримый и неформализуемый творческий ресурс, пассионарность и т.п. Я сам конечно не люблю, когда при мне вот так многозначительно выражаются подобными гуманитарными терминами, но что делать, если факт есть факт :-) Большие и неповоротливые с их миллиардами не могут, а маленькие и независимые — могут

  • Kotlin как будущее разработки приложений на Android
    0

    А почему я должен выводить 0 для случая, если ключа нету в мапе? Как я уже ответил другому комментатору, ситуации разные бывают, я просто привёл простейший пример. Могу специально покопаться и поискать места в самом kotlinc, где используются !!, и это вполне уместно.

  • Kotlin как будущее разработки приложений на Android
    0

    Я прекрасно знаю, что значит !!.. Иногда?.. не спасает, т.к. для ключа, которого нет в мапе, всё равно нет валидного значения (можно вернуть что-то бессмысленное, но тогда что-то всё равно упадёт в будущем). Ситуации бывают разные, я написал не один десяток тысяч строк на Котлине, и всякого повидал. Мой комментарий ставил целью опровергнуть заявление, что KNPE был брошен где-то в "интеропе с Java". Отнюдь. Котлин не всесилен, и есть куча способов упасть в чистом котлине. Можно даже NPE словить, если пошаманить со статическими инициализаторами или с lateinit.

  • Kotlin как будущее разработки приложений на Android
    0

    Есть масса сценариев, где котлиновская null safety не работает. Например, мы вот только что положили в мапу элемент, примерно так:


    val map = mutableMapOf<String, String>()
    map["foo"] = "bar"

    А потом (мамой клянёмся, что "foo" есть в мапе):


    println(map["foo"]!!.length)

    если не поставить !!, компилятор ругается. К сожалению, null safety не всесилен. Он помогает устранить часть ошибок с NPE, которые возможны в Java, но ото всех ошибок такого рода избавиться невозможно. Справедливости ради стоит так же сказать, что для Java есть статические анализаторы кода и наборы аннотаций, которые позволяют добиться примерно аналогичного поведения (Checker Framework, инспекции IntelliJ IDEA).

  • Разработка под WebAssembly: реальные грабли и примеры
    0
    А при просто потоке машинных кодов, обращающихся к каким-то произвольным участкам памяти, как гарантированно понять, что какой-то посторонний код (в худшем случае вообще в параллельном потоке — этого сейчас в WASM нет, но планируется в ближайшее время) не поправит данную ячейку памяти (которая потом используется как указатель)?

    Таки WASM — это не машинные коды, про него очень много всего можно сказать. Аналогичная проблема в JVM решается с помощью memory model. Собственно, там предполагается, что один поток может не увидеть изменений в памяти, сделанные другим потоком. Причём, на некоторых процессорных архитектурах это прямо аппаратно так (вроде на MIPS было
    так).


    Ээээ что? Что значит браузеру не нужно с данной памятью работать? Ему не нужна вообще никакая память для своей личной работы или как? А если хоть какая-то нужна, то как её защитить от доступа из WASM модуля с помощью защиты страниц виртуальной памяти?

    Ещё раз — браузер мапит где-то для себя страницы. При этом для WASM он резервирует страниц на 4Гб, что никак не противоречит тому, что ещё какие-то страницы памяти выделены под сам WASM. При этом для доступа к WASM-хипу можно использовать что-то вроде такого: wasm_heap[ptr & 0xFFFFFFFF], поэтому мы гарантированно либо попадём в хип, либо получим sigsegv.


    Формат wasm — это по сути и есть IR, представляющее собой ассемблерные инструкции некого виртуального процессора

    WASM — это очень неудобный IR. Как минимум, потому что не SSA. Держу пари, что WASM машины внутри себя его во что-то более удобное преобразуют.


    Причём этот формат является чуть изменённой (упрощённой и с большей безопасностью) версией IR из LLVM

    Да вообще достаточно мало общего. Если для вас это "чуть изменённая" версия LLVM-биткода, то можно и JVM-байткод или MSIL назвать "чуть изменённой" версией LLVM.


    а это единственное разумное решение

    А обоснование какое?

  • Разработка под WebAssembly: реальные грабли и примеры
    0

    ok, во-первых, WebAssembly выполняется как раз в v8. Во-вторых, эти же лимиты они про то, как работает v8 с точки зрения юзера, а внутри он может что угодно и как угодно выделять. В третьих, зарезервировать в ОС страниц можно сколько угодно, пока в них процесс писать не будет, рельно память выделяться не будет. Впрочем, если резервировать с правильными флагами, то при попытке записи вообще будет генериться sigsegv (ну или как это называется в Windows), и никогда не будет выделяться физическая память. Что я, собственно, и предлагаю.

  • Разработка под WebAssembly: реальные грабли и примеры
    0

    В смысле? Chrome и не должен никому ничего давать. Это операционка должна давать Chrome-у. Есть какие-то причины, почему она не даст зарезервировать приложению (Chrome) страниц суммарно на 4Gb?

  • Разработка под WebAssembly: реальные грабли и примеры
    0
    Так нужны гарантии, что эти значения не меняются. Именно в этом проблема, а не в определение самих значений.

    Гарантий нет, но ведь всегда есть достаточно безопасные и предсказуемые кусочки программы, про которые что-то можно доказать. Кроме того, повторяю, что для верхнего лимита адресуемой памяти есть как минимум нижняя граница, которая указана просто в модуле. Для оптимизатора не важны точные значения. Для доказательства неравенства Amin < A < Amax, Bmin < B < Bmax, где Amin, Amax, Bmin, Bmax — константы, достаточно доказать, что Amax < Bmin. Если считать, что B — это размер хипа, то Bmin и Bmax тупо указаны в модуле. А Amax можно попытаться каким-то образом оценить, хотя бы сверху. Можно даже не с константами работать, а с инвариантами цикла. Ну например есть код:


    while (start < end) {
      *start++ = 0;
    }

    компилятор вставит проверку


    while (start < end) {
      if (start >= wasm_upper_bound) generate_exception();
      *start++ = 0;
    }

    далее, у нас есть два инварианта цикла: wasm_upper_bound и end. К сожалению, start таковым не является, так что классический loop unswitching сделать не получится. Но известно, что он выполняется неравенство start < end с инвариантом цикла, так что можно попробовать модифицировать loop unswitching, чтобы он делал следующее


    if (end < wasm_upper_bound) {
        while (start < end) {
            *start++ = 0;
        }
    } else {
        while (start < end) {
            if (start >= wasm_upper_bound) generate_exception();
            *start++ = 0;
        }
    }

    VirtualProtect это в Винде. Только ничем эти функции не помогут для решения данной проблемы. Если закрыть с помощью них доступ к какой-то области памяти, то каким образом сам браузер будет работать с этой областью памяти?

    А браузеру вовсе не нужно с данной памятью работать. Учитывая, что в WebAssembly пока размер кучи ограничен 2^32, а процессоры у нас 64-битные, можно тупо нарезервировать страниц как раз на 2^32, но на реальные физические отобразить ровно столько, сколько заявлено в дескрипторе wasm-модуля (ну и по мере вызова grow_memory отображать дополнительные).


    С учётом того, что в LLVM IR имеются векторные типы, это конечно очень большая загадка, как это делается

    Вы хотите сказать, что clang берёт и сам генерит векторные инструкции? Мне казалось, что они всё-таки получаются в процессе работы самого LLVM. Учитывая, что с точки зрения меня, как разработчика приложений, формат wasm является всего лишь форматом обмена данными, мне всё равно, в какой там IR браузер разворачивает мой wasm-модуль и как его оптимизировать. Или разработчики WebAssembly не хотят, чтобы браузер делал векторизацию и хотят переложить эту заботу на компилятор? Ну тогда я всё равно не вижу практической невозможности позволить генерацию быстрого кода, я вижу только невозможность сочетать это с быстрым запуском кода.

  • Разработка под WebAssembly: реальные грабли и примеры
    0
    Каким это образом, если и значение указателя и значения границ определены только в рантайме?

    Вот уж не знаю как. Я точно помню, как общался с сотрудниками Мозиллы и они мне говорили про багу в range analysis ещё в альфа-версии WebAssembly. Как минимум, нижняя граница определена в compile-time (в WebAssembly-модуле для heap необходимо указывать минимальный и максимальный размер хипа), а то, что указатель известен только в рантайме, ещё не значит, что его диапазон нельзя оценить с помощью статического анализа. Такое, например, реализовано в JVM для устранения проверки на выход за границу массива.


    Каким образом можно в рамках одного процесса закрыть некому коду доступ к какой-то области выделенной памяти?

    mprotect в POSIX. В Windows тоже был системный вызов, но я с ходу не вспомнил название.


    Нет там ничего необходимого. В будущем появится (соответствующие инструкции), но пока нет.

    Там есть всё необходимое. Вот как-то C-компиляторы делают это. А они, заметьте, никогда не оптимизируют непосредственно AST C. Т.е. они строят IR (промежуточное представление), которое как раз очень похоже на портабельный ассемблер, а потом уже находят в нём циклы, которые можно векторизовать. Для этого есть куча способов, есть много специализорованной литературы, которая рассказывает про это (вот даже последние редакции Dragon Book рассказывают про векторизацию), и есть ещё большая куча всяческих статей от авторов тех или иных компиляторов.


    С учётом того, что в наиболее требовательных к ресурсам приложениях (программирование различных МК, ядра ОС, дравейров и т.п.) как раз применяется режим C++ с отключёнными исключениями, то данная особенность если и влияет на производительность, то только положительно. )))

    Полагаю, что статья автора как раз не про драйвера и ядра ОС.

  • Разработка под WebAssembly: реальные грабли и примеры
    +1
    Но при этом тот же C++ код скомпилированный в машинные коды всегда получается в разы быстрее. И на это есть две фундаментальные причины

    Мне кажется, что проверка на выход за границы heap-а в ряде случаев может убираться оптимизатором. Кроме того, часть работы по отлову выходов за границу хипа можно сделать через защиту памяти. Что касается SIMD, опять же, браузер может сам анализировать WASM и автоматом векторизовать его (для этого в WASM есть всё необходимое). По крайней мере, LLVM ровно так и делает. А вот ещё моменты, которые ещё, как мне кажется, могут сильно влиять на производительность:


    1. Нет возможности получить указатель на переменную в стеке. Если такой указатель где-то берётся, то приходится размещать переменную в shadow-стеке, со всеми накладными расходами на поддержание shadow-стека.
    2. Нет возможности вообще как-то погулять по стеку, чтобы, например, сгенерировать исключение. Да и нативную поддержку исключений пока не завезли. Так что единственная возможность — это вставлять всюду проверки.
  • Ява после извержения вулкана
    0

    Честно говоря, ответа ни на один вопрос я не получил.


    Какова практическая необходимость такого изменения? Вон, люди в Kotlin наоборот плюются от отсутствия static.

    static не исчезает, он становится неотличим от дефолта. Вместо статичных классов и полей — объекты по умолчанию. Внутренние объекты по умолчанию, таким образом, будут как бы статичными только для себя, по отношению к своему внешнему классу, т.е., если внешний класс сам статичный и так до самого внешнего, то — статичные абсолютно.

    Во-первых, тут вы оперируете слишком большим количеством терминов, которые мы с вами не согласовали (объекты по-умолчанию, внутренние объекты). Можете более подробно описать эти особенности дизайна вашего языка? Объекты по-умолчанию это что-то вроде object в Kotlin? Т.е. есть сущность "объект" а есть — "класс". Или всё является классом? Тогда каким образом конструируются объекты по-умолчанию для классов, у которых нет конструкторов без параметров. Во-вторых, вопрос был в том, зачем избавляться от static.


    Т.е. структурная типизация как в go и typescript вместо существующей номинативной? А зачем?

    На что получил что-то про особенности реализации, которые, увы, не зная всех особенностей вашего замысла, понять практически невозможно (предлагаю всё-таки для конструктивного общения описать дизайн языка, с bnf и операционной семантикой, хотя бы в очень нестрогом виде).


    А вопрос-то был про то, зачем вам в языке структурная типизация вместо номинативной. В чём вы видите преимущества первой перед второй?


    Да, но как тогда вы в методе будете указывать, что переданный параметр должен обладать такими-то свойствами? Для этого нужно будет вводить синтаксис для описания анонимного типа-структуры. А потом и тайпалиасы прибегут (что и будет аналогом интерфейсов).

    В языке аргумент это просто примитив либо название метода, который класс по совместительству. Там нет ничего кроме классов, они же — методы с фигурными скобками. Для машины аргумент это ссылка на структуру объекта, в которой 1: vtable, в котором хеши из сигнатур (у нас же только методы) и значение-ссылка на такую же структуру другого объекта; 2: хэштаблица из хешей (2) предков и себя самого; и 3: адрес метода.

    Я опять же, спрашивал не столько про особенности реализации, сколько про дизайн языка. Вот у вас, судя по всему, структурная типизация, так? Вот в typescript я могу написать


    function foo(x: { bar(x: number): string }) {
        x.bar(23)
    }

    и сюда подойдёт инстанс любого класса, у которого есть bar. Если попробовать в foo засунуть что-то не обладающее методом bar нужной сигнатуры, то компилятор нарисует ошибку. Вот где в вашем языке определяется сигнатура метода? Как в ней описать требования к передаваемому в метод объекту, если нет интерфейсов?


    Ага, т.е. множественное наследование реализаций? А как будет реализовываться vtable?

    Не совсем множественное наследование. vtable состоит из key — хешкода сигнатуры метода, и value — ссылки структуру, описанную в (3), где есть и тело метода и такой же vtable и т.д. до победы

    А вот это уже был вопрос про реализацию. И правильно я понимаю, что вы предлагаете виртуальный вызов вместо обычной косвенной адресации со смещением (одна инструкция на x86) делать lookup в хэш-таблице? А как же производительность?


    Простите, а как при ссылке на overloded-метод должен резолвиться метод с конкретной сигнатурой?

    Прямо по хешу сигнатуры метода из vtable. И есть куда оптимизировать простые случаи.

    Вопрос снова был про семантику а вы ответили реализацией. Хорошо, попробую вот так. Пусть у нас есть в Java такие объявления:


    void foo(Integer x);
    
    void foo(String x);

    когда я пишу o.foo(23), компилятор точно знает, что надо вызвать первый метод, потому что он подходит по сигнатуре. Далее, если у нас все методы есть просто поля функционального типа, то такой резолв становится невозможен (например, он невозможен в JavaScript, где ровно такое поведение, и там похожая (но не такая же) штука реализуется уже в рантайме руками). Именно поэтому для ссылок на методы и в Java используется такой синтаксис, который используется (там по сигнатуре метода в целевом SAM-интерфейсе можно сделать резолв нужного метода). Вы предлагаете отказаться от перегрузки по сигнатуре? А если не предлагаете, то как разработчик должен сообщать компилятору, который из методов ему нужен?


    Практика показывает, что голова начнёт чесаться при решении задачи каскадной упаковки, а именно где остановиться и как это правило сформулировать.

    Просто свои приватные массивы и примитивы, они же лежат по адресу без всяких vtable. Чужие не надо. В пункте 13 даже есть заделка, но для этого и она наверное медленная.

    Ещё раз обратите внимание — практика показывает. На Java вполне можно просто в виде библиотеки это сделать. И никто не делает. Точнее, делают в виде наколенных поделок, которые приходится выбрасывать, потому что при усложнении проекта и появления дополнительных требований оказывается, что никакая автоматика не справится.


    Изобретать неявные преобразования, как в C++?

    Используется обыкновенный класс с абстрактными полями, по тому же самом принципу. Можно его даже подзаполнить, если хочется. Поскольку есть динамические типы, расширяем подходящий объект этим «темлейтом» и абстрактные методы радостно становятся неабстрактными. Просто этот «темплейт» попадает в хештаблицу предков. Т.е., даже никакого механизма специального не надо. Так получается потому, что из языка всё повыкинули.

    Вопрос был про варантность generics, т.е. про возможность объявить такое:


    void foo(List<? extends C> supplier, List<? super C> consumer);

    у шаблонов в C++ с этим проблемы. Ну как проблемы, там это решается средствами, которых и близко нет в Java (и про которые вы так же ничего не сказали)

  • Ява после извержения вулкана
    0
    Никакого труда не составляло бы за всё это время по пунктам перечислить конкретные наивности и побочные проблемы, но их там просто нет или исчезающе мало.

    Мой коммент выше читали? Там как раз некоторые наивности разобраны и обозначены некоторые побочные проблемы.

  • Ява после извержения вулкана
    0

    [del]

  • Ява после извержения вулкана
    +1
    Модификатор «static» из языка убрать, в качестве static — дефолтный экземпляр, доступный по ссылке на типизированный null.

    Какова практическая необходимость такого изменения? Вон, люди в Kotlin наоборот плюются от отсутствия static.


    Типы классов сравниваются по хеш-коду, который будет сгенерирован именами поля, именами аргументов, типами и возвращаемыми значениями,

    Т.е. структурная типизация как в go и typescript вместо существующей номинативной? А зачем?


    Таким образом, больше не нужен «interface» как таковой, только «class», «abstract» — лишь инструкция, запрещающая создание экземпляра

    Да, но как тогда вы в методе будете указывать, что переданный параметр должен обладать такими-то свойствами? Для этого нужно будет вводить синтаксис для описания анонимного типа-структуры. А потом и тайпалиасы прибегут (что и будет аналогом интерфейсов). Я кстати ещё молчу про перфоманс instanceof/checkast. Ну и да, это не просто языковое изменение, тут JVM придётся выкинуть.


    Добавление правил слияния для «extends».

    Ага, т.е. множественное наследование реализаций? А как будет реализовываться vtable? Через ужасные трюки как в C++, с нескольми указателями на vtable в каждом инстансе? С неизбежным ростом размера заголовка объекта? А как при этом обеспечивать identity equality?


    Динамические типы. Темплейты как в Си, а не как женериксы в Java

    И как это будет работать с variance? Изобретать неявные преобразования, как в C++?


    Больше не понадобятся специальные ссылки на метод, как в Java 8. Ссылка на метод будет означать ссылку на объект.

    Простите, а как при ссылке на overloded-метод должен резолвиться метод с конкретной сигнатурой?


    Чтобы прямо хотелось распаковать-использовать-упаковать в одном методе, а не чесалась голова «как это лучше сделать».

    Практика показывает, что голова начнёт чесаться при решении задачи каскадной упаковки, а именно где остановиться и как это правило сформулировать.


    Массивам нужен контроль границ только во время записи, и я бы дал возможность читать напрямую из памяти без контроля границ массива.

    Чтение за границами массива — это в 99% случаев не то, чего мы реально хотели, а значит — ошибка. Одним из принципов дизайна Java является fail fast, что, исходя из моего опыта (и из чужого опыта — тоже), является благом. Проблема производительности решается в данном случае JIT-компилятором, который может сделать range analysis и доказать, что проверка не нужна. Они, конечно, слабоваты эти range-анализы, но на практике если у вас такой сложный код, что в нём сложно что-то доказать, то в нём и проверка на выход за границу массива не будет узким местом.

  • PVS-Studio для Java
    0

    А можно пример кода, который при компиляции даёт байт-код, в котором потеряна информация, необходимая для статического анализа?

  • PVS-Studio для Java
    0

    Я так понял, PVS-Studio анализирует исходники. А почему не байт-код, как это делает findbugs? Это позволило бы одним инструментом покрыть много разных JVM-языков. Ведь наверняка PVS-Studio парсит исходники и строит какой-нибудь control flow graph, ищет def-use chains (а то и в SSA всё перегоняет). Всё то же самое можно прекрасно делать с байт-кодом. Или в подобных рассуждениях есть какой-то подвох?

  • Написание собственного неплохого менеджера памяти
    +2

    Аллокатор как часть ОС? А зачем? Обычно ОС предоставляют низкоуровневые вызовы, резервирующие память страницами, вроде sbrk/mmap в POSIX или VirtualAlloc в Windows, а уже поверх них в userspace реализуется что-нибудь вроде malloc. Последний может быть и не нужен, если вы запускаете на своей ОС какую-нибудь Java, где свой аллокатор, который непосредственно в тот же mmap бегает.

  • J2CL — Лучше поздно, чем никогда
    0
    Обычно хватало GwtQuery. Есть Elemental. Есть форк реакта под GWT.

    Всё это весьма и весьма кривое и неудобное. После Angular 2+/TypeScript реально неуклюжим кажется.


    Java плохой язык для декларативного программирования и DSL-ей. В нем фактически отсутствует возможность читабельно написать иерархические структуры, такие как DOM.

    В JavaScript тоже нет никаких возможностей таких. Вот для этого и прикрутили JSX/TSX.


    Как выход либо прикручивается сторонний темплейтер с кучей не type-safe байндингов

    Либо прикручивается сторонний темплейтер, поддерживающий типизированные байндинги, вроде этого.


    В Java много специфической семантики, отличной от JS. С одной стороны мы хотим сделать по стандарту, как в GWT

    А чего в плане интероперабельности не хватает в JSInterop?

  • J2CL — Лучше поздно, чем никогда
    –1
    Кусок страницы, которая рисуется динамически, не отображается или отображается некорректно или в одном браузере норм, в другом — нет.

    Помню, такое бывало в далёком 2008-м. Но в 2018-м? Первый раз слышу. К тому же, опять приведу аналогию с нативным миром — это всё равно, что забиндить к Java через JNI какой-нибудь GTK, и потом пересесть на C, только потому, что приходится в процессе разбираться с устройством этого GTK, который написан на C.


    И вот начинаются танцы с браузером, который работает с JS.

    Ну так JSNI/JSInterop позволяет взять и писать на JS. Это же небольшое количество нативного кода. Помню, сам в проекте на 200К строк Java-кода понаставил несколько грязных хаков на JSNI (это в далёком 2014-м, когда корпоративные клиенты всё ещё сидели на IE8), но в совокупности их там и на 200 строк не набралось бы.


    JS станет не главным языком, на котором все крутится, а «одним из», на равных условиях. Вот тогда ваша аналогия с x86/x64 будет уместна, ну и неизбежно в браузерах появятся средства отладки не привязанные к языку (сейчас что-то есть, но не в том объеме).

    Что-то не разделяю я вашего оптимизма. Как разработчики браузеров не сделали нормальных тулов для транспайлеров, так они и для компиляторов в wasm ничего не сделают. Вроде уже года полтора как зарелизили MVP, но до сих пор по дебагу ничего нет, кроме весьма куцых сорсмапов.

  • J2CL — Лучше поздно, чем никогда
    0

    На вопрос, чем плох GWT, пусть отвечают создатели GWT, которые его успешно похоронили и теперь делают J2CL. А так же многочисленные пользователи GWT, которые в нём почему-то разочаровались. Лично от себя могу добавить следующие моменты:


    1. Действительно, когда-то GWT имел детские болезни, вроде отсутствия инкрементальной компиляции, кривой дебаг и т.п. Сейчас это полечено.
    2. Морально устаревшая и кривая библиотека виджетов. Это когда весь мир сидит на реакте.
    3. Кривой интероп (который заменили в последних версиях на нормальный).
    4. Невозможность совмещать в одном проекте Java, Scala и Kotlin.

    Короче, проблема номер два решалась выпиливанием старой библиотеки виджетов и написанием нормального Angular/Java (ведь написал же гугл форки для TS и Dart, чего бы Java не осилить?), а не выкидыванием всего GWT и заменой его на J2CL

  • J2CL — Лучше поздно, чем никогда
    +3
    Помимо того, что она оочень многословна

    Думаю, что для тех, кому Java очень многословна, она и на бэкэнде не нужна. Есть полно других языков, которые менее многословны. Думаю, что те, кто выбирают Java, выбирают её не за краткость. Вот, например, лично мне "многословность" Java не мешает. Всё равно львиная доля времени уходит на обдумывание задачи, уточнение требований, отладку, тестирование. А код IDE помогает писать. И аргумент с тем, что более краткий код является более лаконичным, тоже сомнительный. Вспомним языки J и K. Очень читабельный на них код?


    она еще и далека от JavaScript по синтаксису.

    Java, например, очень далека по синтаксису от систем команд x86/x64 и ARM. Разве это кому-то мешает писать бэкэнд и мобильные приложения на ней и потом давать на откуп JVM или ART трансляцию эти платформы?


    И вроде бы что тут плохого, вы ведь не хотим знать JS? А придется. Рано или поздно придется лезть в отладку и смотреть что происходит под капотом.

    Отладку какую? В браузер с source maps или прямо в сгенерированный JS? С первым чем это отличатся от просто подебажить Java в IDE? Второе — ну это как дизассемблировать. Такое редко но делают, в основном, когда натыкаются на баги в JVM, и хотят сами разобраться в деталях вместо того, чтобы сразу писать багрепорт.


    Разве что, c взлетом WebAssembly что-то поменяется

    А что поменяется? Вместо относительно понятного JS будет генериться совсем низкоуровневый код, похожий на ту же систему команд процессора. Как раз в этом смысле генерация JS даже выигрывает.

  • J2CL — Лучше поздно, чем никогда
    0

    Хочу сказать о достаточно узкой нише, где без GWT (или аналога) — никак. Это приложения в несколько миллионов строк Java-кода, которые нужно запускать ещё и на Web (при этом требований к нативности интерфейса нет). Это всякие мультимедиа-приложения, игры и т.п. Переписывать всю эту тонну кода на TS и держать две параллельные ветки кода — это слишком затратно.

  • J2CL — Лучше поздно, чем никогда
    +1

    Ну как же это? JSweet упомянули, а TeaVM нет, хотя у него и на гитхабе звёздочек больше, и делает его ваш соотечественник.

  • J2CL — Лучше поздно, чем никогда
    +2

    Может, проблема не в том, что Java для написания фронта плоха, а в том, что плох GWT?

  • Типобезопасный SQL на Kotlin
    0

    В JS можно использовать аннотацию JsName:


    class A {
        @JsName("eqeq")
        infix fun `==`(b: A): String = "OK"
    }
  • Смена основного стека с .NET на Java
    0
    Да, я знаю про jOOQ, но ни разу не видел его использование хоть в чем-то, напоминающем продакшен.

    Есть Querydsl, использовал в продакшене и не могу нарадоваться. Ещё есть Jinq, но с ним я только игрался и идея использовать его в продакшене мне кажется сомнительной. Причина — использует сериализуемые лябмды, что накладывает множество ограничений (лучше анализировал байт-код лябмд с помощью какого-нибудь инструментатора/класслоадера).


    Возможно потому что это полу-платный новодел без JSR, возможно по другой причине.

    JSR не панацея. На спринг есть JSR? А, скажем, для логгирования используют log4j/logback/slf4j вместо стандартного (JSR) java.util.logging.

  • List.of() и все, все, все…
    0

    А что я тут ещё заметил: для списков разной длины возвращается свой класс. Это плохо, потом будет какой-то код, написанный для List<T> получать всё это многообразие разных реализаций и нарвёмся мы на мегаморфные вызовы, что сразу убьёт все полезные оптимизации.

  • Блеск и нищета джавовых веб-фреймворков
    +1

    А чем это отличается от jSweet?

  • Блеск и нищета джавовых веб-фреймворков
    +3
    С этим нет смысла сравнивать, пока вы не скажите какой фреймворк был использован в вашем TodoMVC.

    Самописный, идеологически напоминающий Angular. Посмотрите сайт проекта, там про всё это написано


    А в чем преимущества в вашем проекте, если «GWT такой же»?

    А в том, что в отличие от GWT можно писать на Java, Kotlin и Scala. А ещё есть несколько приятных фишек, отсутствующих в GWT (например, эмуляция тредов на корутинах). Ну и собственно, упомянутый фреймворк, которого для GWT нет.

  • Блеск и нищета джавовых веб-фреймворков
    +2

    Сама TeaVM никуда не входит. Это всего лишь AOT-компилятор, который порождает самодостаточный JS-файл, где всё есть и которому ничего больше не нужно загружать.

  • Блеск и нищета джавовых веб-фреймворков
    +2
    1. Интернет не всегда высокоскоростной
    2. Из-за размера увеличивается нагрузка на устройство (больше парсить, кэш браузера отжирает больше хранилища).