Форум: "Начинающим";
Текущий архив: 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.043 c