Как стать автором
Обновить

Комментарии 26

Извините за возможно тупой вопрос, но GPU это graphics processing unit? Какого рода задачи выполняет ваше приложение, если оно одновременно и использует мейнстримный спринг бут и такую экзотику как вычисления на GPU?

Присоединяюсь к вопросу

Допущена ошибка :D
Почему-то писав статью за GPU -> предполагалось ОЗУ.
Хотя GPU в моем случае не используется вообще.

public enum TestEnum {
        A("1"),
        B("2"),
        C("3"),
        D("4"),
        E("5"),
        F("6"),
        G("7");
        private String number;

        private TestEnum(String number) {
            this.number = number;
        }

        public String getNumber() {
            return number;
        }
}

В перечислениях в Java есть встроенное поле ordinal, представляющее порядковый номер члена перечисления.

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

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

Во-вторых, по-православному добавление новых постоянных всегда делается в конец существующего энума.

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

по-умолчанию в таблицу вставляется именно порядковый номер, а не имя

Все делают ошибки, а принятые плохие решения, просочившись в стандарт, остаются там навсегда. Это такой же косяк, с которым приходится жить, как и @*ToMany(fetch = EAGER).

В том-то и дело, что это не ошибка. Да, разработчики JDK не прописали жёсткого запрета на перестановку членов перечисления, но уже тот факт, что Enum можно сериализовать (а вместе с ним и EnumSet/EnumMap, в которых в частности используется ordinal) говорит о том, что перестановки делать нельзя. В JPA исходя из этого и решили использовать порядковый номер, а не имя. Во-первых, чтобы повторить исходное поведение (старые данные будут неверно преобразовываться в случае смены порядка), и во-вторых чтобы использовать число вместо текста в таблице.

Ну, не знаю, не знаю. Как по мне, так ошибка самая что ни на есть.

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

Использование данного метода в прикладном функционале сродни использованию java.util.ArrayList#trimToSize: метод, несомненно, полезный, но в 99,(9)% неиспользуемый вне реализации стандартной библиотеки классов. Но он не мешает, т.к. работа с коллекциями в подавляющем большинстве случаев идёт на уровне интерфейсов.

Приведу ещё пару примеров решений, на первый взгляд ошибочных, но на деле оказавшихся очень даже полезными.

1) Несериализуемый Optional в своё время вызвал немало споров, а всё потому, что значительная часть пользователей не поняла, что Optional задумывался как OptionalReturn, иными словами он должен использоваться только как возвращаемое значение и с этой точки зрения запрет сериализации выглядит полностью логичным и оправданным.

2) Одноразовый Stream тоже вызвал недоумение у многих, привыкших переиспользовать коллекции и вертеть их как угодно, тем более, что Stream намного тяжелее и дороже коллекций. Но оказывается, что для ленивого связывания и параллелизма очень сложно реализовать механизм поддержания и сбрасывания промежуточного состояния. И ещё сложнее реализовать все свойства стримов в случае, например, построчного чтения из файла.

С перечислениями, на мой взгляд, та же история, просто по непонятной причине это явно не прописали в документации.

>> но уже тот факт, что Enum можно сериализовать (а вместе с ним и EnumSet/EnumMap, в которых в частности используется ordinal)

То что ordinal используется для быстрой работы enum set/map, не говорит что ordinal используется для сериализации (можете сами в этом убедиться).

>> В JPA исходя из этого и решили использовать порядковый номер, а не имя.

Не факт, что именно из-за этого. Как по мне странное решение, я думаю не стоило делать default value вообще (пусть программист подумает хорошо). Лично я стараюсь использовать сокращенные мнемоники (в виде отдельного поля в enum и реализации javax.persistenceюConverter) если сохранении полного enum name не желательно из-за производительности. Просто если базой пользуется еще кто-то (а не только ваш jpa код), то эти кто-то будут очень вам "благодарны", что вы все циферками записали/засекретили, смысл которых нужно помнить или искать в ваших java сырцах ))

>> разработчики JDK не прописали жёсткого запрета на перестановку членов перечисления

Если enum не сохраняется по индексу (в проектах, где я участвовал мы никогда так не делали) нет смысла добавлять новый enum в конец. Добавление же нового элемента в более логичную позицию улучшает читабельность кода (группирая похожие элементы вместе, а не разнося их)

Да, действительно, странно получается. Может упор на производительность делали? Стандарт ведь ещё бородатых годов.

Это не пример из прода) Тут суть в том что есть некая строка которая возвращается) А не в номере.

И ладно, дискуссия из него получилась вполне годная )

@SpringBootApplication(exclude = [DataSourceAutoConfiguration::class]) 
//Выпиливаем все не нужные.

Более правильным будет выпиливание ненужных библиотек из classpath-а приложение, а то, что нужно явно исключить лучше описывать в application.{yml|properties}:

spring.autoconfigure.exclude= \ 
  org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, \
  org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, \
  org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration

Это во-первых позволяет отвязать настройки от кода, а во-вторых создав несколько файлов настроек под соответствующий профиль можно легко переключаться между ними.

Согласен, что это лучше. Просто пример одного из вариантов исключения.

Ещё стоит оптимизировать приложения по области их деятельности:

  • Должно выживать под большой нагрузкой => поднимаем фоновый процесс + пулинг модель, убираем сериализацию, переходим на Webflux (если есть возможность), включаем http/2 и.т.д.

  • Должно обрабатывать большие массивы данных => вспоминаем про спец. инструменты хранилищ данных, буфферные чтения, воскрешаем SAX парсеры и п.р.

И что ни одного квадратного алгоритма у себя не нашли? Обычно одна такая найденная и поправленная штука в хорошем месте перекрывает по эффекту примерно все перечисленное в статье, разве что кроме тяжелого шифрования в ненужном месте.

О да, я называю это внезапными квадратами. Что самое интересное, в развитой микросервисной архитектуре квадрат может быть и во взаимодействии.

В нашем случае их не было.

Добавить свободных ресурсов и скорости может ещё отказ от Spring в проекте. Не прорабатывали этот вариант?

100 % правда. Был проделан большой анализ. Рассматривали micronaut, quarqus и "свое решение". Micronaut по метрикам мало оптимизаций привносит. Quarqus 2.0 много времени на переписывание и поддержку, оставили за ним только момент с высоконагруженнымы микросервисами, но даже в нем нету решения главного бича спринга.

Наибольшей оптимизации спринга можно добиться если делать все возможные генерации в precompile, то-есть отказаться от спринга. Тогда тут можно выиграть не плохо ресурсов и RPS. Но появится другая проблема: интеграция с другими сервисами(redis, elastic и т.д.), когда в спринге ты просто можешь прикрутить стартер и все готово.

Готовых хороших решений нету, особенно с мно-вом интеграций с другими сервисами и большого комьюнити.

Micronaut по метрикам мало оптимизаций привносит

Наибольшей оптимизации спринга можно добиться если делать все возможные генерации в precompile

Но погодите, ведь микронавт ровно этим и занимается. DI, декорация, проксирование и прочее выполняется в compile time, насколько я понимаю. Какие именно метрики вам не понравились?

Кажется что это тема для отдельной статьи.

Действительно какие-то вещи он делает в compile time. Тот-же DI, он другой и делается в compile time и решает проблему с рефлексией в спринге, но quarqus представляет более оптимизированное решение. Некоторые вещи он продолжает делать в runtime, тот-же AOP - частичная компиляция. Так как micronaut пытается быть таким-же как Spring, но "лучше", из-за этого он тащит ряд похожих решений спринга.

После проделанных тестов на производительность, у нас отпали вопросы к micronaut. Micronaut производительнее чем Spring. Но не так значительно чтобы отказаться от Spring. Quarqus выглядит намного вкуснее.

Графики по 99% перцентилю. Сравнение quarqus/micronaut/spring.
Графики по 99% перцентилю. Сравнение quarqus/micronaut/spring.

то внутренние операции в StreamApi на небольших массивах все равно используют слишком много времени выполнение по сранению со StreamApi.


Вроде как описка.

Можно, пожалуйста, чуть подробнее про, тк вроде все @Componentиндексированы в спринге :

Если мы используем Spring, индексируем его компоненты с помощью spring-indexes, что даст прирост скорости запуска

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации