@@ -338,22 +338,35 @@ static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, int level,
338338 if (pid == 0 )
339339 return ;
340340
341- Vector * children = Vector_new (Class (Process ), false, DEFAULT_SIZE );
342-
343- int lastShown = 0 ;
344- for (int i = Vector_size (this -> processes ) - 1 ; i >= 0 ; i -- ) {
345- Process * process = (Process * )Vector_get (this -> processes , i );
346- if (Process_isChildOf (process , pid )) {
347- if (process -> show )
348- lastShown = Vector_size (children );
349- Vector_add (children , process );
341+ // The vector is sorted by parent PID, find the start of the range by bisection
342+ int vsize = Vector_size (this -> processes );
343+ int l = 0 ;
344+ int r = vsize ;
345+ while (l < r ) {
346+ int c = (l + r ) / 2 ;
347+ Process * process = (Process * )Vector_get (this -> processes , c );
348+ pid_t ppid = process -> isRoot ? 0 : Process_getParentPid (process );
349+ if (ppid < pid ) {
350+ l = c + 1 ;
351+ } else {
352+ r = c ;
350353 }
351354 }
355+ // Find the end to know the last line for indent handling purposes
356+ int lastShown = r ;
357+ while (r < vsize ) {
358+ Process * process = (Process * )Vector_get (this -> processes , r );
359+ if (!Process_isChildOf (process , pid ))
360+ break ;
361+ if (process -> show )
362+ lastShown = r ;
363+ r ++ ;
364+ }
365+
366+ for (int i = l ; i < r ; i ++ ) {
367+ Process * process = (Process * )Vector_get (this -> processes , i );
352368
353- int size = Vector_size (children );
354- for (int i = 0 ; i < size ; i ++ ) {
355369 int index = (* node_index )++ ;
356- Process * process = (Process * )Vector_get (children , i );
357370
358371 int lft = (* node_counter )++ ;
359372
@@ -382,7 +395,6 @@ static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, int level,
382395 process -> tree_index = index ;
383396 Hashtable_put (this -> displayTreeSet , index , process );
384397 }
385- Vector_delete (children );
386398}
387399
388400static int ProcessList_treeProcessCompare (const void * v1 , const void * v2 ) {
@@ -392,10 +404,18 @@ static int ProcessList_treeProcessCompare(const void* v1, const void* v2) {
392404 return SPACESHIP_NUMBER (p1 -> tree_left , p2 -> tree_left );
393405}
394406
395- static int ProcessList_treeProcessCompareByPID (const void * v1 , const void * v2 ) {
407+ static int compareProcessByKnownParentThenPID (const void * v1 , const void * v2 ) {
396408 const Process * p1 = (const Process * )v1 ;
397409 const Process * p2 = (const Process * )v2 ;
398410
411+ int result = SPACESHIP_NUMBER (
412+ p1 -> isRoot ? 0 : Process_getParentPid (p1 ),
413+ p2 -> isRoot ? 0 : Process_getParentPid (p2 )
414+ );
415+
416+ if (result != 0 )
417+ return result ;
418+
399419 return SPACESHIP_NUMBER (p1 -> pid , p2 -> pid );
400420}
401421
@@ -406,34 +426,37 @@ static void ProcessList_buildTree(ProcessList* this) {
406426 int node_counter = 1 ;
407427 int node_index = 0 ;
408428
409- // Sort by PID
410- Vector_quickSortCustomCompare (this -> processes , ProcessList_treeProcessCompareByPID );
429+ // Mark root processes
411430 int vsize = Vector_size (this -> processes );
412-
413- // Find all processes whose parent is not visible
414- int size = Vector_size (this -> processes );
415- for (int i = 0 ; i < size ; i ++ ) {
431+ for (int i = 0 ; i < vsize ; i ++ ) {
416432 Process * process = (Process * )Vector_get (this -> processes , i );
417-
418433 pid_t ppid = Process_getParentPid (process );
419- bool isRoot = false;
434+ process -> isRoot = false;
420435
421436 // If PID corresponds with PPID (e.g. "kernel_task" (PID:0, PPID:0)
422437 // on Mac OS X 10.11.6) regard this process as root.
423438 if (process -> pid == ppid )
424- isRoot = true;
439+ process -> isRoot = true;
425440
426441 // On Linux both the init process (pid 1) and the root UMH kernel thread (pid 2)
427442 // use a ppid of 0. As that PID can't exist, we can skip searching for it.
428443 if (!ppid )
429- isRoot = true;
444+ process -> isRoot = true;
430445
431- // Lookup the parent via the processTable hashtable not modified in buildTree
446+ // We don't know about its parent for whatever reason
432447 if (ProcessList_findProcess (this , ppid ) == NULL )
433- isRoot = true;
448+ process -> isRoot = true;
449+ }
450+
451+ // Sort by known parent PID (roots first), then PID
452+ Vector_quickSortCustomCompare (this -> processes , compareProcessByKnownParentThenPID );
453+
454+ // Find all processes whose parent is not visible
455+ for (int i = 0 ; i < vsize ; i ++ ) {
456+ Process * process = (Process * )Vector_get (this -> processes , i );
434457
435458 // If parent not found, then construct the tree with this node as root
436- if (isRoot ) {
459+ if (process -> isRoot ) {
437460 process = (Process * )Vector_get (this -> processes , i );
438461 process -> indent = 0 ;
439462 process -> tree_depth = 0 ;
0 commit comments