文章目录
前言
- 本文使用 Spock(可集成Spring Boot项目) 编写测试用例,基于 Groovy (JVM语言)
- 用例的目标为 Mybatis 的查询api
- 用例数据量10W 行
- 用例仓库地址
1. 配置用例堆内存大小
-Xmx100m,配置堆内存大小,让溢出情况更快出现
2. 单次全量查造成 GC overhead limit exceeded
3. 分片查询减轻GC压力
- 使用 Guava 的工具分片查询同一批数据,异常消失。
4. Spock 语法积累
4.1 测试用例的钩子函数
Spock 相关的钩子函数造数
- setup 方法——用例执行前调用
- cleanup 方法——用例执行后调用
@SpringBootTest(classes = KetchupApplication.class)
class GcSpec extends Specification {
@Resource
FileOutputRecordMapper mapper
/**
* 十万条数据库查询
*/
Long startId = 1;
Long endId = 100000;
/**
* 生成十万条数据,测试用例执行完后删除
*/
def setup() {
def allIds = (startId..endId).toList()
Lists.partition(allIds, 1000).forEach { subIds ->
def sub = subIds.collect(it -> createPO(it))
mapper.batchInsertWithId(sub);
}
}
def cleanup() {
mapper.deleteByIdRang(startId, endId)
}
}
4.2 given when then expect 的用法
以下是已知的三种用例写法
def "分片查询" () {
given:
when:
then:
}
def "分片查询" () {
when:
then:
}
def "分片查询" () {
given:
expect:
}
5. Groovy 语法积累
5.1 Rang 数据结构
- rang 声明
def rang = (startId .. endId)
- 普通的 list 声明 ()
def list = [1,2,3]
- rang 转 list
// 生成一个list,内部的元素是从1 到 100000的数值类型
def allIds = (1 .. 100000).toList()
5.2 List.collect
// 以下的 collect 写法比Java简洁很多
def sub = subIds.collect(it -> createPO(it))
// 等价于 Java 的写法
List<FileOutputRecordPO> poList = subIds.stream().map(it -> createPO(it)).collect(Collectors.toList())
6. Guava 工具类积累
Lists.partition(allIds, 1000).forEach...
本文的集合分片工具来自:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1-jre</version>
</dependency>
后记
大数据量的查询时,避免用一个大List<>装大量数据,必要时将数据分片,减轻GC压力。
大数据的不同任务,尽量串行化执行,避免出现GC毛刺。