Java列表复制性能测试报告

Java列表复制性能测试报告

作者: 杜伟 QQ:184167125

  • 1综述

本文对Java的列表(List、Map)的复制性能进行测试,并给出测试结果。在系统开发时,后台业务逻辑中的数据模型操作,需要对大量的列表进行操作,其中包含了列表的复制,这些操作要求必须满足高性能要求。本文对有100万个元素的列表进行了浅拷贝复制测试,希望通过这些测试数据,可以为系统架构的高性能设计做参考依据。作者:杜伟(微信:easydw),转发请注明。

  • 2测试结果及意义

.测试结果(List)

  1. 经过本文的测试,发现Java对列表的浅拷贝性能非常高,100万条的列表(List)拷贝只需1、2毫秒;
  2. Map的拷贝耗时稍长,约60毫秒;
  3. 内存占用上,100万条的List占用内存约71M,List复制占用内存约7.6M。

 

2.测试结果(Map)

  1. Map的浅拷贝性能一般,100万条的Map拷贝需要60毫秒左右;

    private Map<String, Object> _dataMap;

  1. Map带List拷贝性能更慢,100万条的拷贝耗时160毫秒左右;本项测试包含了创建100万个List<Object>的时间,详情见代码。这也说明了List的拷贝耗时非常少。

private Map<String, List<Object>> _dataListMap;

  1. 内存占用:Map的内存占用比较多,下面是Map<String, Object>的内存占用,100万个对象的Map竟然占用600M的内存,有点夸张,复制后的内存占用0.8M又有点偏少,几次测试均是如此。感兴趣的朋友可验证下吧。

  

3.测试意义

在高并发、高性能的后台系统中,最难处理的就是列表的操作同步问题,即:对列表的进行元素的增加和删除操作时,如此时还有对该列表的for循环,就会出现系统错误。通常做法是在增删和for循环的代码段增加同步锁,但是这样往往会导致系统性能瓶颈。

有了以上这些测试数据,在进行系统建模设计及模型高效访问时,就可以进行合理的设计,例如:列表的访问基本不再需要加同步锁,只需要进行拷贝列表即可;Map的操作可以进行封装,避免在业务模块中的循环操作,同样可取消同步锁,这样做可以让系统性能进一步的提高。

测试过程

  1. 数据准备

1.数据类采用非常简单的模拟类,如下:

public class UserInfo {
  
public String id = "";
   public int
num = 0;
}

2.测试类采用单例模式,简化系统测试

public class CopyTest {

    private static CopyTest _ct = new CopyTest();

    public static CopyTest Instance(){

        return _ct;

    }
   ……
}

3.在测试类中创建2个列表来保存数据

    _lstdata是原始保存数据列表, _lstdata2是复制后的列表保存对象.

private  int count = 1000000;

private  int index = 0;

private List<UserInfo> _lstdata2;

private List<UserInfo> _lstdata = new ArrayList<UserInfo>();



private Map<String, Object> _dataMap;     // 唯一索引列表

private Map<String, List<Object>> _dataListMap;    // 非唯一索引列表



private Map<String, Object> _dataMap2;    // 唯一索引列表

private Map<String, List<Object>> _dataListMap2;   // 非唯一索引列表
 

4.数据生成

    程序初始化时,创建100个对象并保存到_lstdata列表中。

public void InitData(){

    if (_lstdata2 != null)

        _lstdata2.clear();

    _lstdata.clear();

    List<Object> lstdata;

    _dataMap = new HashMap<>();

    _dataListMap = new HashMap<>();

    for (int i=0; i<count; i++){

        index = i;

        UserInfo ui = new UserInfo();

        ui.num = i;

        ui.id = String.valueOf(i);

        _lstdata.add(ui);
    }
 
    if (_dataMap.containsKey(ui.id) == false)

        _dataMap.put(ui.id, ui);

    if (_dataListMap.containsKey(ui.id) == false) {

        lstdata = new ArrayList<Object>();

        _dataListMap.put(ui.id, lstdata);

    }

    else {

        lstdata = _dataListMap.get(ui.id);

    }

    if (lstdata != null)

        lstdata.add(ui);

    else

        LogT.AddErr(String.format("AddItem-非唯一列表添加批量失败:未找到指定key=[%s]对应的列表,继续执行"));

}
 
}

 

    1. 浅拷贝说明

本程序采用如下语句实现List列表的复制,这种复制方式是“浅拷贝”,即:两个列表可以自行进行for循环,其中的对象都指向相同的内存区域。

_lstdata2 = new ArrayList<>(_lstdata);

    1. 性能测试
public String CopyData(){

    String ret = "";

    TimeScan timeScan = new TimeScan();

    timeScan.Start(0 ,"00");

    _lstdata2 = new ArrayList<>(_lstdata);  // 这句话耗时非常少,只是消耗部分内存

    timeScan.stopAll();

    ret = "列表元素数量:"+_lstdata.size()+", "+_lstdata2.size();

    ret += timeScan.getAllTxt();

    return ret;

}
public String CopyDic(){

    String ret = "";

    TimeScan timeScan = new TimeScan();

    timeScan.Start(0 ,"00");

    _dataMap2 = new HashMap<>(_dataMap);

    _dataMap.remove("11");

    timeScan.stopAll();



    ret = "Map元素数量:"+_dataMap.size()+", "+_dataMap2.size();

    ret += "--"+timeScan.getAllTxt();

    return ret;

}

带List的Map列表浅拷贝,包括了其中的List的拷贝,这样确保新的Map列表与原列表是独立两个对象。

public String CopyDic2(){

    String ret = "";

    TimeScan timeScan = new TimeScan();

    timeScan.Start(0 ,"00");

    _dataListMap2 = new HashMap<>(_dataListMap);

    List<Object> lst ;

    for (String key:_dataListMap2.keySet()) {

        lst = new ArrayList<>(_dataListMap2.get(key));

        _dataListMap2.put(key, lst);

    }

    List<Object> lsttmp =  _dataListMap.get("1");

    if (lsttmp != null)

        lsttmp.add(NewItem());

    timeScan.stopAll();



    ret += "<p>MapEx元素数量:"+_dataListMap.size()+", "+_dataListMap2.size();

    ret += "<p>MapEx中1的元素数:"+_dataListMap.get("1").size() +","+_dataListMap2.get("1").size();

    ret += "--"+timeScan.getAllTxt();

    return ret;

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值