好吧,我正在使用 VirtualStringTree 来创建一种流程管理器......
由于使用设置为 1000 毫秒的计时器更新树,我遇到了麻烦(cpu 使用率对于我的应用程序检索大量数据(填充大约 20 列)来说太高了。
所以我想知道如何构建一种缓存系统,以便我只能在发生某些变化时更新树,我猜这似乎是减少我的应用程序 cpu 使用率的关键?
剪辑:
type
TProcessNodeType = (ntParent, ntDummy);
PProcessData = ^TProcessData;
TProcessData = record
pProcessName : String;
pProcessID,
pPrivMemory,
pWorkingSet,
pPeakWorkingSet,
pVirtualSize,
pPeakVirtualSize,
pPageFileUsage,
pPeakPageFileUsage,
pPageFaults : Cardinal;
pCpuUsageStr: string;
pIOTotal: Cardinal;
...
end;
如果我的应用程序启动,我会用所有正在运行的进程填充树。请记住,这只调用一次,稍后当应用程序运行时,我会收到新进程或通过 wmi 终止的进程的通知,因此我不需要稍后在计时器中调用以下过程来更新树...
procedure FillTree;
begin
var
NodeData: PProcessData;
Node: PVirtualNode;
ParentNode: PVirtualNode;
ChildNode: PVirtualNode;
Process: TProcessItem;
I : Integer;
begin
ProcessTree.BeginUpdate;
for I := 0 to FRunningProcesses.Count - 1 do
begin
Process := FRunningProcesses[i];
NodeData^.pProcessID := ProcessItem.ProcessID;
NodeData^.pProcessName := ProcessItem.ProcessName;
...
我有一个类,它将检索我想要的所有数据并将其存储到树中,例如:
var
FRunningProcesses: TProcessRunningProcesses;
因此,如果我想枚举所有正在运行的进程,我只需给它一个如下调用:
// clears all data inside the class and refills everything with the new data...
FRunningProcesses.UpdateProcesses;
问题从这里开始,而我枚举了所有内容,而不仅仅是已经更改的数据,这些数据非常占用 CPU:
procedure TMainForm.UpdateTimerTimer(Sender: TObject);
var
NodeData: PProcessData;
Node : PVirtualNode;
Process: TProcessItem;
I: Integer;
begin
for I := 0 to FRunningProcesses.Count - 1 do
begin
Application.ProcessMessages;
Process := FRunningProcesses[I];
// returns PVirtualNode if the node is found inside the tree
Node := FindNodeByPID(Process.ProcessID);
if not(assigned(Node)) then
exit;
NodeData := ProcessVst.GetNodeData(Node);
if not(assigned(NodeData)) then
exit;
// now starting updating the tree
// NodeData^.pWorkingsSet := Process.WorkingsSet;
....
基本上,计时器仅用于 cpu 使用和我可以从以下进程中检索的所有内存信息:
- 私有内存
- 工作集
- 峰值工作集
- 虚拟尺寸
- 页面文件使用
- 峰值页面文件使用
- 页面错误
- CPU使用率
- 线程数
- 处理计数
- GDI 句柄计数
- 用户句柄计数
- 总 CPU 时间
- 用户 CPU 时间
- 内核CPU时间
所以我认为上面的数据必须被缓存并以某种方式进行比较,如果它改变了,或者不只是想知道如何以及什么是最有效的?