Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.08.20;
Скачать: CL | DM;

Вниз

Порядок объявления переменных.   Найти похожие ветки 

 
learner ©   (2006-07-27 15:21) [0]

Параметром в процедуру передовала указатель на следующую структуру:
SYSTEM_PROCESSES_ADD = packed record
   NextEntryDelta : ULONG;
   ThreadCount : ULONG;
   CreateTime : LARGE_INTEGER;
   UserTime : LARGE_INTEGER;
   KernelTime : LARGE_INTEGER;
   ProcessName : string;
   FullPath : string;
   UserName : string;
   BasePriority : KPRIORITY;
   ProcessId : ULONG;
   InheritedFromProcessId : ULONG;
   HandleCount : ULONG;
   VmCounters : VM_COUNTERS;
   PrivatePageCount : ULONG;
   IoCounters: IO_COUNTERS;
   Threads: array [0..0] of SYSTEM_THREADS;  
 end;

После изменения порядка объявления переменных:
SYSTEM_PROCESSES_ADD = packed record
   NextEntryDelta : ULONG;
   ThreadCount : ULONG;
   CreateTime : LARGE_INTEGER;
   UserTime : LARGE_INTEGER;
   KernelTime : LARGE_INTEGER;
   BasePriority : KPRIORITY;
   ProcessId : ULONG;
   InheritedFromProcessId : ULONG;
   HandleCount : ULONG;
   VmCounters : VM_COUNTERS;
   PrivatePageCount : ULONG;
   IoCounters: IO_COUNTERS;
   Threads: array [0..0] of SYSTEM_THREADS;
   ProcessName : string;<--Перемещено
   FullPath : string;<--Перемещено
   UserName : string;<--Перемещено  
 end;

скорость выполнения процедуры упала в пять раз !
Перепроверила раз сто. Вывод один:
От порядка объявления переменных зависит скорость.
Возникают два вопроса:
Почему это происходит и как в данной конкретной
стуктуре оптимальнее всего разместить переменные ?
Не перебирать же все возможные перестановки :))


 
MBo ©   (2006-07-27 15:27) [1]

А почему массив Threads, как я полагаю, неопределенного размера (точнее, определяемого, видимо, динамически), не последним параметром во втором случае передается?


 
tesseract ©   (2006-07-27 15:28) [2]


> От порядка объявления переменных зависит скорость.


В packed record да, зависит. Необходимо выровнять переменные по 4 байтам.


 
Сергей М. ©   (2006-07-27 15:28) [3]


> передовала


> После изменения порядка объявления переменных


Ты с дуба упала ?)
MSDN тебе уже не указ ?)

Там что, так прямо и написано, мол, меняй порядок следования полей записи как тебе вздумается ?)


 
tesseract ©   (2006-07-27 15:29) [4]

а она ещё и стандартная :-)

да больше так не надо делать.......


 
StriderMan ©   (2006-07-27 15:45) [5]


> MSDN тебе уже не указ ?)

че-то не нашел в MSDN такой структуры... может MSDN обновить...


 
Игорь Шевченко ©   (2006-07-27 15:50) [6]

Сергей М. ©   (27.07.06 15:28) [3]

Это не MSDN. Это вольная переделка моего творчества, похоже.


 
MBo ©   (2006-07-27 15:50) [7]

>StriderMan ©   (27.07.06 15:45) [5]
в msdn недокументировано.
http://www.rsdn.ru/article/qna/baseserv/enumproc.xml


 
learner ©   (2006-07-27 15:52) [8]

>[3] Сергей М. ©   (27.07.06 15:28)
"С дуба я не падала", а вот Вам необходимо подучиться хорошим манерам

Эту стуктуру использую и заполняю в мною написаной процедуре.
и как параметр ни в какие API функции не передаю.
Так что что хочу и как хочу так в ней и объявляю.


 
learner ©   (2006-07-27 15:53) [9]

>[6] Игорь Шевченко ©   (27.07.06 15:50)
>Это не MSDN. Это вольная переделка моего творчества, похоже.
Совершенно верно.


 
Сергей М. ©   (2006-07-27 15:57) [10]


> learner ©   (27.07.06 15:52) [8]


> а вот Вам необходимо


Ой какие мы нежные !)


> [9]


И что, это дает уверенность, что порядок следования полей можно менять от балды ? Даже несмотря на то что это творчество уважаемого ИШ, а не мелкомягких ?


 
learner ©   (2006-07-27 16:02) [11]

>[10] Сергей М. ©   (27.07.06 15:57)
Это не точная копия.
>И что, это дает уверенность, что порядок следования полей можно менять от >балды ?
Так я же ее сама вручную заполняю. И в др. функциях (не моих) не использую.


 
learner ©   (2006-07-27 16:05) [12]

[2] tesseract ©   (27.07.06 15:28)
> В packed record да, зависит. Необходимо выровнять переменные по 4 байтам.
Это означает изменить тип или порядок ?
Можно подробнее ?


 
Мефисто   (2006-07-27 16:11) [13]

Воспользоваться рекомендациями:


> tesseract ©   (27.07.06 15:28) [2]


Причем в рекордах желательно первыми полями указывать поля по 4 байта,
потом 2 байта, и затем по 1 байтовые поля. Т.е. от большего к меньшему.
Причина в выравнивании данныйх по 4 байтам (tesseract ©   (27.07.06 15:28) [2]). А если беспорядочно поля выставить, то время зря тратиться на выравниваниек данных.


 
tesseract ©   (2006-07-27 16:17) [14]


>  А если беспорядочно поля выставить, то время зря тратиться
> на выравниваниек данных.


не на выравнивание, а на  поиск нужных данных в структуре, процесс долгий, учитываю 32 битность процессора.

Плюс ещё сбиваешь с толку кэш процессора.  

ЗЫ: но в пять раз - я так понимаю pentium4?


 
Мефисто   (2006-07-27 16:28) [15]


> tesseract ©   (27.07.06 16:17) [14]


Так скажем, оба этих фактора влияют в комплексе на проблему выше.


 
learner ©   (2006-07-27 16:29) [16]

>ЗЫ: но в пять раз - я так понимаю pentium4?
Да. pentium4, 3.0 GHz
Вызывала в цикле 10 000 раз.


 
tesseract ©   (2006-07-27 16:30) [17]


> Мефисто   (27.07.06 16:28) [15]


Да я не против. Так на пальцах раскрыл проблему как мог.
Сам уже слабо помню механиз всяких prefetch.

но AMD такой код воспримет лучше, чем p4.


 
learner ©   (2006-07-27 16:37) [18]

SYSTEM_PROCESSES_ADD = packed record
  IoCounters: IO_COUNTERS; ( 48 )
  VmCounters : VM_COUNTERS; ( 44 )
  CreateTime : LARGE_INTEGER;
  UserTime : LARGE_INTEGER;
  KernelTime : LARGE_INTEGER;
  NextEntryDelta : ULONG;
  ThreadCount : ULONG;
  ProcessId : ULONG;
  InheritedFromProcessId : ULONG;
  HandleCount : ULONG;
  PrivatePageCount : ULONG;
  BasePriority : KPRIORITY;
  ProcessName : string;
  FullPath : string;
  UserName : string;  
  Threads: array [0..0] of SYSTEM_THREADS;
end;
Т.е. так ?


 
Игорь Шевченко ©   (2006-07-27 16:41) [19]

learner ©   (27.07.06 16:37) [18]

Можно и так. А можно воспользоваться моими же классами...

{
  Модуль: NtProcessInfo

  Описание: Класс для удобного представления информации о списке процессов
            и потоков, возвращаемом функцией NtQuerySystemInformation
            с информационным классом SystemProcessesAndThreadsInformation

  Автор: Игорь Шевченко

  Дата создания: 20.12.2002

  История изменений:
}
unit NtProcessInfo;

interface
uses
 NtDll, HSObjectList, Windows, HsNtDef;

type
 THSNtThreadInfo = class
 public
   Info: SYSTEM_THREADS;
   constructor Create (AInfo: SYSTEM_THREADS);
 end;

 THSNtThreadInfoList = class(THSObjectList)
 private
   function GetItems (I: Integer): THSNtThreadInfo;
 public
   property Items[I: Integer]: THSNtThreadInfo read GetItems; default;
 end;

 {
   Информация о процессе, приведенная к единому виду для операционных систем
   Windows NT4 и Windows 2000 (и выше).
 }
 THSNtProcessInfo = class
 private
   function GetProcessName: string;
   function GetUserName: string;
 public
   Info: SYSTEM_PROCESSES_NT2000;
   Threads: THSNtThreadInfoList;

   constructor Create (const AInfo: SYSTEM_PROCESSES_NT2000);
   constructor CreateNt4 (const AInfo: SYSTEM_PROCESSES_NT4);
   destructor Destroy; override;
   property ProcessName: string read GetProcessName;
   property UserName: string read GetUserName;
 end;

 THSNtProcessInfoList = class(THSObjectList)
 private
   function GetItems (I: Integer): THSNtProcessInfo;
 public
   constructor Create (AData: Pointer);
   constructor CreateEmpty;
   procedure Rebuild (const AData: Pointer);
   property Items[I: Integer]: THSNtProcessInfo read GetItems; default;
 end;
 TQueryListInformation = function (InfoClass: Integer; var rc: NTSTATUS;
 var ReturnLength: DWORD): Pointer;

function QueryListInformation (InfoClass: Integer; var rc: NTSTATUS;
 var ReturnLength: DWORD): Pointer;
function QuerySessionListInformation (const SessionId: ULONG;
 InfoClass: Integer; var rc: NTSTATUS; var ReturnLength: DWORD): Pointer;

implementation
uses
 SysUtils, NtStatusDefs, NtUtils;

function QueryListInformation (InfoClass: Integer; var rc: NTSTATUS;
 var ReturnLength: DWORD): Pointer;
var
 ListSize: Integer;
begin
 ListSize := $400;
 GetMem(Result, ListSize);
 rc := NtQuerySystemInformation(InfoClass, Result, ListSize, @ReturnLength);
 while rc = STATUS_INFO_LENGTH_MISMATCH do begin
   FreeMem(Result);
   ListSize := ListSize * 2;
   GetMem(Result, ListSize);
   rc := NtQuerySystemInformation(InfoClass, Result, ListSize, @ReturnLength);
 end;
 if rc <> STATUS_SUCCESS then begin
   FreeMem(Result);
   Result := nil;
 end;
end;

function QuerySessionListInformation (const SessionId: ULONG;
 InfoClass: Integer; var rc: NTSTATUS; var ReturnLength: DWORD): Pointer;
var
 ListSize: Integer;
 SystemSessionInformation: SYSTEM_SESSION_INFORMATION;
begin
 ListSize := $1000;
 SystemSessionInformation.SessionId := SessionId;
 SystemSessionInformation.BufferSize := ListSize;
 GetMem(SystemSessionInformation.Buffer, ListSize);
 rc := NtQuerySystemInformation(InfoClass, @SystemSessionInformation,
   SizeOf(SystemSessionInformation), @ReturnLength);
 while rc = STATUS_INFO_LENGTH_MISMATCH do begin
   FreeMem(SystemSessionInformation.Buffer);
   ListSize := ListSize * 2;
   SystemSessionInformation.BufferSize := ListSize;
   GetMem(SystemSessionInformation.Buffer, ListSize);
   rc := NtQuerySystemInformation(InfoClass, @SystemSessionInformation,
     SizeOf(SystemSessionInformation), @ReturnLength);
 end;
 if rc <> STATUS_SUCCESS then begin
   FreeMem(SystemSessionInformation.Buffer);
   Result := nil;
 end else
   Result := SystemSessionInformation.Buffer;
end;

{ THSNtThreadInfo }

constructor THSNtThreadInfo.Create (AInfo: SYSTEM_THREADS);
begin
 inherited Create;
 Info := AInfo;
end;

{ THSNtThreadInfoList }

function THSNtThreadInfoList.GetItems (I: Integer): THSNtThreadInfo;
begin
 Result := THSNtThreadInfo(inherited Items[I]);
end;

{ THSNtProcessInfo }

constructor THSNtProcessInfo.Create (const AInfo: SYSTEM_PROCESSES_NT2000);
begin
 inherited Create;
 Info := AInfo;
 Threads := THSNtThreadInfoList.Create;
end;

constructor THSNtProcessInfo.CreateNt4 (const AInfo: SYSTEM_PROCESSES_NT4);
begin
 inherited Create;
 Move (AInfo, Info, SizeOf(AInfo));
 FillChar(Info.IoCounters, SizeOf(IO_COUNTERS), 0);
 Threads := THSNtThreadInfoList.Create;
end;

destructor THSNtProcessInfo.Destroy;
begin
 Threads.Free;
 inherited;
end;

{ THSNtProcessInfoList }

constructor THSNtProcessInfoList.Create (AData: Pointer);
begin
 inherited Create;
 Rebuild (AData);
end;

constructor THSNtProcessInfoList.CreateEmpty;
begin
 inherited Create;
end;

function THSNtProcessInfoList.GetItems (I: Integer): THSNtProcessInfo;
begin
 Result := THSNtProcessInfo(inherited Items[I]);
end;

function THSNtProcessInfo.GetProcessName: string;
begin
 Result := HSUnicodeStringToAnsiString(Info.ProcessName);
end;

procedure THSNtProcessInfoList.Rebuild(const AData: Pointer);
var
 NextOffset: ULONG;
 PProcess: PSYSTEM_PROCESSES_NT2000;
 ProcessItem: THSNtProcessInfo;
 PThreads: PSYSTEM_THREADS_ARRAY;
 I: Integer;
begin
 Clear;
 PProcess := PSYSTEM_PROCESSES_NT2000(AData);
 repeat
   if Win32MajorVersion <= 4 then begin
     ProcessItem := THSNtProcessInfo.CreateNt4 (
       PSYSTEM_PROCESSES_NT4(PProcess)^);
     PThreads := PSYSTEM_THREADS_ARRAY(DWORD(PProcess) +
       SizeOf(SYSTEM_PROCESSES_NT4));
   end else begin
     ProcessItem := THSNtProcessInfo.Create(PProcess^);
     PThreads := PSYSTEM_THREADS_ARRAY(DWORD(PProcess) +
       SizeOf(SYSTEM_PROCESSES_NT2000));
   end;
   for I:=0 to Pred(ProcessItem.Info.ThreadCount) do
     ProcessItem.Threads.Add(THSNtThreadInfo.Create(PThreads^[I]));
   Add(ProcessItem);
   NextOffset := PProcess^.NextEntryDelta;
   PProcess := PSYSTEM_PROCESSES_NT2000(DWORD(PProcess) + NextOffset);
 until NextOffset = 0;
end;

function SIDToName (const SID: PSID): string;
var
 Use: SID_NAME_USE;
 DomainName: ZString;
 DomainNameLength: DWORD;
 Name: ZString;
 NameLength: DWORD;
begin
 DomainNameLength := SizeOf(DomainName);
 NameLength := SizeOf(Name);
 if not LookupAccountSid (nil, SID, Name, NameLength, DomainName,
    DomainNameLength, Use) then
   Result := "***"
 else
   Result := Name;
end;

function THSNtProcessInfo.GetUserName: string;
var
 AccessToken: THandle;
 SidInfo: PSIDANDATTRIBUTES;
 ReturnLength: DWORD;
 ProcessHandle: THandle;
begin
 Result := "";
 ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION, false,
   Info.ProcessId);
 if ProcessHandle = 0 then
   Exit;
 try
   if not OpenProcessToken(ProcessHandle, TOKEN_QUERY, AccessToken) then
     Exit;
   GetMem (SidInfo, 4096);
   try
     Win32Check(GetTokenInformation(AccessToken, TokenUser, SidInfo, 4096,
       ReturnLength));
     Result := SidToName(SidInfo^.Sid);
   finally
     FreeMem(SidInfo);
     CloseHandle(AccessToken);
   end;
 finally
   CloseHandle(ProcessHandle);
 end;
end;

end.


 
tesseract ©   (2006-07-27 16:48) [20]


> learner ©   (27.07.06 16:37) [18]


вся запись должна быть кратна 32.
это повышает производительность. В приниципе убери packed и должно всё работать.

сначала объявляються 4 - байтные поля - потом остальные.
string лучше заменить на pchar -тоже 4 байта будет.


 
learner ©   (2006-07-27 16:54) [21]

>[19] Игорь Шевченко ©   (27.07.06 16:41)
Игорь, спасибо большое.
Именно этот модуль я, сейчас, и изучаю :))
Мне непонятно только одно. Почему Вы так определяете размер буфера ?

rc := NtQuerySystemInformation(InfoClass, @SystemSessionInformation,
  SizeOf(SystemSessionInformation), @ReturnLength);
while rc = STATUS_INFO_LENGTH_MISMATCH do begin
  FreeMem(SystemSessionInformation.Buffer);
  ListSize := ListSize * 2;
  SystemSessionInformation.BufferSize := ListSize;
  GetMem(SystemSessionInformation.Buffer, ListSize);
  rc := NtQuerySystemInformation(InfoClass, @SystemSessionInformation,
    SizeOf(SystemSessionInformation), @ReturnLength);
end;

У меня, почему-то работает следующее :
cbSize:=0;
rc := NtQuerySystemInformation(InfoClass, nil, cbSize, @ReturnLength);
if rc = STATUS_INFO_LENGTH_MISMATCH then
begin
 cbSize:=ReturnLength;
 ReallocMem(pSysInfo, ReturnLength);
 rc:=NtQuerySystemInformation(InfoClass, pSysInfo, cbSize,ReturnLength);
end;


 
Ketmar ©   (2006-07-27 17:02) [22]

ReallocMem в стандартном MM страдает неэффективностью (если верить статьям на rsdn %-).


 
Игорь Шевченко ©   (2006-07-27 17:03) [23]

learner ©   (27.07.06 16:54) [21]


> Мне непонятно только одно. Почему Вы так определяете размер
> буфера ?


Так список процессов от вызова к вызову может меняться :) Поэтому ReturnLength может не сработать при следующем вызове.


 
learner ©   (2006-07-27 17:28) [24]

>[23] Игорь Шевченко ©   (27.07.06 17:03)
:))
Разместила преременные как все мне посоветовали и получила прирост
скорости на 8%. Мелочь, а так приятно :))


 
Германн ©   (2006-07-27 17:33) [25]


> Разместила преременные как все мне посоветовали и получила
> прирост
> скорости на 8%. Мелочь, а так приятно :))

А где же начальные "пять раз"?
:-)


 
Игорь Шевченко ©   (2006-07-27 18:01) [26]


> Разместила преременные как все мне посоветовали и получила
> прирост
> скорости на 8%. Мелочь, а так приятно


А что за смысл задачи, что такие требования к скорости предъявляются, если не секрет ?


 
learner ©   (2006-07-27 18:34) [27]

>А где же начальные "пять раз"?
Тестировала - тестировала и , вдруг, скорость упала в пять раз.
Вообще - то я прогоняла, чтобы посмотреть на утечку памяти, но так получилось. Стала выяснять в чем дело, вернулась по "хистору"
к предидущим вариантам. Поняла, что дело в расположении переменных.
А 8% прироста, это от исходной скорости.
>А что за смысл задачи, что такие требования к скорости предъявляются, если >не секрет ?
Не секрет.
На заре мною была написана программа. Она при запуске мне выводила списки
прцессов, сервисов, драйверов и DLL - ек появившихся в системе с момента ее предидущего запуска или не знакомых ей. А также новые вхождения
в реестре ( которые я знаю ) в плане автозапуска и подгружаемых библиотек.
Очень часто она мне помогала и я к ней привыкла. Но она совсем по-дилетански написана, и на сканирование всего у нее уходило 45-50 сек.
Вот и решила переписать.  
А ZwQuerySystemInformation дает очень много полезной информации.
Вот и стала изучать труды Игоря Шевченко :))


 
learner ©   (2006-07-27 18:37) [28]

Сорри надо читать : "предыдущего"



Страницы: 1 вся ветка

Текущий архив: 2006.08.20;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.042 c
15-1153391517
Vlad
2006-07-20 14:31
2006.08.20
Ваша гражданская позиция (небольшой опрос)


15-1153430033
QuickFinder
2006-07-21 01:13
2006.08.20
Игры на ZX-Spectrum: Back To Skool


15-1153560452
brother
2006-07-22 13:27
2006.08.20
Иконки рабочего стола


2-1154012559
Лом
2006-07-27 19:02
2006.08.20
Сложение двух массивов


15-1153167812
Loginov Dmitry
2006-07-18 00:23
2006.08.20
Прошу заценить новую статью