三国卡牌客户端基础资源仓库
hch
8 天以前 fcce9ab0e54e4580569ba4ed5be0f4e3ba4d37fa
Assets/Launch/Utility/StringUtility.cs
@@ -2,88 +2,201 @@
using System.Collections;
using System.Text;
using System;
using System.Collections.Concurrent;
// AI提醒实际在现代编辑器中,低于4个字符串的+ 操作符的性能和 string.Concat 几乎相同,会被智能优化为 string.Concat
public class StringUtility
{
    public static readonly string[] splitSeparator = new string[] { "|" };
    // 对象池方案:线程安全的StringBuilder池
    private static readonly ConcurrentQueue<StringBuilder> _stringBuilderPool = new ConcurrentQueue<StringBuilder>();
    private const int MAX_POOL_SIZE = 32;  // 增加池大小以适应高并发
    private const int DEFAULT_CAPACITY = 64;
    private const int SMALL_CAPACITY = 64;   // 适用于小规模拼接
    private const int TINY_CAPACITY = 32;    // 适用于极小规模拼接
    private const int MEDIUM_CAPACITY = 128; // 新增中等容量级别
    private const int LARGE_CAPACITY = 256;  // 新增大容量级别
    // 新增:为循环调用的优化版本(复用StringBuilder)
    [ThreadStatic]
    private static StringBuilder _threadLocalStringBuilder;
    
    /// <summary>
    /// 获取当前线程的StringBuilder
    /// 智能容量估算(优化版)
    /// </summary>
    private static StringBuilder GetThreadLocalStringBuilder()
    private static int EstimateCapacity(params string[] objects)
    {
        if (_threadLocalStringBuilder == null)
        if (objects == null || objects.Length == 0)
            return TINY_CAPACITY;
        int totalLength = 0;
        // 单次遍历计算总长度,提高性能
        foreach (string str in objects)
        {
            _threadLocalStringBuilder = new StringBuilder();
            if (str != null)
                totalLength += str.Length;
        }
        return _threadLocalStringBuilder;
        // 更精细的容量策略,减少内存浪费
        if (totalLength <= TINY_CAPACITY)
            return TINY_CAPACITY;
        else if (totalLength <= SMALL_CAPACITY)
            return SMALL_CAPACITY;
        else if (totalLength <= MEDIUM_CAPACITY)
            return MEDIUM_CAPACITY;
        else if (totalLength <= LARGE_CAPACITY)
            return LARGE_CAPACITY;
        else
            // 对于超大字符串,预留25%的缓冲空间(减少内存浪费)
            return totalLength + (totalLength >> 2);
    }
    /// <summary>
    /// 智能字符串拼接方法,自动选择最优策略
    /// - 2-4个字符串:直接使用 string.Concat() (最高性能)
    /// - 5个以上字符串:使用线程本地 StringBuilder 复用 (循环优化)
    /// 从对象池获取StringBuilder
    /// </summary>
    private static StringBuilder GetPooledStringBuilder(int capacity = DEFAULT_CAPACITY)
    {
        if (_stringBuilderPool.TryDequeue(out StringBuilder sb))
        {
            sb.Clear();
            // 如果容量不足,重新创建
            if (sb.Capacity < capacity)
            {
                sb = new StringBuilder(capacity);
            }
            return sb;
        }
        return new StringBuilder(capacity);
    }
    /// <summary>
    /// 将StringBuilder归还到对象池(优化版)
    /// </summary>
    private static void ReturnToPool(StringBuilder sb)
    {
        if (sb == null)
            return;
        // 容量过大或过长,不回收以避免内存问题
        if (sb.Capacity > 2048 || sb.Length > 1024)
        {
            SecureClear(sb);
            return;
        }
        // 池未满时才回收
        if (_stringBuilderPool.Count < MAX_POOL_SIZE)
        {
            sb.Clear();
            _stringBuilderPool.Enqueue(sb);
        }
        else
        {
            // 池满时进行安全清理
            SecureClear(sb);
        }
    }
    /// <summary>
    /// 安全清理StringBuilder内容(防止敏感数据泄露)
    /// </summary>
    private static void SecureClear(StringBuilder sb)
    {
        if (sb == null || sb.Length == 0)
            return;
        // 基础清理
        sb.Clear();
        // 安全清理:用空字符覆盖缓冲区
        // #if UNITY_EDITOR || DEVELOPMENT_BUILD
        // // 仅在开发版本中执行更彻底的清理,避免影响性能
        // int originalCapacity = sb.Capacity;
        // if (originalCapacity <= 1024) // 仅对小容量StringBuilder进行安全清理
        // {
        //     sb.Capacity = originalCapacity;
        //     for (int i = 0; i < originalCapacity; i++)
        //     {
        //         sb.Append('\0');
        //     }
        //     sb.Clear();
        // }
        // #endif
    }
    /// <summary>
    /// 智能字符串拼接方法(优化版),自动选择最优策略
    /// - 1-4个字符串:直接使用 string.Concat() (最高性能)
    /// - 4-8个字符串:使用对象池 StringBuilder,容量预分配
    /// - 9个以上字符串:使用对象池 StringBuilder + 容量估算
    /// </summary>
    public static string Concat(params string[] _objects)
    {
        if (_objects == null || _objects.Length == 0)
            return string.Empty;
        // 少量字符串直接使用Concat,性能最佳
        if (_objects.Length <= 4)
        {
            return string.Concat(_objects);
        }
        // 大量字符串使用线程本地StringBuilder,避免重复创建
        var sb = GetThreadLocalStringBuilder();
        sb.Clear();
        // 中等数量字符串使用简单容量策略
        int estimatedCapacity;
        if (_objects.Length <= 8)
        {
            estimatedCapacity = DEFAULT_CAPACITY;
        }
        else
        {
            // 大量字符串才进行容量估算(优化性能)
            estimatedCapacity = EstimateCapacity(_objects);
        }
        var sb = GetPooledStringBuilder(estimatedCapacity);
        try
        {
        foreach (string str in _objects)
        {
            sb.Append(str);
        }
        return sb.ToString();
    }
    // AI提醒实际在现代编辑器中,低于4个字符串的+ 操作符的性能和 string.Concat 几乎相同,会被智能优化为 string.Concat
    // 添加常用2个字符串拼接的优化版本
    public static string Contact(string str1, string str2)
        finally
    {
        return string.Concat(str1, str2);
            ReturnToPool(sb);
    }
    // 添加常用3个字符串拼接的优化版本
    public static string Contact(string str1, string str2, string str3)
    {
        return string.Concat(str1, str2, str3);
    }
    // 添加常用4个字符串拼接的优化版本
    public static string Contact(string str1, string str2, string str3, string str4)
    {
        return string.Concat(str1, str2, str3, str4);
    }
    public static string FormatSpeed(float speed)
    {
        if (speed > 1048576f)
        {
            return Contact((speed / 1048576f).ToString("f1"), " M/S");
            return Concat((speed / 1048576f).ToString("f1"), " M/S");
        }
        else if (speed > 1024f)
        {
            return Contact((speed / 1024f).ToString("f1"), " KB/S");
            return Concat((speed / 1024f).ToString("f1"), " KB/S");
        }
        else
        {
            return Contact(speed.ToString("f1"), " B/S");
            return Concat(speed.ToString("f1"), " B/S");
        }
    }
    /// <summary>
    /// 预热对象池(在应用启动时调用)
    /// </summary>
    public static void WarmupPool(int count = 4)
    {
        // 预热不同容量的StringBuilder以适应不同场景
        for (int i = 0; i < count && _stringBuilderPool.Count < MAX_POOL_SIZE; i++)
        {
            _stringBuilderPool.Enqueue(new StringBuilder(DEFAULT_CAPACITY));
        }
    }
}