登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

清风幻影的博客

Where there is love, I will be there.

 
 
 

日志

 
 
关于我

同是天涯沦落人,相逢何必曾相识. 天生我材必有用,千金散尽还复来. 天若有情天亦老,人间正道是沧桑. 月影西斜人已去, 堤上梅花情依旧, 此情故已成追忆, 美人如玉夜留香

java反射效率  

2010-09-19 11:37:18|  分类: java_5 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
java反射效率到底如何,花了点时间,做了一个简单的测试.供大家参考.

测试背景:
1. 测试简单Bean(int,Integer,String)的set方法
2. loop 1亿次
3. 测试代码尽可能避免对象的创建,复发方法的调用,仅仅测试set方法的耗时

测试结果:
 场景  本机测试结果(XP,双核,2G) 服务器测试结果(Linux,XEN虚拟机,8核,5.5G)
方法直接调用 235MS 190MS
JDK Method调用
29188MS
4633MS
JDK Method调用(稍作优化)
5672MS
4262MS
Cglib FastMethod调用
5390MS
2787MS

得出一个感性的结果:
1.JDK反射效率是直接调用的一个数量级,差不多20倍
2.一个set方法的反射调用时间 = 4633ms / 1亿 / 3次 = 0.0154us
3.Cglib的fastmethod还是有优势的

最后,附上测试代码:
  1 /**
  2  * <pre>
  3  * 本机测试结果(XP,双核,2G):
  4  * 直接调用(LOOP=1亿):       235MS 
  5  * 反射调用(LOOP=1亿):       29188MS
  6  * 反射调用(优化)(LOOP=1亿):  5672MS
  7  * 放射调用(CGLIB)(LOOP=1亿):5390MS
  8  * 
  9  * 服务器测试结果(linux xen虚拟机,5.5G内存;8核CPU):
 10  * 直接调用(LOOP=1亿):       190MS
 11  * 反射调用(LOOP=1亿):       4633MS
 12  * 反射调用(优化)(LOOP=1亿):  4262MS
 13  * 放射调用(CGLIB)(LOOP=1亿):2787MS
 14  * </pre>
 15  * 
 16  * @author Stone.J 2010-9-15 上午10:07:27
 17  */
 18 public class ReflectionTest {
 19 
 20     private static final int                      DEFAULT_INT                = 1;
 21     private static final Integer                  DEFAULT_INTEGER            = 1;
 22     private static final String                   DEFAULT_STRING             = "name";
 23     private static final Object[]                 DEFAULT_INTS               = { 1 };
 24     private static final Object[]                 DEFAULT_INTEGERS           = new Integer[] { 1 };
 25     private static final Object[]                 DEFAULT_STRINGS            = new String[] { "name" };
 26 
 27     private static final Bean                     BEAN                       = new Bean();
 28 
 29     private static final CachedMethod             CACHED_METHOD              = new CachedMethod();
 30     private static final OptimizationCachedMethod OPTIMIZATION_CACHED_METHOD = new OptimizationCachedMethod();
 31     private static final CglibCachedMethod        CGLIB_CACHED_METHOD        = new CglibCachedMethod();
 32 
 33     private static final long                     LOOP                       = 1 * 10000 * 10000;
 34 
 35     // 测试main
 36     public static void main(String[] args) {
 37         if (args.length != 1) {
 38             System.out.println("args error.");
 39             System.exit(1);
 40         }
 41         int tc = Integer.valueOf(args[0]);
 42 
 43         long start = System.currentTimeMillis();
 44         for (long i = 0; i < LOOP; i++) {
 45             switch (tc) {
 46                 case 1:
 47                     // 直接调用
 48                     test();
 49                     break;
 50                 case 2:
 51                     // 反射调用
 52                     testReflection();
 53                     break;
 54                 case 3:
 55                     // 优化后反射调用
 56                     testOptimizationReflection();
 57                     break;
 58                 case 4:
 59                     // cglib反射调用
 60                     testCglibReflection();
 61                     break;
 62                 default:
 63                     System.out.println("tc error. must be [1-4]");
 64                     break;
 65             }
 66         }
 67         long dur = System.currentTimeMillis() - start;
 68         System.out.println(dur);
 69     }
 70 
 71     // 直接调用测试
 72     public static void test() {
 73         BEAN.setId(DEFAULT_INT);
 74         BEAN.setCode(DEFAULT_INTEGER);
 75         BEAN.setName(DEFAULT_STRING);
 76     }
 77 
 78     // 反射调用测试
 79     public static void testReflection() {
 80         try {
 81             CACHED_METHOD.setId.invoke(BEAN, DEFAULT_INTS);
 82             CACHED_METHOD.setCode.invoke(BEAN, DEFAULT_INTEGERS);
 83             CACHED_METHOD.setName.invoke(BEAN, DEFAULT_STRINGS);
 84         } catch (Exception e) {
 85             e.printStackTrace();
 86         }
 87     }
 88 
 89     // 优化后反射调用测试
 90     public static void testOptimizationReflection() {
 91         try {
 92             OPTIMIZATION_CACHED_METHOD.setId.invoke(BEAN, DEFAULT_INTS);
 93             OPTIMIZATION_CACHED_METHOD.setCode.invoke(BEAN, DEFAULT_INTEGERS);
 94             OPTIMIZATION_CACHED_METHOD.setName.invoke(BEAN, DEFAULT_STRINGS);
 95         } catch (Exception e) {
 96             e.printStackTrace();
 97         }
 98     }
 99 
100     // cglib反射调用测试
101     public static void testCglibReflection() {
102         try {
103             CGLIB_CACHED_METHOD.cglibSetId.invoke(BEAN, DEFAULT_INTS);
104             CGLIB_CACHED_METHOD.cglibSetCode.invoke(BEAN, DEFAULT_INTEGERS);
105             CGLIB_CACHED_METHOD.cglibSetName.invoke(BEAN, DEFAULT_STRINGS);
106         } catch (Exception e) {
107             e.printStackTrace();
108         }
109     }
110 
111     /**
112      * <pre>
113      * 测试的bean
114      * 简单的int Integer String类型
115      * </pre>
116      * 
117      * @author Stone.J 2010-9-15 上午10:40:40
118      */
119     public static class Bean {
120 
121         private int     id;
122         private Integer code;
123         private String  name;
124 
125         public int getId() {
126             return id;
127         }
128 
129         public void setId(int id) {
130             this.id = id;
131         }
132 
133         public Integer getCode() {
134             return code;
135         }
136 
137         public void setCode(Integer code) {
138             this.code = code;
139         }
140 
141         public String getName() {
142             return name;
143         }
144 
145         public void setName(String name) {
146             this.name = name;
147         }
148 
149     }
150 
151     /**
152      * 反射测试需要:Cached Method
153      * 
154      * @author Stone.J 2010-9-15 上午10:41:04
155      */
156     public static class CachedMethod {
157 
158         public Method setId;
159         public Method setCode;
160         public Method setName;
161 
162         {
163             try {
164                 setId = Bean.class.getDeclaredMethod("setId"int.class);
165                 setCode = Bean.class.getDeclaredMethod("setCode", Integer.class);
166                 setName = Bean.class.getDeclaredMethod("setName", String.class);
167             } catch (Exception e) {
168                 e.printStackTrace();
169             }
170         }
171 
172     }
173 
174     /**
175      * 反射测试需要:优化后的Cached Method
176      * 
177      * @author Stone.J 2010-9-15 上午10:41:21
178      */
179     public static class OptimizationCachedMethod extends CachedMethod {
180 
181         {
182             /** 所谓的优化 */
183             setId.setAccessible(true);
184             setCode.setAccessible(true);
185             setName.setAccessible(true);
186         }
187 
188     }
189 
190     /**
191      * 反射测试需要,使用cglib的fast method
192      * 
193      * @author Stone.J 2010-9-15 上午10:51:53
194      */
195     public static class CglibCachedMethod extends CachedMethod {
196 
197         public FastMethod cglibSetId;
198         public FastMethod cglibSetCode;
199         public FastMethod cglibSetName;
200 
201         private FastClass cglibBeanClass = FastClass.create(Bean.class);
202 
203         {
204             cglibSetId = cglibBeanClass.getMethod(setId);
205             cglibSetCode = cglibBeanClass.getMethod(setCode);
206             cglibSetName = cglibBeanClass.getMethod(setName);
207         }
208 
209     }
210 
211 }
  评论这张
 
阅读(1711)| 评论(0)

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018