小心StringBuilder.toString

本文探讨了在使用StringBuilder进行字符串拼接时出现性能瓶颈的原因,并提供了一种更高效的替代方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">最近看服务器运行的时候,发现CPU使用load特别高,排查了一下,问题出现在下面的代码里面</span>
 StringBuilder buf = new StringBuilder();
 String line = null;
 while ((line = br.readLine()) != null) {
	if (StringUtils.isNotEmpty(buf.toString())) {
		buf.append("\r\n");
	}
	buf.append(line);
}

dump服务器stack的时候,发现代码经常停留在if (StringUtils.isNotEmpty(buf.toString())) 这一行

这是为什么呢?

StringUtils.isNotEmpty是公共方法,应该没什么大问题。

问题就处在buf.toString()上面

public String toString() {
        // Create a copy, don't share the array
    return new String(value, 0, count);
    }
每次toString的时候会新建一个String对象

在看看String的构造方法

 public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.offset = 0;
        this.count = count;
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }
最后一句 Arrays.copyOfRange(value, offset, offset+count);
会不停的拷贝内存,所以内存不高才怪。
其实代码可以不用这么判断,直接判断

StringBuilder buf = new StringBuilder();
 String line = null;
 while ((line = br.readLine()) != null) {
	if (buf.length()>0) {
		buf.append("\r\n");
	}
	buf.append(line);
}
细节决定成败!理解底层实现原理对于编写高质量代码有很重要的作用!


public static string model2Json(model.Dtry AObj) { StringBuilder jsonBuilder = new StringBuilder(); jsonBuilder.Append("{"); jsonBuilder.Append("\"Id\":" + dbutility.json.Enquote(AObj.Id.ToString()) + ","); jsonBuilder.Append("\"typeid\":" + dbutility.json.Enquote(AObj.typeid.ToString()) + ","); jsonBuilder.Append("\"typename\":" + dbutility.json.Enquote(AObj.typename.ToString()) + ","); jsonBuilder.Append("\"usernum\":" + dbutility.json.Enquote(AObj.usernum.ToString()) + ","); jsonBuilder.Append("\"user_nickname\":" + dbutility.json.Enquote(AObj.user_nickname) + ","); jsonBuilder.Append("\"CreateMan\":" + dbutility.json.Enquote(AObj.CreateMan) + ","); jsonBuilder.Append("\"Creator\":" + dbutility.json.Enquote(AObj.Creator.ToString()) + ","); jsonBuilder.Append("}"); return jsonBuilder.ToString(); } public static string model2Json(model.Dtry AObj) { StringBuilder jsonBuilder = new StringBuilder(); jsonBuilder.Append("{"); jsonBuilder.Append("\"Id\":" + dbutility.json.Enquote(AObj.Id.ToString()) + ","); jsonBuilder.Append("\"typeid\":" + dbutility.json.Enquote(AObj.typeid.ToString()) + ","); jsonBuilder.Append("\"typename\":" + dbutility.json.Enquote(AObj.typename.ToString()) + ","); jsonBuilder.Append("\"usernum\":" + dbutility.json.Enquote(AObj.usernum.ToString()) + ","); jsonBuilder.Append("\"user_nickname\":" + dbutility.json.Enquote(AObj.user_nickname) + ","); jsonBuilder.Append("\"CreateMan\":" + dbutility.json.Enquote(AObj.CreateMan) + ","); jsonBuilder.Append("\"Creator\":" + dbutility.json.Enquote(AObj.Creator.ToString()) + ","); jsonBuilder.Append("}"); return jsonBuilder.ToString(); } 详细分析并优化
03-15
如下C#是将excel表内容导入Oracle数据库,怎么优化性能缩短写入耗时和不占用资源和锁表 public object[] importempsecurity_check_Excel(object[] param) { string msg = ""; int rev = 0; string loginUser = GetClientInfo(ClientInfoType.LoginUser).ToString(); string loginDB = "RPTDB"; string rtnMsgSplit = "@"; int importRowNum = 0; string v_sql = ""; string v_user = GetClientInfo(ClientInfoType.LoginUser).ToString(); IDbConnection conn = AllocateConnection(loginDB); IDbTransaction trans; if (conn.State != ConnectionState.Open) { conn.Open(); } trans = conn.BeginTransaction(); try { //Deserialize excel data row objet transfer into list type from client call serverMethod. var data = JsonConvert.DeserializeObject<List<EMP_SECURITYData>>(param[0].ToString()); #region Insert all excel data row into RPTAP.ITDAILY_REPORT(Global temporay table) StringBuilder sql = new StringBuilder(); foreach (var item in data) { v_sql = string.Format($@" INSERT INTO RPTAP.SECRECY_CHECK (MACH_NAME,DEPT_NA,EMP_NO,EMP_NA,EMP_POSIT,NDA_Y,CLASS_Y,CLASS_DATE,PARK,DEPOSIT_NO,UPDATE_NO,UPDATE_TIME) VALUES ('{item.MACH_NAME}', '{item.DEPT_NA}', '{item.EMP_NO}', '{item.EMP_NA}', '{item.EMP_POSIT}', '{item.NDA_Y}', '{item.CLASS_Y}' , TO_DATE('{item.CLASS_DATE}', 'YYYY/MM/DD'), '{item.PARK}', '{item.DEPOSIT_NO}', '{v_user}', SYSDATE )"); importRowNum += ExecuteCommand(v_sql.ToString(), conn, trans); } //sql.Append("SELECT * FROM DUAL"); //var importRowNum = ExecuteCommand(sql.ToString(), conn, trans); msg += importRowNum > 0 ? importRowNum : 0; msg += rtnMsgSplit + "InsertSuccess"; trans.Commit(); trans.Dispose(); #endregion } catch (Exception ex) { msg += ex.ToString(); rev = 1; trans.Rollback(); trans.Dispose(); conn.Close(); this.ReleaseConnection(loginDB, conn); } finally { conn.Close(); this.ReleaseConnection(loginDB, conn); } object[] ret = new object[] { rev, msg }; return ret; }
06-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值