using System.Collections.Concurrent; using UnityEngine; namespace UVC.Data.Core { /// /// DataArray 객체의 재사용을 위한 풀링 클래스입니다. /// public static class DataArrayPool { private static readonly ConcurrentQueue _pool = new ConcurrentQueue(); private static int _maxPoolSize = 100; // DataArray는 DataObject보다 수가 적을 것이므로 기본값 조정 // --- 통계용 필드 --- private static int _inUseCount = 0; private static int _peakUsage = 0; private static int _poolMisses = 0; private static readonly object _statsLock = new object(); static DataArrayPool() { // maxPoolSize만큼의 DataObject 인스턴스를 미리 생성하여 풀에 추가합니다. for (int i = 0; i < _maxPoolSize; i++) { _pool.Enqueue(new DataArray() { IsInPool = true, CreatedFromPool = true }); } } /// /// 풀에서 DataArray 객체를 가져옵니다. 풀이 비어있으면 새로 생성합니다. /// /// 재사용 가능한 DataArray 객체 public static DataArray Get() { bool fromPool = _pool.TryDequeue(out var array); lock (_statsLock) { _inUseCount++; if (_inUseCount > _peakUsage) { _peakUsage = _inUseCount; } if (!fromPool) { _poolMisses++; if (_inUseCount > _maxPoolSize) { int oldSize = _maxPoolSize; _maxPoolSize += 100; // 증가량 조정 //Debug.Log($"DataArrayPool size automatically increased from {oldSize} to {_maxPoolSize}. Peak usage: {_peakUsage}"); } } } //if(_peakUsage % 10 == 0) Debug.Log($"DataArrayPool stats: {GetStats()}"); if (fromPool) { array.IsInPool = false; } return fromPool ? array : new DataArray() { CreatedFromPool = true }; } /// /// 사용이 끝난 DataArray 객체를 풀에 반환합니다. /// /// 반환할 DataArray 객체 public static void Return(DataArray array) { if (array == null || array.IsInPool) return; bool shouldReturnToPool; lock (_statsLock) { _inUseCount--; shouldReturnToPool = _pool.Count < _maxPoolSize; } if (shouldReturnToPool) { array.Reset(); array.IsInPool = true; _pool.Enqueue(array); } } /// /// 풀의 현재 성능 통계를 문자열로 반환합니다. /// /// 풀 통계 (최대 사용량, 현재 사용량, 풀 비어있을 때 생성 횟수, 현재 풀 크기) public static string GetStats() { lock (_statsLock) { return $"최대 사용량: {_peakUsage}, 현재 사용량: {_inUseCount}, 풀 비어있을 때 생성 횟수: {_poolMisses}, 현재 풀 크기: {_pool.Count}, Max Size: {_maxPoolSize}"; } } /// /// 풀 통계를 초기화합니다. /// public static void ResetStats() { lock (_statsLock) { _peakUsage = 0; _poolMisses = 0; } } } }