title: VirtualStringTree updating data using cache system
body: <p>Well, I'm using VirtualStringTree to create kind of a process manager...</p>
  
  <p>I run into trouble because of updating the tree with a timer set to 1000ms (cpu usage is too high for my application retrieving a lot of data (filling about 20 columns). </p>
  
  <p>So I wonder how would one build kind of a cache system so I can update the tree only when something changed which I guess seems to be the key decrementing the cpu usage for my application a lot?</p>
  
  <p>Snip:</p>
  
  <pre><code>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;
  </code></pre>
  
  <p>If my application starts I fill the tree with all running processes.
  Remember this is called only once, later when the application runs I got notified of new processes or processes which are terminated via wmi so I dont need to call the following procedure in the timer later to update the tree...</p>
  
  <pre><code>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;
  
  ...
  </code></pre>
  
  <p>I have a Class which will retrieve all the data I want and store it into the tree like:</p>
  
  <pre><code>var
    FRunningProcesses: TProcessRunningProcesses;
  </code></pre>
  
  <p>So if I want to enumerate all running processes I just give it a call like:</p>
  
  <pre><code>  // clears all data inside the class and refills everything with the new data... 
    FRunningProcesses.UpdateProcesses;
  </code></pre>
  
  <p>The problem starts here while I enumerate everything and not only data which had changed which is quite cpu intensive:</p>
  
  <pre><code>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; 
  ....
  </code></pre>
  
  <p>Basically the timer is only needed for cpu usage and all memory informations I can retrieve from a process like: </p>
  
  <ul>
  <li>Priv.Memory</li>
  <li>Working Set</li>
  <li>Peak Working Set</li>
  <li>Virtual Size</li>
  <li>PageFile Usage</li>
  <li>Peak PageFile Usage </li>
  <li>Page Faults</li>
  <li>Cpu Usage</li>
  <li>Thread Count</li>
  <li>Handle Count</li>
  <li>GDI Handle Count</li>
  <li>User Handle Count</li>
  <li>Total Cpu Time</li>
  <li>User Cpu Time</li>
  <li>Kernel Cpu Time</li>
  </ul>
  
  <p>So I think the above data must be cached and compared somehow if its changed or not just wonder how and what will be most efficient?</p>