using UnityEngine;
|
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; // 新增大容量级别
|
|
|
/// <summary>
|
/// 智能容量估算(优化版)
|
/// </summary>
|
private static int EstimateCapacity(params string[] objects)
|
{
|
if (objects == null || objects.Length == 0)
|
return TINY_CAPACITY;
|
|
int totalLength = 0;
|
|
// 单次遍历计算总长度,提高性能
|
foreach (string str in objects)
|
{
|
if (str != null)
|
totalLength += str.Length;
|
}
|
|
// 更精细的容量策略,减少内存浪费
|
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>
|
/// 从对象池获取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);
|
}
|
|
// 中等数量字符串使用简单容量策略
|
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();
|
}
|
finally
|
{
|
ReturnToPool(sb);
|
}
|
}
|
|
|
public static string FormatSpeed(float speed)
|
{
|
if (speed > 1048576f)
|
{
|
return Concat((speed / 1048576f).ToString("f1"), " M/S");
|
}
|
else if (speed > 1024f)
|
{
|
return Concat((speed / 1024f).ToString("f1"), " KB/S");
|
}
|
else
|
{
|
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));
|
}
|
}
|
|
|
|
}
|