String连接的简单性能测试

/**

* String连接性能测试

*@author x1ny

*@date 2015/8/8

*/



根据String 的字节码实现知道 使用 “+”连接字符串实际上是创建了一个StringBuffer对象进行连接操作然后再转换为String对象。下面将在具体测试程序中测试性能的差异。


测试方法:用四种不同的连接方式 创建“tsettesttesttesttest”字符串1千万次,查看其性能差别

测试代码:


public class StringConnectionTest {

	public static void main(String[] args) {
		connByOperationOnce(10000000);
		connByOperation(10000000);
		connByStringBuffer(10000000);
		connByStringBuilder(10000000);
	}
	
	public static void connByOperationOnce(int count){
		long endTime;
		long time;
		long startTime = System.currentTimeMillis();
		String str;
		for(int i = 0; i <= count; i++)
			str = "test" + "test" + "test" + "test" + "test";
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("使用加号一次连接字符串" + count + "次所需要的时间为:" + time + "ms" );
	}
	
	public static void connByOperation(int count){
		long endTime;
		long time;
		long startTime = System.currentTimeMillis();
		String str;
		for(int i = 0; i <= count; i++){
			str = "test";
			str += "test";
			str += "test";
			str += "test";
			str += "test";
		}
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("使用加号多次连接字符串" + count + "次所需要的时间为:" + time + "ms" );
	}

	public static void connByStringBuffer(int count){
		long endTime;
		long time;
		long startTime = System.currentTimeMillis();
		String str;
		for(int i = 0; i <= count; i++){
			StringBuffer sb = new StringBuffer("test");
			sb.append("test");
			sb.append("test");
			sb.append("test");
			sb.append("test");
			str = sb.toString();
		}
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("使用StringBuffer连接字符串" + count + "次所需要的时间为:" + time + "ms" );
	}
	
	public static void connByStringBuilder(int count){
		long endTime;
		long time;
		long startTime = System.currentTimeMillis();
		String str;
		for(int i = 0; i <= count; i++){
			StringBuilder sb = new StringBuilder("test");
			sb.append("test");
			sb.append("test");
			sb.append("test");
			sb.append("test");
			str = sb.toString();
		}
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("使用StringBuilder连接字符串" + count + "次所需要的时间为:" + time + "ms" );
	}
}

测试结果:


测试版本为1.6.0_65

使用加号一次连接字符串10000000次所需要的时间为:10ms

使用加号多次连接字符串10000000次所需要的时间为:3383ms

使用StringBuffer连接字符串10000000次所需要的时间为:1561ms

使用StringBuilder连接字符串10000000次所需要的时间为:1199ms


测试版本为1.7.0_79

使用加号一次连接字符串10000000次所需要的时间为:6ms

使用加号多次连接字符串10000000次所需要的时间为:2452ms

使用StringBuffer连接字符串10000000次所需要的时间为:2097ms

使用StringBuilder连接字符串10000000次所需要的时间为:864ms


测试版本为1.8.0_40

使用加号一次连接字符串10000000次所需要的时间为:5ms

使用加号多次连接字符串10000000次所需要的时间为:1782ms

使用StringBuffer连接字符串10000000次所需要的时间为:726ms

使用StringBuilder连接字符串10000000次所需要的时间为:840ms


发现使用 String str = "test" + "test" + "test" + "test" + "test" ; 性能与其他方式差距太大,几乎为0,查看字节码可以发现:

     11: ldc           #68                 // String testtesttesttesttest

编译器在编译时直接将语句优化为 String str = "testtesttesttesttest'" 并没有进行连接操作,于是乎花费时间几乎为0。


测试将被连接的字符串“test‘用局部变量保存。


将测试代码改为:


package mytest;

public class StringConnectionTest {

	public static void main(String[] args) {
		System.out.println("测试版本为" + System.getProperty("java.version"));
		connByOperationOnce(10000000);
		connByOperation(10000000);
		connByStringBuffer(10000000);
		connByStringBuilder(10000000);
	}
	
	public static void connByOperationOnce(int count){
		long endTime;
		long time;
		String str;
		String str2 = "test";
		long startTime = System.currentTimeMillis();

		for(int i = 0; i <= count; i++)
			str = str2 + str2 + str2 + str2 + str2;
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("使用加号一次连接字符串" + count + "次所需要的时间为:" + time + "ms" );
	}
	
	public static void connByOperation(int count){
		long endTime;
		long time;
		String str;
		String srt2 = "test";
		long startTime = System.currentTimeMillis();

		for(int i = 0; i <= count; i++){
			str = srt2;
			str += srt2;
			str += srt2;
			str += srt2;
			str += srt2;
		}
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("使用加号多次连接字符串" + count + "次所需要的时间为:" + time + "ms" );
	}

	public static void connByStringBuffer(int count){
		long endTime;
		long time;
		String str;
		String str2 = "test";
		long startTime = System.currentTimeMillis();
		
		for(int i = 0; i <= count; i++){
			StringBuffer sb = new StringBuffer(str2);
			sb.append(str2);
			sb.append(str2);
			sb.append(str2);
			sb.append(str2);
			str = sb.toString();
		}
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("使用StringBuffer连接字符串" + count + "次所需要的时间为:" + time + "ms" );
	}
	
	public static void connByStringBuilder(int count){
		long endTime;
		long time;
		String str;
		String str2 = "test";
		long startTime = System.currentTimeMillis();
		
		for(int i = 0; i <= count; i++){
			StringBuilder sb = new StringBuilder(str2);
			sb.append(str2);
			sb.append(str2);
			sb.append(str2);
			sb.append(str2);
			str = sb.toString();
		}
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("使用StringBuilder连接字符串" + count + "次所需要的时间为:" + time + "ms" );
	}
}

再进行测试得:

测试版本为1.6.0_65

使用加号一次连接字符串10000000次所需要的时间为:1366ms

使用加号多次连接字符串10000000次所需要的时间为:3433ms

使用StringBuffer连接字符串10000000次所需要的时间为:1449ms

使用StringBuilder连接字符串10000000次所需要的时间为:1139ms


测试版本为1.7.0_79

使用加号一次连接字符串10000000次所需要的时间为:1630ms

使用加号多次连接字符串10000000次所需要的时间为:3432ms

使用StringBuffer连接字符串10000000次所需要的时间为:1512ms

使用StringBuilder连接字符串10000000次所需要的时间为:1152ms


测试版本为1.8.0_40

使用加号一次连接字符串10000000次所需要的时间为:1233ms

使用加号多次连接字符串10000000次所需要的时间为:2780ms

使用StringBuffer连接字符串10000000次所需要的时间为:1175ms

使用StringBuilder连接字符串10000000次所需要的时间为:1085ms



结论:

当在线程不安全的环境下:

应该使用StringBuffer来确保线程安全。


在线程安全的环境下:

使用StringBuilder永远可以获取更高的性能, 但若在一条语句中连接,使用“+”号性能略低但可读性,可维护性更高。


待解决困惑: “+”是使用StringBuilder实现的,在一条语句中使用“+”号连接只创建了一个StringBulider,为什么性能和直接使用StringBulider差别颇大。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
针对.NET和MongoDB的性能测试,可以使用MongoDB官方提供的C#驱动程序来进行测试。具体步骤如下: 1. 安装MongoDB C#驱动程序 可以通过NuGet包管理器来安装MongoDB C#驱动程序,或者从MongoDB官网下载源代码并手动安装。 2. 编写测试代码 编写测试代码时,需要注意以下几点: - 尽量使用异步操作,以提高性能。 - 使用连接池来管理数据库连接。 - 使用索引来加速查询操作。 以下是一个简单的测试代码示例: ``` using MongoDB.Driver; using System; using System.Diagnostics; using System.Threading.Tasks; namespace MongoDBTest { class Program { static async Task Main(string[] args) { var client = new MongoClient("mongodb://localhost:27017"); var database = client.GetDatabase("test"); var collection = database.GetCollection<BsonDocument>("test"); // 插入数据 var stopwatch = Stopwatch.StartNew(); for (int i = 0; i < 10000; i++) { var document = new BsonDocument { { "name", "test" }, { "value", i } }; await collection.InsertOneAsync(document); } stopwatch.Stop(); Console.WriteLine($"Insert: {stopwatch.ElapsedMilliseconds}ms"); // 查询数据 stopwatch.Restart(); var filter = Builders<BsonDocument>.Filter.Eq("name", "test"); var result = await collection.FindAsync(filter); await result.ToListAsync(); stopwatch.Stop(); Console.WriteLine($"Query: {stopwatch.ElapsedMilliseconds}ms"); } } } ``` 3. 运行测试代码 运行测试代码时,可以使用性能测试工具来模拟多个并发用户对数据库进行操作,以更全面地测试性能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值