一些开源项目的性能基准Benchmark

目录 [−]

  1. Tomcat 7.0.37
    1. BIO
    2. NIO
  2. Jetty
  3. Vert.x
  4. Memcached
  5. MongoDB
  6. Java serializers
  7. CXF
  8. Spring MVC

项目中使用了好些的开源项目。对于它们的性能, 只有官方的一些性能报告和一些第三方的性能分析。 做性能估计的时候只是根据以往的经验做估算。 随着软件的不断升级,以及服务器硬件配置的升级, 这些开源项目的性能也有了变化。以前的性能数据可能不太准确了。
所以这篇文章记录了当前(2014年秋)我在AWS机器上做的一些性能数据,期望在做软件架构的时候有所帮助。
当前测试的软件包括:

  • Tomcat
  • Jetty
  • Vert.x
  • Memcached
  • MongoDB
  • Java serializers
  • CXF
  • Spring MVC

这篇文章会不断更新, 将我最新的测试列出来。

服务器采用的AWS c3.xlarge,

型号vCPU内存 (GiB)存储 (GB)
c3.xlarge47.52 x 40

Tomcat 7.0.37


Test tool: Apache Bench (ab)
JDK: build 1.7.0_17-b02

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Java Blocking Connector Java Non Blocking Connector APR/native Connector
BIO NIO APR
Classname Http11Protocol Http11NioProtocol Http11AprProtocol
Tomcat Version 3.x onwards 6.x onwards 5.5.x onwards
Support Polling NO YES YES
Polling Size N/A maxConnections maxConnections
Read HTTP Request Blocking Non Blocking Blocking
Read HTTP Body Blocking Sim Blocking Blocking
Write HTTP Response Blocking Sim Blocking Blocking
Wait for next Request Blocking Non Blocking Non Blocking
SSL Support Java SSL Java SSL OpenSSL
SSL Handshake Blocking Non blocking Blocking
Max Connections maxConnections maxConnections maxConnections

BIO

default server.xml.
采用默认的tomcat配置, TPS(throughput)可以达到3000/秒。
throughput

NIO

将BIO连接改成NIO连接。 可以看到性能有不少的提升,TPS(throughput)可以达到4500/秒。

1
2
3
4
5
6
7
8
9
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
acceptCount="100"
enableLookups="false"
compression="off"
maxConnections="65500"
maxKeepAliveRequests="1"
tcpNoDelay="true"
connectionTimeout="20000"
redirectPort="8443" />

throughput

如果用一个Servlet代替index.jsp,性能差不多。 事实上也应该如此,index.jsp最终也会编译成一个servlet(查看tomcat的work目录)。

1
2
3
4
5
6
7
8
9
10
11
@WebServlet(name = "test", urlPatterns = { "/hello" })
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = -4212401095124126998L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
PrintWriter writer = response.getWriter();
writer.println("<html>Hello servlet</html>");
writer.flush();
}
}

throughput

在吞吐率一定的情况下, 相应时间和并发数成反比:
$$
throughput = \frac{concurrency}{response\ time}
$$

例如,throughput = 3000, 并发数为1000, 则每个response的平均相应时间为330毫秒。

Jetty


Jetty提供了一个Web服务器和javax.servlet容器。 还支持 SPDY, WebSocket, OSGi, JMX, JNDI, JAAS等。 Jetty被广泛的应用在各种项目和产品中, 包括开发过程和生产系统。 Jetty很容易的被嵌入其它设备,工具,框架和应用服务器/集群中。
测试用的Jetty 是9.2.2.v20140723版本。
throughput

可以看到Jetty的吞吐率能够达到 5600 requests/second.

Vert.x


Vert.x是一个轻量级的, 高性能, 支持多语言的应用平台, 运行于JVM之上。为现代的移动应用, Web和企业应用而设计。主项目现在已经作为eclipse的一个子项目。其它项目如各种模块还在vert-x organisation自己的代码库上开发。它使用Netty处理网络IO。
它的部分核心开发人员也是netty的核心开发人员,技术应该相当高。

throughput
从图上可以看出, vert.x性能还是挺高的, 大并发下能达到10000 requests/second之上。
但是, Vert.x 毕竟还是一个小众的开发框架, 有待于生态圈的建设。 开发模式与传统的Java servlet不太一样,和常用的Spring框架等也不能很好的集成。所以能否壮大还有待观察。

Memcached


Test tool: twemperf
下面的命令创建1000个并发连接,来连接本机的11211端口(此端口是该工具的默认端口),连接创建的速度是每秒1000个,每一个连接发送“set”请求10次(相当于迭代10次),这10次请求在每秒1000的请求的速度下发送,发送的数据大小在(也就是存入到memcached中的value的大小)1~16个字节中正态分布。

1
mcperf --linger=0 --timeout=5 --conn-rate=1000 --call-rate=1000 --num-calls=10 --num-conns=1000 --sizes=u1,16

测试结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Total: connections 1000 requests 10000 responses 10000 test-duration 1.009 s
Connection rate: 991.1 conn/s (1.0 ms/conn <= 12 concurrent connections)
Connection time [ms]: avg 10.2 min 10.0 max 10.5 stddev 0.04
Connect time [ms]: avg 0.2 min 0.1 max 0.4 stddev 0.03
Request rate: 9911.1 req/s (0.1 ms/req)
Request size [B]: avg 35.9 min 28.0 max 44.0 stddev 4.80
Response rate: 9911.1 rsp/s (0.1 ms/rsp)
Response size [B]: avg 8.0 min 8.0 max 8.0 stddev 0.00
Response time [ms]: avg 0.1 min 0.0 max 2.4 stddev 0.00
Response time [ms]: p25 1.0 p50 1.0 p75 1.0
Response time [ms]: p95 1.0 p99 1.0 p999 1.0
Response type: stored 10000 not_stored 0 exists 0 not_found 0
Response type: num 0 deleted 0 end 0 value 0
Response type: error 0 client_error 0 server_error 0

再看一个测试,创建100个连接,来连接本机的11211端口,每一个连接在上一个连接断开后创建,每一个连接发送100个“set”请求,每一个请求是在收到上一个请求的响应之后创建,发送的数据大小是1个字节。

1
mcperf --linger=0 --call-rate=0 --num-calls=100 --conn-rate=0 --num-conns=100 --sizes=d1

测试结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Total: connections 100 requests 10000 responses 10000 test-duration 0.423 s
Connection rate: 236.5 conn/s (4.2 ms/conn <= 1 concurrent connections)
Connection time [ms]: avg 4.2 min 3.4 max 5.2 stddev 0.79
Connect time [ms]: avg 0.0 min 0.0 max 0.1 stddev 0.01
Request rate: 23653.1 req/s (0.0 ms/req)
Request size [B]: avg 28.0 min 28.0 max 28.0 stddev 0.00
Response rate: 23653.1 rsp/s (0.0 ms/rsp)
Response size [B]: avg 8.0 min 8.0 max 8.0 stddev 0.00
Response time [ms]: avg 0.0 min 0.0 max 0.2 stddev 0.00
Response time [ms]: p25 1.0 p50 1.0 p75 1.0
Response time [ms]: p95 1.0 p99 1.0 p999 1.0
Response type: stored 10000 not_stored 0 exists 0 not_found 0
Response type: num 0 deleted 0 end 0 value 0
Response type: error 0 client_error 0 server_error 0

get方法:

1
mcperf --linger=0 --call-rate=0 --num-calls=100 --conn-rate=0 --num-conns=100 --sizes=d1 --m=get

测试结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Total: connections 100 requests 10000 responses 10000 test-duration 0.342 s
Connection rate: 292.4 conn/s (3.4 ms/conn <= 1 concurrent connections)
Connection time [ms]: avg 3.4 min 2.9 max 4.1 stddev 0.52
Connect time [ms]: avg 0.0 min 0.0 max 0.1 stddev 0.01
Request rate: 29235.6 req/s (0.0 ms/req)
Request size [B]: avg 19.0 min 19.0 max 19.0 stddev 0.00
Response rate: 29235.6 rsp/s (0.0 ms/rsp)
Response size [B]: avg 32.0 min 32.0 max 32.0 stddev 0.00
Response time [ms]: avg 0.0 min 0.0 max 0.2 stddev 0.00
Response time [ms]: p25 1.0 p50 1.0 p75 1.0
Response time [ms]: p95 1.0 p99 1.0 p999 1.0
Response type: stored 0 not_stored 0 exists 0 not_found 0
Response type: num 0 deleted 0 end 0 value 10000
Response type: error 0 client_error 0 server_error

MongoDB


Test tool: 官方测试性能方法
mongo-perf

Java serializers


下面这个工具很强大,,通过它可以得到大多数流行的java序列化框架的benchmark。
Java serializers

这个链接是我利用这个工作在AWS做的测试结果:
Java序列化框架性能比较

json-smart 的作者提供另外一个测试,号称他的json-smart比其它框架有显著的提升,但是有人用上面的 jvm-serializers测试套件测试了一下,反而不如jackson, 虽然比一些其它的框架要好。

CXF


Test tool: Apache Bench (ab)

这里使用cxf 3.0.1实现RESTful形式的两个web service。
Web容器依然是上面的Tomcat, NIO配置。
对于普通的CXF实现 (/test/hello),仅仅返回一个String,不涉及到序列化反序列化。性能结果为:
throughput

相比于普通的tomcat下的web application,性能有所下降。

如果加上Jackson序列化,性能结果为:
throughput
性能和上面的差不多,基本能达到3000 TPS。

CXF codes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Service
@Path("/test")
public class TestService {
@GET
@Path("/hello")
public Response say() {
return Response.ok().entity("hello cxf").build();
}
@GET
@Path("/user/{id}")
public User queryUser(@PathParam("id") final String id) {
return new User("birdnest", "sadsadsadasd31edqwdwqde","abc@wqedwq.com", "127.0.0.1");
}
}
1
2
3
4
5
6
7
8
9
10
public class User {
@JsonProperty("id")
private String userid;
private String hashPassword;
private String mail;
private String ipAddress;
@JsonIgnore
private Date lastLoginDate;
......
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Bean(destroyMethod = "destroy")
public Server restEndpoint() {
List<Object> serviceBeans = new ArrayList<>();
serviceBeans.add(testService);
JAXRSServerFactoryBean factoryBean = new JAXRSServerFactoryBean();
factoryBean.setAddress("");
factoryBean.setServiceBeans(serviceBeans);
factoryBean.setProviders(Arrays.asList(
new JacksonJsonProvider(new ObjectMapper())
));
return factoryBean.create();
}

Spring MVC


这里使用Spring MVC生成两个RESTful形式的web services, 就像上面的CXF一样。正好可以和上面的CXF和Tomcat比较, 看看不同的Restful的实现框架的性能如何。

Spring MVC的实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Controller
public class SpringMVCController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
@ResponseBody
public String hello() {
return "hello MVC";
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
@ResponseBody
public User queryUser(@PathVariable( "id" ) Long id) {
return new User("birdnest", "sadsadsadasd31edqwdwqde","abc@wqedwq.com", "127.0.0.1");
}
}

hello webservice的性能如下, 看起来还不错, 比CXF框架好多了。
简单返回String类型
吞吐率可以达到3000 requests每秒。

J返回SON对象的web service的性能也不错:
返回json类型