#java #performance #optimization #memory
#java #Производительность #оптимизация #память
Вопрос:
Говорят, что преждевременная оптимизация — это корень всего зла, но вот так…
У нас есть высокопроизводительное приложение; кэш в памяти, поддерживаемый Java на стороне сервера, и то, что должно быть очень быстрым графическим интерфейсом C # на стороне клиента.
Я отмечаю, что в настоящее время объекты, которые мы используем в кэше, имеют значения по умолчанию — например, инициализирующие строки по умолчанию на «» и даты на 1/1/1999 вместо того, чтобы оставлять их нулевыми.
Возможно, я здесь очень привередлив, но разве это не добавляет немного больше места для каждого объекта (как в кэше, так и при сериализации объекта), чем в противном случае, если бы оно было null?
Просто интересно, какого рода улучшения (если таковые имеются) будут достигнуты, когда наши объемы объектов начнут становиться довольно высокими…
Приветствую, Дэйв.
Комментарии:
1. @f1dave: вау… Высокопроизводительное приложение, и вы храните даты в объектах? Момент времени должен храниться в примитиве (скажем, в Java long ) в виде (миллисекунд), прошедших с момента начала эпохи. Это почти всегда верно, особенно если речь идет о производительности. Единственный момент, когда вам нужно «отформатировать» этот момент времени как дату, — это когда какой-то пользователь хочет прочитать его удобным для пользователя способом (скажем, в своем собственном часовом поясе и т.д.).
2. @Аноним. Я вообще не понимаю, как это связано с вопросом производительности.
3. @Kaj — OP спросил о «немного большем пространстве», а не о процессоре.
4. И использование значений по умолчанию (также известных как «шаблон нулевого объекта») обычно предназначено для предотвращения NPE.
5. О, послушайте, конечно, я был бы обеспокоен NPE. Но я на мгновение надеваю свою черную шляпу (дурацкую шляпу, что угодно). @SyntaxT3rr0r — В кэше хранятся объекты. Сами объекты имеют атрибуты, которые настолько просты, насколько это возможно, в основном примитивы. Однако они используют java.util.Date.
Ответ №1:
Преждевременная оптимизация, безусловно, является злом.
Но думать о характеристиках производительности вашего приложения и соответствующих стратегиях проектирования для оптимизации производительности вполне разумно, если производительность является ключевым требованием приложения 🙂
Несколько важных моментов:
- Есть некоторые (незначительные) преимущества в производительности от использования null вместо значения по умолчанию. Машинному коду проще проверить наличие значения null, чем разыменовывать ссылку на объект и проверять значение этого объекта. Вероятно, вы этого не заметите, если все находится в кэше L1, но если это приводит к отсутствию кэша в высокопроизводительном приложении, это может стать болезненным.
- Существует некоторая дополнительная нагрузка на память, но это, вероятно, не имеет большого значения — предполагая, что вы повторно используете одни и те же объекты со значением по умолчанию много раз (т. Е. Многие ключи указывают на одно и то же значение), тогда в целом не будет много дополнительных экземпляров объекта.
- Если ваши значения по умолчанию неизменяемы, одноэлементные объекты, то это очень помогает по трем причинам:
- Вам нужна только одна копия неизменяемого объекта, а не разные экземпляры «» (String.intern() здесь помогает!)
- Гораздо более вероятно, что один объект, используемый много раз, будет эффективно кэшироваться
- Вы можете использовать равенство ссылок (value == DEFAULT_SINGLETON) для проверки значения по умолчанию, что позволяет избежать необходимости разыменования указателя, когда DEFAULT_SINGLETON является статическим конечным значением.
- Если вы используете неизменяемые одноэлементные значения по умолчанию, будьте очень осторожны, чтобы не подмешать какие-либо другие экземпляры того же значения. Это может произойти, например, при десериализации объектов — вам нужно использовать readResolve() и т.д. чтобы убедиться, что вы получаете правильное значение singleton на месте.
На мой взгляд, вам, вероятно, следует предпочесть null для значений по умолчанию.
- Это немного быстрее и использует меньше памяти
- Это, скорее всего, поможет вам обнаружить логическую ошибку (с помощью громкого исключения NullPointerException, а не вызовет трудноотслеживаемую ошибку с использованием значения по умолчанию вместо реального значения)
Комментарии:
1. Приветствую mikera. Да, похоже, мы довольно последовательны в использовании неизменяемых одноэлементных объектов, как вы говорите. И что вы знаете, парень, который написал исходный код, тот, кто просит меня исследовать значения null 😉