As a new employee, one of the first tasks is to read other people's code. I will go straight to the topic and read the code through pre-reading, I found several methods to implement value replication between two different types of beans. I found that there were performance differences after querying the internet, so I came up with the idea of understanding several implementations. The first step is to first explore whether the performance difference we have summarized is correct based on the principle of seeking truth from facts.
There are four replication methods: BeanUtils of Apache, PropertyUtils of Spring, BeanUtils of Cglib, and BeanCopier of Cglib. In Eclipse, a Project is created to specifically test the performance of several codes. The specific code is as follows: A FromBean and a ToBean have basically the same Code, except for the class name, so only one copy is posted.
public class FromBean {private String name;private int age;private String address;private String idno;private double money;public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}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;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getIdno() {return idno;}public void setIdno(String idno) {this.idno = idno;}}
A BenchmarkTest class for testing. To reduce repeated code, a policy mode is written.
Public class BenchmarkTest {private int count; public BenchmarkTest (int count) {this. count = count; System. out. println ("Performance Test" + this. count + "=");} public void benchmark (IMethodCallBack m, FromBean frombean) {try {long begin = new java. util. date (). getTime (); ToBean tobean = null; System. out. println (m. getMethodName () + "start testing"); for (int I = 0; I <count; I ++) {tobean = m. callMethod (frombean);} long end = new java. util. date (). getTime (); System. out. println (m. getMethodName () + "Time consumed" + (end-begin); System. out. println (tobean. getAddress (); System. out. println (tobean. getAge (); System. out. println (tobean. getIdno (); System. out. println (tobean. getMoney (); System. out. println (tobean. getName (); System. out. println ("");} catch (Exception e) {e. printStackTrace ();}}}
Interface Declaration used in the policy
public interface IMethodCallBack { String getMethodName(); ToBean callMethod(FromBean frombean) throws Exception;}
Used test class
Public class TestMain {/*** @ param args */public static void main (String [] args) {FromBean fb = new FromBean (); fb. setAddress ("Datun Road, Chaoyang District, Beijing"); fb. setAge (20); fb. setMoney (30000.111); fb. setIdno ("110330219879208733"); fb. setName ("test"); IMethodCallBack beanutilCB = new IMethodCallBack () {@ Override public String getMethodName () {return "BeanUtil. copyProperties ";}@ Override public ToBean callMethod (FromBean frombean) throws Exception {ToBean toBean = new ToBean (); BeanUtils. copyProperties (toBean, frombean); return toBean ;}}; IMethodCallBack propertyCB = new IMethodCallBack () {@ Override public String getMethodName () {return "PropertyUtils. copyProperties ";}@ Override public ToBean callMethod (FromBean frombean) throws Exception {ToBean toBean = new ToBean (); PropertyUtils. copyProperties (toBean, frombean); return toBean ;}}; IMethodCallBack springCB = new IMethodCallBack () {@ Override public String getMethodName () {return "org. springframework. beans. beanUtils. copyProperties ";}@ Override public ToBean callMethod (FromBean frombean) throws Exception {ToBean toBean = new ToBean (); org. springframework. beans. beanUtils. copyProperties (frombean, toBean); return toBean ;}}; IMethodCallBack cglibCB = new IMethodCallBack () {BeanCopier bc = BeanCopier. create (FromBean. class, ToBean. class, false); @ Override public String getMethodName () {return "BeanCopier. create ";}@ Override public ToBean callMethod (FromBean frombean) throws Exception {ToBean toBean = new ToBean (); bc. copy (frombean, toBean, null); return toBean ;}};
// When the number is small, the test performance BenchmarkTest bt = new BenchmarkTest (10); bt. benchmark (beanutilCB, fb); bt. benchmark (propertyCB, fb); bt. benchmark (springCB, fb); bt. benchmark (cglibCB, fb );
// Test 10 thousand performance tests BenchmarkTest bt10000 = new BenchmarkTest (10000); bt0000.benchmark (beanutilCB, fb); bt0000.benchmark (propertyCB, fb); bt0000.benchmark (springCB, fb ); bt10000.benchmark (cglibCB, fb );
// Worried that the test result BenchmarkTest bt1000R = new BenchmarkTest (10000) and bt1000R will be affected due to the order problem. benchmark (cglibCB, fb); bt1000R. benchmark (springCB, fb); bt1000R. benchmark (propertyCB, fb); bt1000R. benchmark (beanutilCB, fb );}}
After three tests, the final results are as follows:
10 quizzes |
First time |
Second |
Third time |
Average Value |
Average value each time |
BeanUtil. copyProperties |
54 |
57 |
50 |
53.66667 |
5.366666667 |
PropertyUtils. copyProperties |
4 |
4 |
4 |
4 |
0.4 |
Org. springframework. beans. BeanUtils. copyProperties |
12 |
10 |
11 |
11 |
1.1 |
BeanCopier. create |
0 |
0 |
0 |
0 |
0 |
10000 quizzes |
First time |
Second |
Third time |
Average Value |
Average value each time |
BeanUtil. copyProperties |
241 |
222 |
226 |
229.6667 |
0.022966667 |
PropertyUtils. copyProperties |
92 |
90 |
92 |
91.33333 |
0.009133333 |
Org. springframework. beans. BeanUtils. copyProperties |
29 |
30 |
32 |
30.33333 |
0.003033333 |
BeanCopier. create |
1 |
1 |
1 |
1 |
0.1 |
10000 reverse quiz |
First time |
Second |
Third time |
Average Value |
Average value each time |
BeanUtil. copyProperties |
178 |
174 |
178 |
176.6667 |
0.017666667 |
PropertyUtils. copyProperties |
91 |
87 |
89 |
89 |
0.0089 |
Org. springframework. beans. BeanUtils. copyProperties |
21 |
21 |
21 |
21 |
0.0021 |
BeanCopier. create |
0 |
1 |
1 |
0.666667 |
6.66667E-05 |
However, during the test, Cglib first caches the instance, which is also one of the reasons for its good performance. If the cache is removed, there will be some performance differences, but the overall performance is still good, But the strange thing is that 10000 times is less than 10 times, in addition, the subsequent reversal of 10 thousand times is the least time-consuming, so is the result of multiple tests. According to the overall performance, the performance of BeanCopier of Cglib is the best, whether it is a large number of 10 thousand tests, or a small number of 10 times, almost always close to zero loss, spring provides better performance when the number of times is increased. When there is less data, the performance is worse than that of PropertyUtils. PropertyUtils has relatively stable performance and shows a linear growth trend. The performance of BeanUtil in Apache is the worst, and the performance is not good, whether it is a single Copy or a large number of multiple copies.
|
10 times |
10000 times |
10000 reversal |
BeanCopier. create |
41 |
28 |
10 |
The performance test is here, and the data is also shown as above. The remaining two articles will be written later. This article focuses on performance, the next article will explain the differences in the use of each method. The last article will discuss what the performance difference between the four methods has long been.