Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.08.20;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.049 c
15-1153331373
Юрий Зотов
2006-07-19 21:49
2006.08.20
Что Вы думаете о буквоедах?


15-1153428532
Footballer
2006-07-21 00:48
2006.08.20
А какие вы знаете смайлики? %)


2-1154266307
Ivolg
2006-07-30 17:31
2006.08.20
Запуск *.bat файла


15-1153421716
Vendict
2006-07-20 22:55
2006.08.20
Клиент


3-1150127390
Вася
2006-06-12 19:49
2006.08.20
Как создать поле в ClientDatSet





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский