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. C++Primer学习——动态内存

    静态内存:用来保存static 栈内存:保存非static 智能指针: shared_ptr:允许多个指针指向一个对象 unique_ptr:独占所指对象 weak_ptr:一种弱引用,指向share ...

  2. hihocoder #1073 : 光棍节

    描述 尽管付出了种种努力,jzp还是得过光棍节. jzp非常不爽,但也无能为力,只能够哀叹起来他的命运.他想到了一位长者的人生经验:"人的一生,不光要靠自我奋斗,也要考虑历史的进程" ...

  3. hdu 4777 树状数组+合数分解

    Rabbit Kingdom Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  4. Linux内核异常处理体系结构详解(一)【转】

    转自:http://www.techbulo.com/1841.html 2015年11月30日 ⁄ 基础知识 ⁄ 共 6653字 ⁄ 字号 小 中 大 ⁄ Linux内核异常处理体系结构详解(一)已 ...

  5. Linux查看CPU、内存、进程使用情况(转)

    在系统维护的过程中,随时可能有需要查看 CPU 使用率,并根据相应信息分析系统状况的需要.在 CentOS 中,可以通过 top 命令来查看 CPU 使用状况.运行 top 命令后,CPU 使用状态会 ...

  6. 图解JavaScript原型和原型链

    先看看最简单的栗子: //构造函数 function People(name, age){ this.name = name; this.age = age; } //原型对象(所有由构造函数实例而来 ...

  7. Structured Streaming + Kafka 集成中遇到的问题

    官方指导:http://spark.apache.org/docs/2.2.0/structured-streaming-kafka-integration.html 1.版本问题  起初用的kafk ...

  8. .net环境下跨进程、高频率读写数据

    一.需求背景 1.最近项目要求高频次地读写数据,数据量也不是很大,多表总共加起来在百万条上下. 单表最大的也在25万左右,历史数据表因为不涉及所以不用考虑, 难点在于这个规模的热点数据,变化非常频繁. ...

  9. Python3 XML解析

    什么是XML? XML 指可扩展标记语言(eXtensible Markup Language),标准通用标记语言的子集,是一种用于标记电子文件使其具有结构性的标记语言. 你可以通过本站学习XML教程 ...

  10. android注解入门 并来自己写一个框架

    介绍 这里我带大家来学习一下注解 并且用来写下一个模仿xUtils3 中View框架 此框架 可以省略activity或者fragment的 findViewById 或者设置点击事件的烦恼 我正参加 ...