Шаблон Java «Прототип» - новый против клона против class.newInstance

В моем проекте есть несколько фабрик-прототипов, которые создают экземпляры путем клонирования окончательного частного экземпляра.

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

Используя google, чтобы получить некоторые подсказки об этом, я не нашел ничего подходящего. Вот небольшой отрывок из javadoc неизвестного проект

К сожалению, clone() работает медленнее, чем вызов new. Однако это намного быстрее, чем вызов java.lang.Class.newInstance(), и несколько быстрее, чем наш собственный метод «клонирования».

Для меня это выглядит как старая передовая практика времени java 1.1. Кто-нибудь знает об этом больше? Это хорошая практика для использования этого с «современным» jvm?


person Guillaume    schedule 11.03.2010    source источник


Ответы (6)


Безусловно, этот вид практики полностью устарел. С тех пор виртуальная машина Java значительно улучшилась. Создание объекта чрезвычайно дешево. Другая связанная с этим практика, объединение объектов в пул, также устарела, потому что стоимость создания и очистки объектов теперь намного эффективнее. В некоторых случаях это может быть полезно (Джон Скит приводит здесь несколько хороших примеров), но ни в коем случае образом, он должен быть частью базовой библиотеки фреймворка, такой как эта.

Я бы посоветовал найти новые библиотеки и/или новый проект для работы ;-)

Ознакомьтесь с этой статьей класса Java Urban Performance Legends для большего понимания.

person Mark Renouf    schedule 11.03.2010
comment
Спасибо за ссылку, я знал, что с этим дизайном что-то не так, но мне нужны были некоторые «академические» доказательства! - person Guillaume; 12.03.2010
comment
Мне просто нужно смягчить ответ: это недействительно для Android-разработчика: передовая практика Google продвигает использование клонирования/объединения по сравнению с созданием объекта - person Guillaume; 21.06.2010
comment
Да, Android написан на Java, но на самом деле это не Java, так что это технически правильно. Точнее сказать, что объединение объектов больше не требуется для Sun HotSpot JVM (и других подобных ей). Dalvik — это собственное животное, и создание объектов и GC могут быть дорогими и болезненными на устройствах с ограниченными ресурсами, поэтому всегда следуйте рекомендациям вашей целевой платформы/JVM. (Хотя я бы хотел, чтобы это было не так, это пока.) - person Mark Renouf; 22.06.2010

Гы. Это одна из худших идей, которые я когда-либо слышал.

Не делай странных вещей. Даже если вы измерили и увидели какое-то очевидное улучшение (ну, в данном случае это нулевой шанс), долго подумайте, прежде чем делать это. Кто знает, это будет исправлено в следующей JVM. Затем у вас остается какой-то странный фрагмент кода, который хуже работает, его трудно читать, и из-за этого некоторые ошибки.

Я имею в виду, что люди, разрабатывающие JVM, не идиоты! Используйте 1_!

Я думаю, вам следует избавиться от этого странного фрагмента кода.

person Enno Shioji    schedule 11.03.2010

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

Хотелось бы, чтобы у меня все еще был код, которым я мог бы поделиться, но некоторое время назад я провел простой тест производительности этого шаблона по сравнению с использованием «нового» оператора и обнаружил, что использование «нового» оператора в худшем случае было так же быстро, как этот шаблон, и в лучшем случае быстрее и эффективнее. Может быть какой-то пограничный случай, который мой тест не охватил, где это все еще может быть допустимым подходом, но в целом я бы посоветовал избегать этого шаблона.

Еще одно замечание: я бы посоветовал вам не слишком беспокоиться об этом, если он присутствует в существующей кодовой базе. Но также я бы не стал писать новый код, чтобы расширить этот шаблон для большего количества частей вашего проекта, если только это не повредит ясности и непротиворечивости вашей кодовой базы — в этот момент вы должны оценить, будет ли это разумно в долгое время, чтобы реорганизовать этот код из вашего проекта. Под «умным» я подразумеваю, будет ли рефакторинг этого кода вне вашего проекта экономить время в будущем на разработку и отладку> количество времени, необходимое для рефакторинга этого.

person Tom Neyland    schedule 11.03.2010

No.

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

person Yishai    schedule 11.03.2010

Я создал простой тест для класса Person. Я использую последнюю версию OpenJDK 8:

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

И получил следующие результаты:

Benchmark             Mode  Cnt     Score       Error   Units

MyBenchmark.viaClone  avgt   10     10.041 ±    0.059   ns/op
MyBenchmark.viaNew    avgt   10      7.617 ±    0.113   ns/op

Этот простой тест показывает, что создание экземпляра нового объекта и установка соответствующих свойств из исходного объекта занимает на 25 % меньше времени, чем его клонирование.

person Andrii Abramov    schedule 13.07.2017

Мои тесты с DecimalFormat (OpenJDK 8/Windows/JMH 1.19) показывают совершенно противоположное изображение:

Benchmark               Mode  Cnt     Score     Error  Units
Format.everyTimeCreate  avgt   10  9326.967 ± 199.511  us/op
Format.useClone         avgt   10  5102.397 ±  72.993  us/op
Format.useGlobalWithTL  avgt   10  4605.604 ±  59.000  us/op

Похоже, не так просто ответить, что работает лучше.

person Gmugra    schedule 18.10.2017