String变量引起的Loadrunner资源泄漏


在压力测试中,通常碰到TPS平稳持续下降的现象,通常为负载机存在资源泄漏。一般有两种:1.连接数,2.JVM内存。本文就第2种类型进行测试和分析。



 

测试数据:

1.       String方式

public int action() throws Throwable {

lr.start_transaction("string");

 

String a = "The time is "+System.currentTimeMillis();

        String b = "The time is "+System.currentTimeMillis();

        String c = "The time is "+System.currentTimeMillis();

        String d = "The time is "+System.currentTimeMillis();

        String e = "The time is "+System.currentTimeMillis();

         lr.end_transaction("stringl", lr.AUTO);

 

写了个简单的给String变量赋值的代码,使用当前时间保证每次赋值都会变化。10个线程执行30分钟。

 

测试结果:

 

TPS持续下降:

 

YGC非常频繁:

同时CPU有走高的趋势

 

 

2.       StringBuilder方式一(New对象放在Action内)

 

//new放在Action中,每次迭代都new一个对象

 

         public int action() throws Throwable {

         lr.start_transaction("StringBuilder");

         StringBuilder bf1=new StringBuilder();

         StringBuilder bf2=new StringBuilder();

         StringBuilder bf3=new StringBuilder();

         StringBuilder bf4=new StringBuilder();

         StringBuilder bf5=new StringBuilder();

         bf1.append("The time is ");

        bf2.append("The time is ");

         bf3.append("The time is ");

         bf4.append("The time is ");

         bf5.append("The time is ");

         bf1.append(System.currentTimeMillis());

        bf2.append(System.currentTimeMillis());

         bf3.append(System.currentTimeMillis());

         bf4.append(System.currentTimeMillis());

         bf5.append(System.currentTimeMillis());

        bf1.setLength(0);

         bf2.setLength(0);

        bf3.setLength(0);

         bf4.setLength(0);

         bf5.setLength(0);

         lr.end_transaction("StringBuilder", lr.AUTO);

 

TPS

         

         TPS同样会下降

 

堆内存

 

 

 

3.       StringBuilder方式二(New对象放在Action外)

 

public class Actions

{

         StringBuilder bf1=new StringBuilder();

         StringBuilder bf2=new StringBuilder();

         StringBuilder bf3=new StringBuilder();

         StringBuilder bf4=new StringBuilder();

         StringBuilder bf5=new StringBuilder();

          

         public int init() throws Throwable {

 

                   return 0;

         }//end of init

 

 

         public int action() throws Throwable {

                  

         lr.start_transaction("StringBuilder");

 

         bf1.append("The time is ");

        bf2.append("The time is ");

         bf3.append("The time is ");

         bf4.append("The time is ");

         bf5.append("The time is ");

         bf1.append(System.currentTimeMillis());

        bf2.append(System.currentTimeMillis());

         bf3.append(System.currentTimeMillis());

         bf4.append(System.currentTimeMillis());

         bf5.append(System.currentTimeMillis());

        bf1.setLength(0);

         bf2.setLength(0);

        bf3.setLength(0);

         bf4.setLength(0);

         bf5.setLength(0);

         lr.end_transaction("StringBuilder", lr.AUTO);

 

                   return 0;

         }//end of action

 

 

TPS

TPS有轻微下降,但下降幅度比前两种方式要改善很多。

 

堆内存

从内存Dump中看到StringBuilder 实例有50 10用户,每个用户new 5个对象),但仍然有其他对象占很大比重,不清楚是否是Loadrunner本身所占用。

 



 

测试结果

1.       采用String类型给变量赋值,半小时看到TPS明显下降,并且负载机CPU有上升趋势,剩余内存有下降趋势;

2.       采用StringBuilder给变量赋值,new StringBuilder对象放在Action内(每次迭代均new一次),执行半小时,现象同String类型差不多;

3.       采用StringBuilder给变量赋值,new StringBuilder对象放在Action外,执行半小时,TPS有所下降,但下降趋势比前两个场景要小很多。

 

原因分析

1.       String 类型和 StringBuffer/StringBuilder 类型的主要性能区别其实在于 String 是不可变的对象,因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,(脚本中变量取当前时间,保证每次取值不同) new 对象需要消耗资源,并且当内存中无引用对象多了以后, JVM  GC 就会开始工作,导致GC频繁;

2.       由于本次压力测试与MAMBPS有一个共同特点,TPS比较高,因此可能是对象生成速度非常快,GC来不及回收,导致对象不断累积,并且GC越来越频繁导致了CPU上升和TPS逐渐下降,一般应用的TPS较低,因此有足够时间进行回收;

3.       另外,采用Loadrunner Java Vuser方式,LR本身也会生成一些对象,在高TPS下可能会出现对象来不及释放导致性能下降。

 

 

你可能感兴趣的:(瓶颈分析)