Mostrando postagens com marcador api do windows. Mostrar todas as postagens
Mostrando postagens com marcador api do windows. Mostrar todas as postagens

quinta-feira, 17 de dezembro de 2009

Thread e a Máscara de Afinidade

Que perrengue!

Estou tentando melhorar um processo que consome muita CPU. E por estar em um ambiente multi processado optei por direcionar a thread gulosa via SetThreadAffinityMask.

A principio o Windows se encarrega de direcionar o uso do processador para aquel que estiver mais ocioso naquele momento.

Em um servidor com 8 processadores, funciona assim:


00000001 = 1 = Processador nº1 (Concentra no 1º processador)
00000010 = 2 = Processador nº2 (Concentra no 2º processador)
00000011 = 3 = Processador nº1 e nº2 (Balanceia entre o 1º e o 2º)
00000100 = 4 = Processador nº3 (Concentra no 3º processador)
00000101 = 5 = Processador nº1 e nº3 (Balanceia entre o 1º e o 3º)
...
11111111 = 255 = Balanceia entre os 8 processadores


Ou seja, cada bit ligado representa o processador que será usado. Mas usa-se a representação decimal no momento de passar para a função.

Já a função SetProcessAffinityMask define a máscara de afinidade do processo, sendo que as threads herdam esta mascara.

Existe também a função SetThreadIdealProcessor, que indica ao Windows qual o processador preferido para aquela thread, e o Windows irá dar "preferência" a esta thread.

Uma função interessante foi a SetPriorityClass, que permite baixar ou aumentar a prioridade de um processo. O correlato para a thread é a SetThreadPriority.


Função que retorna o processador que está sendo usado no momento:
(Só funciona do Vista para frente e Server 2003 para frente)

interface

function GetCurrentProcessorNumber: DWORD; stdcall;

implementation

function GetCurrentProcessorNumber; external kernel32 name 'GetCurrentProcessorNumber';



http://msdn.microsoft.com/en-us/library/ms683181(VS.85).aspx

quarta-feira, 18 de novembro de 2009

Arquivo mapeado e Serviço do Windows

Enfim! Valeu a pena não ter desistido! :)

Vamos lá:

Problema:

Criar um arquivo mapeado entre um Serviço do Windows em uma aplicação GUI. O objetivo é acompanhar em tempo real o tamanho de uma pilha de objetos.

Solução:

Para criar um arquivo mapeado:

procedure TGatewayCTI.CriarArquivoCompartilhado;
var
cErro : Cardinal;
begin
Self.FMappingFile := CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,100,PChar('Session\FILA_GATEWAY'));
if (Self.FMappingFile <> 0) then
begin
cErro := GetLastError;
if (cErro = ERROR_ALREADY_EXISTS) then
begin
CloseHandle(Self.FMappingFile);
Self.FMappingFile := OpenFileMapping(FILE_MAP_ALL_ACCESS,False,PChar('Session\FILA_GATEWAY'));
GerarLogTipoInformation(True,84734903,[' > Sucesso ao abrir arquivo mapeado!'])
end else
begin
GerarLogTipoInformation(True,894733,[' > Sucesso ao criar arquivo mapeado!']);
end;
end else
begin
GerarLogTipoErro(True,49874309,[Format(' > Erro ao criar arquivo mapeado: [%d - %s]',[cErro,SysErrorMessage(cErro)])]);
end;
end;


Para gravar um valor:

procedure TGatewayCTI.AtualizarQuantidade(piIncremento: Integer);
var
Ptr: PChar;
begin
try
if (Self.FMappingFile <> 0) then
begin
Self.FCountQueue := Self.FCountQueue + piIncremento;
if (piIncremento < 0) then
begin
Self.FCountProcessed := Self.FCountProcessed + Abs(piIncremento); 
end;

Ptr := MapViewOfFile(Self.FMappingFile,FILE_MAP_WRITE,0,0,0);
StrPLCopy(Ptr,Format('Na pilha: [%d] - Processadas: [%d]',[Self.FCountQueue,Self.FCountProcessed]),100);
UnmapViewOfFile(Ptr);
end;
except
on E: Exception do
GerarLogTipoException(58679343,E,'Arquivo mapeado');
end;
end;
Para ler o valor:
procedure TfPrincipal.AtualizarValor;
var
Ptr : PChar;
begin
if (Self.FMappingFile <> 0) then
begin
Ptr := MapViewOfFile(Self.FMappingFile,FILE_MAP_READ,0,0,0);
Self.pCount.Caption := Format('%s',[Ptr]);
UnmapViewOfFile(Ptr);
Application.ProcessMessages;
end else
begin
Self.pCount.Caption := 'Arquivo mapeado não disponivel';
end;
end;
Importantíssimo:
Para compartilhar o arquivo entre um serviço e um aplicativo GUI, coloque a palavra 'Session\' antes do nome do arquivo.

quarta-feira, 21 de outubro de 2009

Obter número de Threads de um processo

Olá. Graças à generosidade do Luís Gustavo Fabbro, que mantém um blog muito interessante, a Balaio Tecnológico, posto aqui o código necessário para obter a quantidade de thread de um processo, pelo PID dele:

uses TlHelp32;

{*
Levanta a quantidade de Threads de um processo

@param piPID Identificador do processo em questão
}
function TGInfoWinService.GetThreadCount(piPID: Cardinal): Boolean;
var
hSnapShot   : THandle;
rThreadInfo : TThreadEntry32;
bNext       : Boolean;
iThreadCount: Integer;
begin
Result := False;
iThreadCount := 0;
try
try
hSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
if (hSnapShot = THandle(-1)) then
raise EGWinService.Create('Erro ao levantar ThreadCount',39248209);
rThreadInfo.dwSize := SizeOf(rThreadInfo);
bNext := Thread32First(hSnapShot,rThreadInfo);
while (bNext) do
begin
if (rThreadInfo.th32OwnerProcessID = piPID) then
Inc(iThreadCount);
bNext := Thread32Next(hSnapShot,rThreadInfo);
end;
Result := True;
except
on E: Exception do
GerarLogTipoException(56565654,E,'Unt_WinService');
end;
finally
CloseHandle(hSnapShot);
if Result then
Self.FThreadCount := iThreadCount
else
Self.FThreadCount := -1;
end;
end;


Mais informações em:

http://balaiotecnologico.blogspot.com/2009/10/obtendo-informacoes-sobre-as-threads-de.html

Minha lista de blogs