Сравнение производительности компонентов копирования Java Bean

Java

Система компании всегда использовала компоненты для выполнения операций копирования bean-компонентов.Я просто знаю, что эта операция влияет на производительность, но я понятия не имею, насколько сильно это повлияет. Теперь протестируйте копию Bean, чтобы получить количественные результаты.

Текущие основные компоненты Bean Copy:

  • Apache BeanUtils

  • Spring BeanUtils

  • Cglib BeanCopier

    Хорошо известно, что Apache BeanUtils имеет низкую производительность и обычно не рекомендуется. Здесь он не тестируется, тестируются только два последних компонента.

тестовая среда:

  • JAVA8
  • Spring Boot 2.1.4.RELEASE
  • локальный обычный рабочий стол

Тестовый код:

Тестовая функция: Циркулирующие N раз, скопируйте свойства в объекте Telappmodel в Telappdto, время, проведенное для каждого компонента, тем сильнее выполнение времени.

Тестовый класс POJOИсходный класс TelAppModel.java и целевой класс TelAppDto.java являются простыми классами pojo с одинаковыми переменными-членами.

Обычные методы Java set/get реализуют Bean Copy, код показан ниже:

public static void copySetGet(TelAppModel source, TelAppDto target){
       target.setId(source.getId());
       target.setTelPowerSavingMode((byte)0);
       target.setTelSecret(source.getTelSecret());
       target.setTelAppId(source.getTelAppId());
       target.setTelName(source.getTelName());
       target.setDesc(source.getDesc());
   }

Spring BeanUtils реализует копирование компонентовкод показывает, как показано ниже:

public static void copyPropertiesSpring(Object source, Object target){
    BeanUtils.copyProperties(source, target);
}

Cglib BeanCopier реализует Bean Copyкод показывает, как показано ниже:

public static void copyPropertiesCglib(Object source, Object target){
    BeanCopier beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
    beanCopier.copy(source, target, null);
}

тестовый код: longCount: определяет, сколько раз выполняется копия.

// Инициализировать longCount TelAppModels в качестве тестовых материалов перед выполнением копирования Bean

for(int i = 0; i < longCount; i++){
      appModelSourceList.add(createModel());
}

Три метода копирования Bean вызывают этот метод test() по очереди:

// set/get方法
test((a,b) -> copySetGet(a, b));

// spring BeanUtils
test((a,b) -> copyPropertiesSpring(a, b));

// spring BeanCopier
test((a,b) -> copyPropertiesCglib(a, b));

// Этот метод копирует объект TelAppModel в списке в объект TelAppDto поочередно, и печатает время выполнения longCount раз.Для обеспечения точности результата вышеуказанная операция выполняется 3 раза, то есть 3*longCount раз

private void test(BiConsumer<TelAppModel, TelAppDto> biConsumer){
    int runNum = 3;
    for(int k = 0; k < runNum; k++) {
        long loopCount = longCount;
        long begin = System.currentTimeMillis();
        for (int i = 0; i < loopCount; i++) {
            TelAppModel telAppModel1 = appModelSourceList.get(i);
            TelAppDto telAppDto = new TelAppDto();
            biConsumer.accept(telAppModel1, telAppDto);
        }
        System.out.println((System.currentTimeMillis() - begin));
    }
}

отчет о тестировании:

Запустите 1000,10000,100000,1000000 раз (мс) time: Детали времени следующим образом:

在这里插入图片描述
анализ данных:

  • ○ методы set/get теоретически должны быть самыми быстрыми
  • ○ Производительность следующая: метод set/get > Cglib BeanCopier > Sprign BeanUtils
  • ○ Spring BeanUtils каждый раз занимает много времени для первого цикла, и он не имеет такого же объема данных, как во второй раз, и данные ненормальны.

При выполнении команды просмотрите время потребляемого времени процессора через JVISULVM, Подробно, следующим образом:

在这里插入图片描述
анализ графика:

  • Когда Spring BeanUtils выполняет метод CachedIntrospectionResults.forClass() в первый раз, он загружает информацию о классе с диска в кеш памяти, а затем последующие операции получают информацию о классе из кеша. Это также объясняет, почему Spring BeanUtils работает медленно. Кроме того, эта операция является синхронной, если несколько потоков загружают один и тот же класс одновременно, возникает ситуация блокировки.
  • Весна CopyProperties BeanUtils также занимает много ресурсов ЦП, а это означает, что для фактического выполнения операции копирования Bean потребуется больше времени.
  • Глядя на приведенный выше рисунок, видно, что основное время BeanCopier тратит на вызов метода create(). На фактическое выполнение копирующего Бина уходит меньше времени. Теперь мы оптимизируем в соответствии с этим. каждый раз создавая новый BeanCopier, используйте Cache BeanCopier, созданный BeanCopier.create().Измененный код выглядит следующим образом:
 static BeanCopier beanCopierStatic = BeanCopier.create(TelAppModel.class, TelAppDto.class, false);
 
 public static void copyPropertiesCglibStatic(Object source, Object target){
     beanCopierStatic.copy(source, target, null);
 }

Затем выполните 1000, 10000, 100000, 1000000 раз соответственно (миллисекунды): подробное время выглядит следующим образом:

在这里插入图片描述

анализировать: Cglib BeanCopier优化,性能大大提高。cglib在性能和set/get方法相差不大

в заключении:

spring beanUtils 和 cglib 性能都还可以接受,如果对性能没有非常苛刻的要求,使用cglib或spring bean utils 问题都问题不大,推荐优先使用cglib