【瑞模网】Unity String 字符串的优化

Hello 小伙伴们大家好,今天和大家分享一下“字符串的优化”。

首先,通过跟踪 System.String 类,我们看到 string.Format 在最终的实现过程中是重新new了一个 StringBuilder。因此我们可以使用在对字符串进行 Format 操作的时候直接共用一个StringBuilder即可,具体实现如下:

private static StringBuilder stringBuilder = new StringBuilder();

public static string Format(string str, params object[] args)
{
    stringBuilder.Remove(0, stringBuilder.Length);
    stringBuilder.AppendFormat(str, args);
    return stringBuilder.ToString();
} 

StringBuilder.Format 的消耗其实也是挺大的,最终调用的是 AppendFormatHelper 这个函数,里面实现也是极其复杂,因此能尽量不用 Format 的时候尽量不用 Format。可以考虑使用 Concat 函数来代替。

string.Concat 每次使用都会重新生成一个 string,然后对其进行数据填充。当我们需要 Concat 的数据比较多的时候,里面每次都会判断填充的数据是否为null,循环体里都会有个objct转string的操作,其实大可不必如此。既然我们之前已经有一个通用的StringBuilder了,可以直接公用即可,每次使用之前清除掉旧数据,实现循环使用。如下图所示:

public static string Concat(string str1, string str2)
{
    stringBuilder.Remove(0, stringBuilder.Length);
    stringBuilder.Append(str1);
    stringBuilder.Append(str2);
    return stringBuilder.ToString();
} 

如果有多个参数 str1、str2、str3等等的...就写多个 Concat 函数,如果在外部调用的时候遇到循环体可以在这边定义一个外部共享的 StringBuilder,具体如下:

private static StringBuilder shareStringBuilder = new StringBuilder();

public static StringBuilder GetShareStringBuilder()
{
    shareStringBuilder.Remove(0, stringBuilder.Length);
    return shareStringBuilder;
}

可能你看到这里,脑袋完全懵的,不知道我在做些什么。现在我直接上操作步骤:

首先新建两个脚本,分别为 GString、GStringSample,如下图所示:

GString 存放我们的字符串优化类,完整代码如下:

using System.Text;

namespace GameStartStudio
{
    // 字符串优化类
    public static class GString
    {
        private static readonly StringBuilder StrBuilder = new();
        private static readonly StringBuilder ShareStrBuilder = new();

        public static StringBuilder GetShareStringBuilder()
        {
            ShareStrBuilder.Remove(0, StrBuilder.Length);
            return ShareStrBuilder;
        }

        public static string Format(string str, params object[] args)
        {
            StrBuilder.Remove(0, StrBuilder.Length);
            StrBuilder.AppendFormat(str, args);
            return StrBuilder.ToString();
        }

        public static string Concat(string str1, string str2)
        {
            StrBuilder.Remove(0, StrBuilder.Length);
            StrBuilder.Append(str1);
            StrBuilder.Append(str2);
            return StrBuilder.ToString();
        }

        public static string Concat(string str1, string str2, string str3)
        {
            StrBuilder.Remove(0, StrBuilder.Length);
            StrBuilder.Append(str1);
            StrBuilder.Append(str2);
            StrBuilder.Append(str3);
            return StrBuilder.ToString();
        }
    }
}

GStringSample 存放测试代码,别忘了将代码挂载起来。

using UnityEngine;
using System.Text;
using UnityEngine.Profiling;

namespace GameStartStudio
{
    public class GStringSample : MonoBehaviour
    {
        private void Update()
        {
            // 优化前
            BeforeOptimize();

            // 优化后
            AfterOptimize();
        }

        string s1 = string.Empty;

        private void BeforeOptimize()
        {
            Profiler.BeginSample("Before Optimize");
            s1 = string.Empty;
            for (int i = 0; i < 1000; i++)
            {
                s1 += i;
            }

            Profiler.EndSample();
        }

        private readonly StringBuilder _stringBuilder = GString.GetShareStringBuilder();

        private void AfterOptimize()
        {
            Profiler.BeginSample("After Optimize");
            _stringBuilder.Remove(0, _stringBuilder.Length);
            for (int i = 0; i < 1000; i++)
            {
                _stringBuilder.Append(i);
            }

            Profiler.EndSample();
        }
    }
}

最后通过观察 Profiler Tab 来查看性能分析:

优化前GC是2.7MB

优化后GC只有27.1KB 

猜你喜欢

转载自blog.csdn.net/rrmod/article/details/130752134
今日推荐