Redução da contenção de heap
Os gerentes de seqüência de caracteres padrão fornecidos pelo MFC e ATL são invólucros simples na parte superior de um global heap.Isso global heap é totalmente thread-safe, que significa que vários threads podem alocar e liberar memória dele simultaneamente sem corromper o heap.Para ajudar a fornecer a acesso thread-safe, o heap tem para serializar o acesso a mesmo.Geralmente isso é feito com um mecanismo de bloqueio semelhante ou uma seção crítica.Sempre que dois threads tentarem acessar o heap simultaneamente, um thread é bloqueado até que de solicitação do Outros thread seja concluída.Para muitos aplicativos, essa situação raramente ocorre e o impacto no desempenho do mecanismo de bloqueio da heap é insignificante.No entanto, para aplicativos com que freqüência acesso a pilha de vários threads contenção de bloquear da heap pode fazer com que o aplicativo seja executado mais lentamente do que se fosse um único encadeamento (mesmo em máquinas com várias CPUs).
Aplicativos que usam CStringT são especialmente suscetíveis a contenção de heap porque as operações em CStringT objetos freqüentemente requerem realocação do buffer de seqüência de caracteres.
Uma maneira de aliviar a contenção de heap entre threads é que cada thread alocar seqüências de caracteres de um heap particular e o local de segmento.Desde que sistema autônomo seqüências de caracteres alocado com alocador de um segmento específico são usados apenas nesse segmento, o alocador não precisa ser thread-safe.
Exemplo
O exemplo abaixo ilustra um procedimento de thread aloca seu próprio heap thread safe particular a ser usado para as seqüências de caracteres desse segmento:
DWORD WINAPI WorkerThreadProc(void* pBase)
{
// Declare a non-thread-safe heap just for this thread:
CWin32Heap stringHeap(HEAP_NO_SERIALIZE, 0, 0);
// Declare a string manager that uses the thread's heap:
CAtlStringMgr stringMgr(&stringHeap);
int nBase = *((int*)pBase);
int n = 1;
for(int nPower = 0; nPower < 10; nPower++)
{
// Use the thread's string manager, instead of the default:
CString strPower(&stringMgr);
strPower.Format(_T("%d"), n);
_tprintf_s(_T("%s\n"), strPower);
n *= nBase;
}
return(0);
}
Comentários
Vários segmentos podem estar em execução usando este procedimento thread mesmo, mas uma vez que cada segmento possui sua própria heap não há nenhuma contenção entre segmentos.Além disso, o fato de que cada heap é thread-safe proporciona um aumento mensurável no desempenho, mesmo se apenas uma cópia do segmento está em execução.Esse é o resultado da pilha não usando operações interligadas caras para proteger contra o acesso simultâneo.
Para obter um procedimento de thread mais complicado, talvez seja conveniente armazenam um ponteiro para o gerente de seqüência de caracteres do segmento em um slot de armazenamento local (TLS) do segmento.Isso permite que outras funções chamadas pelo procedimento para acessar o Gerenciador de seqüência de caracteres do segmento do thread.