spring 上的 aop 性能(idk,aspectj) [英] aop performance on spring (idk, aspectj)
问题描述
我尝试在 Spring 框架 4.1.6 上测试 AOP 的性能
I tried to test the performance of AOP on Spring framework 4.1.6 and
AOP 方法干净,jdk 动态代理和aspectJ.
AOP methods were clean, jdk dynamic proxy and aspectJ.
我向他们提出了 1 到 5 个简单的建议,并检查了每个建议所用的时间.
I made one to five simple advices to them and checked elapsed time for each.
结果:
jdk 动态代理:
- aspect1:2.499 秒
- 方面 2:2.574
- 方面 3:2.466
- 方面 4:2.436
- 方面 5:2.563
aspectJ (ctw):
- 方面 1:2.648
- 方面2:2.562
- 方面 3:2.635
- 方面 4:2.520
- 方面 5:2.574
干净(没有方面):
- 方面 1:2.699
- 方面2:2.513
- 方面 3:2.527
- 方面 4:2.458
- 方面 5:2.402
在测试它们之前,我预计 AspectJ (ctw) 会比 Jdk 动态代理更快,因为 AspectJ 修改了字节码.但即使它们之间没有性能差异也是错误的.
Before testing them, I expected AspectJ (ctw) will be faster than Jdk dynamic proxy because AspectJ modified bytecode. But it was wrong even there was no performance difference among them.
因此,我检查了修改后的目标类(.class)以识别使用了 AspectJ Compiler 并发现字节码被修改.
So, I checked the target class(.class) modified to recognise that AspectJ Compiler used and found bytecode modified.
这里,我有一个问题:它们之间有什么性能差异吗?(idk动态代理,aspectj,无aop)
Here, I have question: Is there any performance difference among them? (idk dynamic proxy, aspectj, no aop)
我的代码:
public class HelloAOP {
public static void main(String [] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/application-context.xml");
Order order = (Order) ctx.getBean("orderImpl");
SimpleDateFormat format = new SimpleDateFormat("mm:ss.SSS");
StopWatch watch = new StopWatch();
watch.start();
order.placeOrder();
watch.stop();
System.out.println("Elapsed: " + format.format(watch.getTotalTimeMillis()));
}
}
目标:
@Service
public class OrderImpl implements Order {
public void placeOrder() {
System.out.println("::Target Object");
for(long i = 0; i < 5000000000L; i++);
}
}
方面:
@Aspect
@Component
public class Aspect1 {
@Before("execution(* com.cafe.beans.impl.OrderImpl.placeOrder())")
public void aspect() {
System.out.println("Aspect 1 *");
}
}
pom.xml:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.1.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-instrument</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.6</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.8.6</version>
</dependency>
<build>
<finalName>testAop</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>3.3</source>
<target>3.3</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Tests.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<complianceLevel>1.8</complianceLevel>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
推荐答案
您不应该对没有看到任何差异感到惊讶,因为您只是在测量一个方法调用.99.9% 的测量时间是方法内部的循环.因此,您没有测量正确的东西.你应该反过来做,可能类似于我在这里所做的:
You should not be surprised not to see any difference because you are just measuring one single method call. 99.9% of the time measured is the loop inside your method. Ergo you are not measuring the right thing. You should do it the other way around, maybe similar to what I did here:
- 该方法不应执行任何操作或几乎不执行任何操作并且不打印任何内容.
- 您应该测量重复调用方面建议的方法的总时间,因为您想了解应用方面的开销,而不是方法体运行时(方法体保持不变,您的方面).
现在您可以将 Spring AOP 与 AspectJ 的性能进行比较,应该会看到 AspectJ 更胜一筹.一些注意事项:
Now you can compare Spring AOP to AspectJ performance and should see that AspectJ is superior. A few caveats:
- 我希望您知道您需要更改 Spring 配置,以便从 Spring AOP 切换到 AspectJ,反之亦然.例如.如果您一直使用 AspectJ Maven 插件进行构建,那么您将使用编译时 AspectJ 编织,无论您是将 Spring 配置为通过加载时编织使用 Spring AOP 还是 AspectJ,如 Spring 手册第 10.8 使用 AspectJSpring 应用程序.
- 您应该衡量不同类型的切入点和建议,例如
@Before
/@After
vs.@Around
,(不)通过this()
使用参数绑定,target()
或args()
等 - 另请注意,您的示例代码在类而不是接口上使用切入点.JDK 动态代理不能直接在类上工作,但只能在接口上工作.为了在类上应用 Spring AOP,你需要 CGLIB 作为 Spring 的依赖,否则它根本无法工作.好的,您的类实现了
Order
接口,因此它可能仍然适用于 JDK 动态代理.
- I hope you know that you need to change the Spring configuration so as to switch from Spring AOP to AspectJ and vice versa. E.g. if you use the AspectJ Maven Plugin all the time for your builds, you will use compile-time AspectJ weaving, no matter if you configure Spring to use Spring AOP or AspectJ via load-time weaving as described in the Spring manual, section 10.8 Using AspectJ with Spring applications.
- You should measure different types of pointcuts and advice, e.g.
@Before
/@After
vs.@Around
, (not) using parameter binding viathis()
,target()
orargs()
etc. - Please also note that your sample code uses a pointcut on a class rather than an interface. JDK dynamic proxies do not work directly on classes, though, only on interfaces. In order to apply Spring AOP on classes, you need CGLIB as a dependency in Spring, otherwise it simply will not work. Okay, your class implements the
Order
interface, so it might still work with JDK dynamic proxies.
这篇关于spring 上的 aop 性能(idk,aspectj)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!