#define arr_alloca( st, sz ) (st*)_alloca( sizeof( st ) * (sz) );
#define INLINE __forceinline
#define var
template< class T >
INLINE void ListToArray( T** dst, const T* src )
{
for( T* now = (T*)src; now; now = now->next )
*(dst++) = now;
}
template< class T >
INLINE auto ListToArray( T** dst, const T* src, const UNIT32 size )
{
auto now = (T*)src;
for( UNIT32 i = 0; i < size; ++i )
{
dst[ i ] = now;
now = now->next;
}
return now;
}
INLINE auto GetHeader( const CMemoryPool* pool, const TMemoryObject* obj )
{
return pool->mFN_Query_UsingHeader_per_Unit() ?
CMemoryPool_Manager::sFN_Get_DataBlockHeader_NormalObjectSize( obj ) :
CMemoryPool_Manager::sFN_Get_DataBlockHeader_SmallObjectSize( obj );
}
void TMemoryPool_TLS_CACHE::TUNITS::UnFill( CMemoryPool* pPool, UINT32 nUnits )
{
_Assert( pPool && nUnits <= m_cntUnits );
auto unfill_units = arr_alloca( TMemoryObject*, nUnits );
auto unfill_groups = arr_alloca( TMemoryUnitGroup*, nUnits );
m_cntUnits -= nUnits;
m_pUnit = ListToArray( unfill_units, m_pUnit, nUnits );
std::sort( unfill_units, unfill_units + nUnits );
for( UINT32 i = 0; i < nUnits; )
{
const auto header = GetHeader( pPool, unfill_units[ i ] );
#if _DEF_USING_MEMORYPOOL_DEBUG
if( !header || !header->mFN_Query_AlignedPTR( unfill_units[ i ] ) )
{
gFN_Error_Report__Damaged_MemoryPoolTLS( unfill_units[ i ] );
unfill_groups[ i ] = nullptr;
i++;
continue;
}
#endif
auto group = header->mFN_Get_UnitsGroup( // nullptr 리턴하는 경우가 있음?
header->mFN_Calculate_UnitsGroupIndex( unfill_units[ i ] ) );
unfill_groups[ i ] = group;
// 앞을 비교
for( ++i; i < nUnits && group->mFN_Test_Ownership( unfill_units[ i ] ); ++i ) // 뒤를 비교
{
#if _DEF_USING_MEMORYPOOL_DEBUG
if( !header->mFN_Query_AlignedPTR( unfill_units[ i ] ) )
{
gFN_Error_Report__Damaged_MemoryPoolTLS( unfill_units[ i ] );
unfill_groups[ i ] = nullptr;
continue;
}
#endif
unfill_groups[ i ] = group;
}
}
// make lists
for( UINT32 i = 0; i < nUnits; )
{
// debug 전용 조건이 아닌지?
if( !unfill_groups[ i ] )
{
++i;
continue;
}
_Assert( unfill_units[ i ] );
const auto groups = unfill_groups[ i ];
const auto first = unfill_units[ i ];
var auto last = unfill_units[ i ];
UINT32 count = 1;
for( ++i; i < nUnits && groups == unfill_groups[ i ]; ++i )
{
last->next = unfill_units[ i ];
last = unfill_units[ i ];
count++;
}
last->next = nullptr;
pPool->mFN_GiveBack_Units( const_cast< TMemoryUnitGroup* >( groups ), first, last, count );
}
}
__forceinline 을 매크로로 한 번 싼 이유는 다른 컴파일러에선 이름이 다를테니까...
위에 ListToArray 함수들은 걍 뻘짓이니 일단 대충 무시.
첫번째 아이디어는 소트에 관한건데,
퀵소트 계열은 정렬 / 반정렬 상태에서 성능이 완전히 엇갈리기 때문에, 만약 주소가 정순이나 역순들의 집합으로 특정될 경우,
merge sort 류를 쓰는게 나을것 같습니다.
테스트하는 경우가 n개 자원 얻고/반납할때 벡터에 담아서 인덱스 순서대로 해서 그래여
그런데 실사용에서는 예측할수 없게 섞일듯
정렬이 시작되는 포인터들을 배열에 잘라넣어서 그 포인터에서 시작되는 정렬된 항목들을 병합해가는 식으로 하면 될듯.
아마, 막 섞이진 않을듯 해유.
음, vc 2008 쯤인가쯤 부터 그전에는 퀵소트 였는데 분할, 합병 정렬로 바뀌었더라구여
두 번째는
auto group = header->mFN_Get_UnitsGroup( header->mFN_Calculate_UnitsGroupIndex( unfill_units[ i ] ) );
std::sort 는 안에 구현된 소트 종류가 좀 많을듯.
두번째는 이게 nullptr 를 가지는 경우가 있나요?
비교해보구여~
const 몇개를 소거했으니 양해바랍니다~
아뇨 없어여~
음 그러니까 mFN_Get_UnitsGroup 이란 함수가 nullptr 를 리턴하는 경우도 있다구요?
없죠?
그러면,
이건 내부 인터페이스라 사용자가 사용할일없어서 그런건 사용자인터페이스에서만 체크했어요
젤 아래 for 문의 if( !unfill_groups[ i ] ) { ++i; continue; }
이건 디버그 모드 전용 조건이 될듯 해요.
릴리즈에선 돌 필요가 없지 않을까
세 번째는
// 앞을 비교 for( ++i; i < nUnits && group->mFN_Test_Ownership( unfill_units[ i ] ); ++i ) // 뒤를 비교
unfill_nits[ i ] 가 정렬되어 들어온다고 가정할때,
매번 begin ~ end 범위 내인지 체크하는건 낭비입니다.
조건이 2개 잖아요?
저 for 문 들어가기 전에 begin 보다 작으면 continue 걸어버리면 될듯.
그리고 for 문 안에선 end 보다 작냐만 비교
잘 생각해보면 nUnits 와의 비교를 없앨 방법이 없진 않을 것 같아요.
unfill_units[ 마지막 한칸 뒤 ] 녀석에다 모든 그룹 주소를 넘을 주소를 넣어두면 되니까요.
주소 최대값 같은거.
그러면 저 for 문은 조건 하나 짜리로 바뀌죠.
음
ㅇㅋ 다 이해했어요~
마찬가지로 unfill_groups[ 마지막 한칸 뒤 ] 에도 아무랑도 안겹칠 주소를 하나 넣어두면
마지막 for 문도 조건이 하나로 줄어듭니다.
nUnits 비교가 필요없죠.
for( ++i; i < nUnits && groups == unfill_groups[ i ]; ++i )
여기.
이 코드들은 O( N ) 알고리즘이라, 조건비교를 줄이는거 말곤 더이상 줄일 여지가 없음요.
그러면 제 아이디어는 다 설명 드렸고,
캬~
적절한 소트를 만드는것 까지 끝내면 현재 코드보다 30% 정도 빨라질것 같습니다.
뭐 운좋으면 한 2배 빨라지구유.
snake 를 사랑합시다. ㅋㅋㅋ
전 낙타랑 뱀이랑 햇갈립니다
늦은 시간인데 감사합니다!
별말씀을~
반복문은 고쳐야겠군여
소유권 테스트 부분이 듣고 보니 맞는데 고치는게 좀 고민되네여 되도록 간결하게 유지하면서 하려면
ㅇㅇ alloca 한개 더 크게 잡고 units 와 groups 마지막에 최대주소값 넣어두면 카운터 비교들은 소거~
캬 대단한거 같음
begin, end 주소리턴해주는 메서드만 만들면 되지 않남유
코드에 그냥 함수만하나만 보였을 뿐인데 거기서 잡아내다니
히힣. 올챙이님의 생각을 머리에 로딩했쥬.
흐바랑 노느라 시간이 좀 끌렸지만 ㅋㅋ
코드 잘 보겠습니다
님 코드 거의 고대로임요~
대소문자 막 섞인 약자들만 편안한 단어로 바꿈 ㅋㅋ