DRUID VS ANTLR4

测试方法

环境:x86_64,eclipse kepler,jdk 6

测试对象:antlr v4,druid手写sql parser模块

测试过程:分别采用单线程、多线程并发测试。单线程时,比较antlr、druid各自解析1次同一条sql语句的性能;多线程(50线程)时,比较antlr、druid所有线程完成1次同一条sql解析的性能。

测试结果##

类别 单线程(druid比antlr) 多线程(druid比antlr)
简单select 7倍 6倍
复杂select 约200倍 约1600倍
Insert 6倍 11倍
Update 15倍 13倍
Delete 3倍 4倍

总结##

1、性能:druid好于antlr。

2、语法支持:两者皆可实现各类语法,但antlr易于druid实现。目前发现druid没有完全实现pg语法,如int ‘123’类型转换。

3、可维护性:antlr好于druid 特别是体现在新增语法时,修改druid的工作量大于antlr。

4、可读性:antlr好于druid antlr采用独立的语法文件管理语法规则,druid语法规则与代码耦合。

5、关键字支持:两者皆支持。druid需要使用switch语句块穷举。


package com.laudandjolynn.test;

import java.text.NumberFormat;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.Options; import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;
import com.laudandjolynn.idb.AntlrParser; public class SqlParser {
private final static String ANTLR = "ANTLR";
private final static String DRUID = "DRUID"; public static void main(String[] args) throws Exception {
CommandLineParser clp = new BasicParser();
Options options = new Options();
options.addOption("t", true, "");
options.addOption("m", true, "");
options.addOption("p", true, "");
options.addOption("s", true, "");
CommandLine cl = clp.parse(options, args);
String helpMsg = "usage: java -jar test.jar -t {antlr|druid} [-m times] [-p threads] -s sql";
if (!cl.hasOption('t') || !cl.hasOption('s')) {
System.out.println(helpMsg);
System.exit(0);
} String tool = cl.getOptionValue('t');
String sql = cl.getOptionValue('s');
int threadCount = cl.hasOption('p') ? Integer.valueOf(cl
.getOptionValue('p')) : 1;
int executeTimes = cl.hasOption('m') ? Integer.valueOf(cl
.getOptionValue('m')) : 1;
if (threadCount == 1) {
single(1, sql, tool, false);
single(executeTimes, sql, tool, true);
} else {
multiple(1, sql, tool, 1, false);
multiple(executeTimes, sql, tool, threadCount, true);
}
System.exit(0);
} private static void single(int executeTimes, String sql, String tool,
boolean stat) {
long sum = 0;
long max = Long.MIN_VALUE;
long min = Long.MAX_VALUE;
int maxIndex = -1;
for (int j = 0; j < executeTimes; j++) {
long start = System.nanoTime();
parse(sql, tool);
long elapse = System.nanoTime() - start;
if (max < elapse) {
max = elapse;
maxIndex = j;
}
if (min > elapse) {
min = elapse;
}
sum += elapse;
}
if (stat) {
NumberFormat format = NumberFormat.getInstance();
format.setMaximumFractionDigits(3);
System.out.println("max: " + format.format(max / 1000000.0)
+ " ms. max value index: " + maxIndex);
System.out
.println("min: " + format.format(min / 1000000.0) + " ms");
System.out.println("avg: "
+ format.format(sum / (double) executeTimes / 1000000.0)
+ " ms");
}
} private static void multiple(int executeTimes, String sql, String tool,
int threadCount, boolean stat) throws Exception {
ExecutorService executorService = Executors
.newFixedThreadPool(threadCount);
CompletionService<Long[]> completionService = new ExecutorCompletionService<Long[]>(
executorService);
for (int i = 0; i < threadCount; i++) {
completionService.submit(new Parser(executeTimes, sql, tool));
} long sum = 0;
long max = Long.MIN_VALUE;
long min = Long.MAX_VALUE;
int maxIndex = -1;
for (int i = 0; i < threadCount; i++) {
Long[] elapses = completionService.take().get();
for (int j = 0; j < executeTimes; j++) {
if (max < elapses[j]) {
max = elapses[j];
maxIndex = i * j;
}
if (min > elapses[j]) {
min = elapses[j];
}
sum += elapses[j];
}
} if (stat) {
NumberFormat format = NumberFormat.getInstance();
format.setMaximumFractionDigits(3);
System.out.println("max: " + format.format(max / 1000000.0)
+ " ms. max value index: " + maxIndex);
System.out
.println("min: " + format.format(min / 1000000.0) + " ms");
System.out.println("avg: "
+ format.format(sum / executeTimes / threadCount
/ 1000000.0) + " ms");
}
} private static class Parser implements Callable<Long[]> {
private String sql = null;
private String tool = null;
private int executeTimes; public Parser(int executeTimes, String sql, String tool) {
this.executeTimes = executeTimes;
this.sql = sql;
this.tool = tool;
} @Override
public Long[] call() throws Exception {
Long result[] = new Long[executeTimes];
for (int i = 0; i < executeTimes; i++) {
long start = System.nanoTime();
parse(sql, tool);
result[i] = System.nanoTime() - start;
}
return result;
}
} private static void parse(String sql, String tool) {
if (ANTLR.equalsIgnoreCase(tool)) {
AntlrParser.parse(sql);
} else if (DRUID.equalsIgnoreCase(tool)) {
new PGSQLStatementParser(sql).parseStatement();
}
}
}

Druid VS Antlr4的更多相关文章

  1. Spring + SpringMVC + Druid + MyBatis 给你一个灵活的后端解决方案

    生命不息,折腾不止. 折腾能遇到很多坑,填坑我理解为成长. 两个月前自己倒腾了一套用开源框架构建的 JavaWeb 后端解决方案. Spring + SpringMVC + Druid + JPA(H ...

  2. Spring + SpringMVC + Druid + JPA(Hibernate impl) 给你一个稳妥的后端解决方案

    最近手头的工作不太繁重,自己试着倒腾了一套用开源框架组建的 JavaWeb 后端解决方案. 感觉还不错的样子,但实践和项目实战还是有很大的落差,这里只做抛砖引玉之用. 项目 git 地址:https: ...

  3. 学记:spring boot使用官网推荐以外的其他数据源druid

    虽然spring boot提供了4种数据源的配置,但是如果要使用其他的数据源怎么办?例如,有人就是喜欢druid可以监控的强大功能,有些人项目的需要使用c3p0,那么,我们就没办法了吗?我们就要编程式 ...

  4. druid连接池获取不到连接的一种情况

    数据源一开始配置: jdbc.initialSize=1jdbc.minIdle=1jdbc.maxActive=5 程序运行一段时间后,执行查询抛如下异常: exception=org.mybati ...

  5. druid配置数据库连接使用密文密码

    spring使用druid配置dataSource片段代码 dataSource配置 <!-- 基于Druid数据库链接池的数据源配置 --> <bean id="data ...

  6. [转]阿里巴巴数据库连接池 druid配置详解

    一.背景 java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池.数据库连接池有很多选择,c3p.dhcp.proxool等,druid作为一名后起之秀,凭借其出色 ...

  7. 技术杂记-改造具有监控功能的数据库连接池阿里Druid,支持simple-jndi,kettle

    kettle内置的jndi管理是simple-jndi,功能确实比较简单,我需要监控kettle性能,druid确实是很不错的选择,但没有提供对应的支持,我改进了druid源码,实现了simple-j ...

  8. sql 连接数不释放 ,Druid异常:wait millis 40000, active 600, maxActive 600

    Hibernate + Spring + Druid 数据库mysql 由于配置如下 <bean id="dataSource" class="com.alibab ...

  9. druid sql黑名单 报异常 sql injection violation, part alway true condition not allow

    最近使用druid,发现阿里这个连接池 真的很好用,可以监控到连接池活跃连接数 开辟到多少个连接数 关闭了多少个,对于我在项目中查看错误 问题,很有帮助, 但是最近发现里面 有条sql语句 被拦截了, ...

随机推荐

  1. UVA1349:Optimal Bus Route Design

    题意:给定一个有向带权图,找若干个环,使得每个点属于且仅属于一个环,要求使得环权值之和最小 题解:发现这题中每个点属于且仅属于一个环,这时候"仅"这种恰好的含义,让我们想到了匹配问 ...

  2. 洛谷mNOIP模拟赛Day1-斐波那契

    题目背景 大样例下发链接:http://pan.baidu.com/s/1c0LbQ2 密码:jigg 题目描述 小 C 养了一些很可爱的兔子. 有一天,小 C 突然发现兔子们都是严格按照伟大的数学家 ...

  3. [BZOJ]1069: [SCOI2007]最大土地面积

    题目大意:给出二维平面上n个点,求最大的由这些点组成的四边形面积.(n<=2000) 思路:求出凸包后旋转卡壳枚举对踵点对作为四边形的对角线,枚举或二分另外两个点,复杂度O(n^2)或O(nlo ...

  4. hdu 5135(2014广州—状态dp)

    t题意:给你n条边,构造任意个三角形,一个三角形恰好只用3条边,每条边只能一次,求面积最大值 思路: 最开始想的是先排序从大到小取,但感觉并不怎么靠谱. 最多12条边,所以可以求出所有可能的三角形面积 ...

  5. poj3580 splay树 REVOVLE循环

    SuperMemo Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12795   Accepted: 3989 Case T ...

  6. [bzoj4881][Lydsy2017年5月月赛]线段游戏

    来自FallDream的博客,未经允许,请勿转载,谢谢. quailty和tangjz正在玩一个关于线段的游戏.在平面上有n条线段,编号依次为1到n.其中第i条线段的两端点坐标分别为(0,i)和(1, ...

  7. vue拦截器实现统一token,并兼容IE9验证

    项目中使用vue搭建前端页面,并通过axios请求后台api接口,完成数据交互.如果验证口令token写在在每次的接口中,也是个不小的体力活,而且也不灵活.这里分享使用vue自带拦截器,给每次请求的头 ...

  8. IntelliJ IDEA光标变粗 backspace无法删除内容解决方法

    进入了vim插件 1.ctrl+alt+s快捷键打开Settings 2.选择左侧列表中的Plugins 3.在右侧面板的搜索框中搜索IdeaVim 4.将复选框中的钩子去掉 backspace成了其 ...

  9. BZOJ#1717:[Usaco2006 Dec]Milk Patterns 产奶的模式(后缀数组+单调队列)

    1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的 ...

  10. Linux系统中安装Oracle过程记录

    第一章 安装数据库软件 1.1 修改密码及创建目录和权限 创建oracle用户和组 创建相关目录并赋权 1.2 设置oracle用户环境变量 ORACLE_BASE:产品基目录 ORACLE_HOME ...