@aloxc
2017-12-05T06:20:59.000000Z
字数 16436
阅读 788
ignite
cache
如题,这段时间在研究ignite,看样子ignite还是挺好的一东西,但是做这几天做了cache功能的性能测试,发现一些问题,
1、嵌入式(clientMode=false,且只在java中使用start方法内嵌启动ignite)性能还行吧
2、本地模式(clientMode=true,且在测试机器上独立的启动一个ignite服务,windows执行bin/ignite.bat,linux执行bin/ignite.sh,并且在此测试机器上运行性能测试的java代码)性能差很多。
3、集群模式(clientMode=true,独立在两台机器上启动ignite服务,在第三台机器上运行性能测试代码)性能一样的差。
这些测试对应的其它配置为
1. 缓存配置:关闭备注backups=0
2. 缓存配置:不限制堆外内存大小OffHeapMaxMemory=0
3. 缓存配置:初始化缓存容量大小 StartSize = 300 * 1024 *1024
4. 缓存配置:禁用交换存储空间swapEnabled=false
5. 部署模式设置为DeploymentMode=SHARED
6. 对等类加载PeerClassLoadingEnabled=true
每次每项测试完毕后清空缓存,每项做20次测试后取平均值,测试数据量分别为5000,10000,20000,50000,100000,测试线程分别为1线程,10线程,20线程,50线程,100线程,200线程。测试方法为总数据量除以线程数就是每线程需要测试的数据量,测试开始时间为startTime,每项操作的所有线程执行完毕的时间为endTime,spendTime=endTime-startTime,所有20次测试的spendTime相加后除以20,得到平均操作时间avgSpendTime,再用总数据量除以avgSpendTime得出每秒能执行的次数。
经过几论测试下来,得到下面这些数据,从数据看出,ignite的cache功能根本无法用于线上服务(嵌入式基本上没什么用),无法做OLTP的补充。
本地windows机器配置:
intel 奔腾 G2030,win7 64bit,8GB ram,180G intel 320 ssd with sata2,
linux机器配置(3台):
intel 至强 E5606,centos release 6.2 final 64bit 2.6.32内核,4GB ram,xxG sas,
以下测试结果的数字是指每秒能执行的次数,
config.txt
thread_count=1,10,20,50,100,200
data_count=5000,10000,20000,50000,100000
show_log=false
test_count=20
client_mode=0
is_avg_time=false
spi_windows=127.0.0.1:47500..47509
spi_linux=172.31.16.68:47500..47509,172.31.16.69:47500..47509
config.txt
thread_count=1,10,20,50,100,200
data_count=5000,10000,20000,50000,100000
show_log=false
test_count=20
client_mode=1
is_avg_time=false
spi_windows=127.0.0.1:47500..47509
spi_linux=172.31.16.68:47500..47509,172.31.16.69:47500..47509
config.txt
thread_count=1,10,20,50,100,200
data_count=5000,10000,20000,50000,100000
show_log=false
test_count=20
client_mode=0
is_avg_time=false
spi_windows=127.0.0.1:47500..47509
spi_linux=172.31.16.68:47500..47509,172.31.16.69:47500..47509
config.txt
thread_count=1,10,20,50,100,200
data_count=5000,10000,20000,50000,100000
show_log=false
test_count=20
client_mode=1
is_avg_time=false
spi_windows=127.0.0.1:47500..47509
spi_linux=172.31.16.68:47500..47509,172.31.16.69:47500..47509
config.txt
thread_count=1,10,20,50,100,200
data_count=5000,10000,20000,50000,100000
show_log=false
test_count=20
client_mode=2
is_avg_time=false
spi_windows=127.0.0.1:47500..47509
spi_linux=172.31.16.68:47500..47509,172.31.16.69:47500..47509
config.txt
thread_count=1,10,20,50,100,200
data_count=5000,10000,20000,50000,100000
show_log=false
test_count=20
client_mode=2
is_avg_time=false
spi_windows=127.0.0.1:47500..47509
spi_linux=172.31.16.68:47500..47509
补充下:测试的缓存类型key为Integer,value为下面这个bean的实例。每次操作的key和value都不一样,下面是所有测试代码,
IgniteBenchmark2.java
package com.github.aloxc.ignite.benchmark;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.DeploymentMode;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.IndexedColors;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.CountDownLatch;
/**
* Created by Administrator on 2016/12/9.
*/
public class IgniteBenchmark2 {
private static Log logger = LogFactory.getLog(IgniteBenchmark2.class);
//测试的数据行数
private static int[] DATA_COUNT_ARRAY;
private static int[] THREAD_COUNT_ARRAY;
private static boolean isWindows = false;
private static final String CACHE_NAME = "benchmark2";
private static Ignite IGNITE;
private static IgniteCache<Integer, BenchmarkUser> CACHE;
private Map<Integer, Set<Integer>> keyMap = null;
private Map<Integer, Map<Integer, BenchmarkUser>> valueMap = null;
private static int TEST_COUNT = 0;
private static int CLIENT_MODE = 0;//0:嵌入式,1:本地,2,集群
private static boolean IS_AVG_TIME = false;
private static List<String> IP_LIST = null;
private static String outPath;
private static boolean SHOW_LOG = false;
static {
Properties props = System.getProperties(); //获得系统属性集
String osName = props.getProperty("os.name"); //操作系统名称
if (osName.toLowerCase().contains("windows")) {
isWindows = true;
}
}
public static void main(String[] args) {
logger.error("开始测试benchmark2");
try {
File file;
if (isWindows) {
file = new File("D:\\ideaprojects\\ignite-examples\\config\\config.txt");
outPath = "D:/log/ignite-benchmark-windows";
} else {
file = new File("/usr/java/ignitebenchmark/config.txt");
outPath = "/usr/java/ignitebenchmark/ignite-benchmark-linux";
}
if (!file.exists()) {
logger.error("config文件不存在,退出程序 " + file.getAbsolutePath());
System.exit(1);
} else {
Properties properties = new Properties();
properties.load(new FileInputStream(file));
String[] infos = properties.getProperty("data_count").split(",");
DATA_COUNT_ARRAY = new int[infos.length];
for (int i = 0; i < infos.length; i++) {
DATA_COUNT_ARRAY[i] = Integer.parseInt(infos[i]);
}
CLIENT_MODE = Integer.parseInt(properties.getProperty("client_mode"));
infos = properties.getProperty("thread_count").split(",");
THREAD_COUNT_ARRAY = new int[infos.length];
for (int i = 0; i < infos.length; i++) {
THREAD_COUNT_ARRAY[i] = Integer.parseInt(infos[i]);
}
IgniteConfiguration cfg = new IgniteConfiguration();
if(CLIENT_MODE == 0 ) {
cfg.setClientMode(false);
outPath += "-嵌入式";
}else{
cfg.setClientMode(true);
TcpDiscoverySpi spi = new TcpDiscoverySpi();
TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
if(CLIENT_MODE == 1){
ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500..47509".split(",")));
outPath += "-本地";
}else if(CLIENT_MODE == 2){
outPath += "-集群";
if (isWindows) {
ipFinder.setAddresses(Arrays.asList(properties.getProperty("spi_windows").split(",")));
} else {
ipFinder.setAddresses(Arrays.asList(properties.getProperty("spi_linux").split(",")));
}
}
spi.setIpFinder(ipFinder);
cfg.setDiscoverySpi(spi);
}
CacheConfiguration cacheConfiguration = new CacheConfiguration<String, DataClass>();
cacheConfiguration.setCacheMode(CacheMode.PARTITIONED);//分区
cacheConfiguration.setBackups(0);//关闭备份
//cacheConfiguration.setOffHeapMaxMemory(0);//不限制堆外内存大小
cacheConfiguration.setStartSize(3 * 1024 *1024);//初始化缓存容量大小,类似于hashmap的size
cacheConfiguration.setSwapEnabled(false);//禁用交换存储
cfg.setCacheConfiguration(cacheConfiguration);
cfg.setDeploymentMode(DeploymentMode.SHARED);
cfg.setPeerClassLoadingEnabled(true);
TEST_COUNT = Integer.parseInt(properties.getProperty("test_count"));
SHOW_LOG = Boolean.parseBoolean(properties.getProperty("show_log"));
IS_AVG_TIME = Boolean.parseBoolean(properties.getProperty("is_avg_time"));
if(IS_AVG_TIME){
outPath += "-取平均时间";
}else{
outPath += "-取总时间";
}
outPath += ".xls";
IGNITE = Ignition.start(cfg);
CACHE = IGNITE.getOrCreateCache(CACHE_NAME);
}
logger.error("资源初始化完毕" + CLIENT_MODE);
new IgniteBenchmark2().test();
} catch (Exception e) {
e.printStackTrace();
} finally {
logger.error("程序运行完毕,删除缓存");
IGNITE.destroyCache(CACHE_NAME);
System.exit(1);
}
}
private void test() throws Exception {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
HSSFRow row = null;
HSSFCell cell = null;
int rowIndex = 0;
int cellIndex = 0;
HSSFCellStyle threadActionStyle = wb.createCellStyle();
threadActionStyle.setFillForegroundColor(IndexedColors.LIGHT_CORNFLOWER_BLUE.getIndex());
threadActionStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
HSSFCellStyle dataCountStyle = wb.createCellStyle();
dataCountStyle.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.getIndex());
dataCountStyle.setFillPattern(CellStyle.SOLID_FOREGROUND);
for (int dataIndex = 0; dataIndex < DATA_COUNT_ARRAY.length; dataIndex++) {
int cellI = 0;
int dataCount = DATA_COUNT_ARRAY[dataIndex];
row = sheet.createRow(rowIndex++);//数据量和线程行
cell = row.createCell(0);
cell.setCellValue("总数据量" + dataCount);
cell.setCellStyle(dataCountStyle);
cellIndex = 0;
for (int threadIndex = 0; threadIndex < THREAD_COUNT_ARRAY.length; threadIndex++) {
int threadCount = THREAD_COUNT_ARRAY[threadIndex];
cellIndex++;
cell = row.createCell(cellIndex);
cell.setCellValue(threadCount + "线程");
cell.setCellStyle(threadActionStyle);
}
row = sheet.createRow(rowIndex++);//写入行
cell = row.createCell(0);
cell.setCellValue("写入");
cell.setCellStyle(threadActionStyle);
row = sheet.createRow(rowIndex++);//读取行
cell = row.createCell(0);
cell.setCellValue("读取");
cell.setCellStyle(threadActionStyle);
row = sheet.createRow(rowIndex++);//批量写入行
cell = row.createCell(0);
cell.setCellValue("批量写入");
cell.setCellStyle(threadActionStyle);
row = sheet.createRow(rowIndex++);//批量读取行
cell = row.createCell(0);
cell.setCellValue("批量读取");
cell.setCellStyle(threadActionStyle);
rowIndex++;
}
for (int i = 0; i < THREAD_COUNT_ARRAY.length + 1; i++) {
sheet.setColumnWidth(i, 256 * 15);
}
int preThreadCount = 1;
int preDataCount = 50000;
keyMap = new HashMap<>(preThreadCount);
valueMap = new HashMap<>(preThreadCount);
genObject(preThreadCount, preDataCount);
new WriteThread(0, null, false, valueMap.get(0),"测试写").run();
new ReadThread(0, null, false, keyMap.get(0),"测试读").run();
Thread.sleep(5000);
for (int dataIndex = 0; dataIndex < DATA_COUNT_ARRAY.length; dataIndex++) {
int dataCount = DATA_COUNT_ARRAY[dataIndex];
final int baseRowIndex = dataIndex * 6;//
for (int threadIndex = 0; threadIndex < THREAD_COUNT_ARRAY.length; threadIndex++) {
int threadCount = THREAD_COUNT_ARRAY[threadIndex];
keyMap = new HashMap<>(threadCount);
valueMap = new HashMap<>(threadCount);
genObject(threadCount, dataCount);
logger.error("开始benchmark测试,threadCount=" + threadCount + "\tdataCount=" + dataCount);
float[] spends = new float[4];
for (int ti = 0; ti < TEST_COUNT; ti++) {
CACHE.removeAll();
float avgSpend = 0f;
WriteThread[] writeThreads = new WriteThread[threadCount];
CountDownLatch latch = new CountDownLatch(threadCount);
float interval;
float tpms;
long start = System.currentTimeMillis();
for (int i = 0; i < writeThreads.length; i++) {
writeThreads[i] = new WriteThread(i, latch, false, valueMap.get(i),"[写线程-" + i + "]");
writeThreads[i].start();
}
latch.await();
long end = System.currentTimeMillis();
if (IS_AVG_TIME) {
avgSpend = 0f;
for (int i = 0; i < writeThreads.length; i++) {
avgSpend += writeThreads[i].getSpend();
}
avgSpend = avgSpend / writeThreads.length;
spends[0] += avgSpend;
} else {
spends[0] += end - start;
}
Thread.sleep(50);
ReadThread[] readThreads = new ReadThread[threadCount];
latch = new CountDownLatch(threadCount);
start = System.currentTimeMillis();
for (int i = 0; i < readThreads.length; i++) {
readThreads[i] = new ReadThread(i, latch, false, keyMap.get(i),"[读线程-" + i + "]");
readThreads[i].start();
}
latch.await();
end = System.currentTimeMillis();
if (IS_AVG_TIME) {
avgSpend = 0f;
for (int i = 0; i < readThreads.length; i++) {
avgSpend += readThreads[i].getSpend();
}
avgSpend = avgSpend / writeThreads.length;
spends[1] += avgSpend;
} else {
spends[1] += end - start;
}
CACHE.removeAll();
Thread.sleep(50);
latch = new CountDownLatch(threadCount);
start = System.currentTimeMillis();
for (int i = 0; i < writeThreads.length; i++) {
writeThreads[i] = new WriteThread(i, latch, true, valueMap.get(i),"[批量写线程-" + i + "]");
writeThreads[i].start();
}
latch.await();
end = System.currentTimeMillis();
if (IS_AVG_TIME) {
avgSpend = 0f;
for (int i = 0; i < writeThreads.length; i++) {
avgSpend += writeThreads[i].getSpend();
}
avgSpend = avgSpend / writeThreads.length;
spends[2] += avgSpend;
} else {
spends[2] += end - start;
}
Thread.sleep(50);
latch = new CountDownLatch(threadCount);
start = System.currentTimeMillis();
for (int i = 0; i < readThreads.length; i++) {
readThreads[i] = new ReadThread(i, latch, true, keyMap.get(i),"[批量读线程-" + i + "]");
readThreads[i].start();
}
latch.await();
end = System.currentTimeMillis();
if (IS_AVG_TIME) {
avgSpend = 0f;
for (int i = 0; i < readThreads.length; i++) {
avgSpend += readThreads[i].getSpend();
}
avgSpend = avgSpend / writeThreads.length;
spends[3] += avgSpend;
} else {
spends[3] += end - start;
}
}
rowIndex = baseRowIndex + 1;
cellIndex = threadIndex + 1;
for (int i = 0; i < spends.length; i++) {
row = sheet.getRow(rowIndex++);
cell = row.createCell(cellIndex);
float avgSpend = spends[i] / 1000L;
avgSpend /= TEST_COUNT;
cell.setCellValue(Math.ceil(dataCount / avgSpend));
}
}
}
logger.error("测试完毕,准备输出测试结果到[" + outPath + "]");
FileOutputStream out = new FileOutputStream(outPath);
wb.write(out);
out.close();
}
/**
* 产生测试数据
*/
private void genObject(int threadCount, int dataCount) {
long start = System.currentTimeMillis();
Random r = new Random();
int perCount = dataCount / threadCount;
for (int i = 0; i < threadCount; i++) {
Map<Integer, BenchmarkUser> map = new HashMap<>(dataCount);
Set<Integer> keyset = new HashSet<>(dataCount);
int id = 0;
for (int j = 0; j < perCount; j++) {
BenchmarkUser user = new BenchmarkUser();
id = i * perCount + j;
user.setId(id);
user.setName("user-" + id);
user.setCommentCount(id);
user.setComposeCount(id);
user.setReplyCount(id);
user.setIp("ip" + id);
user.setLoginCount(id);
user.setPermission(r.nextBoolean());
user.setLoginTime(new Timestamp(System.currentTimeMillis()));
user.setRegisterTime(new Timestamp(System.currentTimeMillis()));
map.put(id, user);
keyset.add(id);
}
keyMap.put(i, keyset);
valueMap.put(i, map);
}
// logger.error("生成测试数据花费" + (System.currentTimeMillis() - start) + "毫秒,线程数 = " + threadCount + ",每线程数据量 = " + (dataCount / threadCount));
}
static class ReadThread extends Thread {
private final int index;
private final CountDownLatch latch;
private Set<Integer> keySet;
private final boolean bBatch;
private long spend = 0;
public ReadThread(int index, CountDownLatch latch, boolean bBatch, Set<Integer> keySet,String threadName) {
super(threadName);
this.index = index;
this.latch = latch;
this.keySet = keySet;
this.bBatch = false;
}
public long getSpend() {
return spend;
}
@Override
public void run() {
long start = System.currentTimeMillis();
if (bBatch) {
CACHE.getAll(keySet);
} else {
long spend1 = System.currentTimeMillis();
for (Integer key : keySet) {
CACHE.get(key);
}
// logger.error("读取线程[" + index + "]花费" + (keySet.size() / (System.currentTimeMillis() - spend1)) + "毫秒");
}
spend = System.currentTimeMillis() - start;
if (SHOW_LOG) {
logger.error(this.getName() + "花费" + (spend) + "毫秒");
}
if (latch != null) {
latch.countDown();
}
}
}
static class WriteThread extends Thread {
private final int index;
private final CountDownLatch latch;
private final boolean bBatch;
private Map<Integer, BenchmarkUser> valueMap;
private long spend = 0;
public WriteThread(int index, CountDownLatch latch, boolean bBatch, Map<Integer, BenchmarkUser> valueMap,String threadName) {
super(threadName);
this.index = index;
this.latch = latch;
this.bBatch = bBatch;
this.valueMap = valueMap;
}
public long getSpend() {
return spend;
}
@Override
public void run() {
long start = System.currentTimeMillis();
if (bBatch) {
CACHE.putAll(valueMap);
} else {
long spend1 = System.currentTimeMillis();
for (Map.Entry<Integer, BenchmarkUser> entry : valueMap.entrySet()) {
CACHE.put(entry.getKey(), entry.getValue());
}
// logger.error("写入线程[" + index + "]花费" + (valueMap.size() / (System.currentTimeMillis() - spend1)) + "毫秒");
}
spend = System.currentTimeMillis() - start;
if (SHOW_LOG) {
logger.error(this.getName() + "花费" + spend + "毫秒");
}
if (latch != null) {
latch.countDown();
}
}
}
}
BenchmarkUser.java
package com.github.aloxc.ignite.benchmark;
import com.github.aloxc.fw.util.JsonUtil;
import java.io.Serializable;
import java.sql.Timestamp;
/**
* Created by Administrator on 2016/12/15.
*/
public class BenchmarkUser implements Serializable{
private int id; // 自增长ID[回复ID]
private String name; // 用户名
private String ip; // 用户IP
private int loginCount; // 登录次数
private int composeCount; // 发表主题数
private int replyCount; // 回复数
private int commentCount; // 评论数
private boolean permission; // [没有注销=true][已被注销=false]
private Timestamp loginTime; // 最新上站时间
private Timestamp registerTime; // 注册时间
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BenchmarkUser other = (BenchmarkUser) obj;
if (id != other.id)
return false;
return true;
}
@Override
public String toString() {
return JsonUtil.toJson(this);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getLoginCount() {
return loginCount;
}
public void setLoginCount(int loginCount) {
this.loginCount = loginCount;
}
public int getComposeCount() {
return composeCount;
}
public void setComposeCount(int composeCount) {
this.composeCount = composeCount;
}
public int getReplyCount() {
return replyCount;
}
public void setReplyCount(int replyCount) {
this.replyCount = replyCount;
}
public int getCommentCount() {
return commentCount;
}
public void setCommentCount(int commentCount) {
this.commentCount = commentCount;
}
public boolean isPermission() {
return permission;
}
public void setPermission(boolean permission) {
this.permission = permission;
}
public Timestamp getLoginTime() {
return loginTime;
}
public void setLoginTime(Timestamp loginTime) {
this.loginTime = loginTime;
}
public Timestamp getRegisterTime() {
return registerTime;
}
public void setRegisterTime(Timestamp registerTime) {
this.registerTime = registerTime;
}
}