 :: collect-flat ( samples -- flat )
     IH{ } clone :> per-word-samples
     samples [| sample |
-        sample sample-callstack unique keys [
+        sample sample-callstack unique keys [ ignore-word? not ] filter [
             per-word-samples [ { 0 0 0 0 } or sample 4 head-slice v+ ] change-at
         ] each
     ] each
     per-word-samples [ f <profile-node> ] assoc-map ;
 
+: redundant-flat-node? ( child-node root-node -- ? )
+    [ total-time>> ] bi@ = ;
+
+: trim-flat ( root-node -- root-node' )
+    dup '[ [ nip _ redundant-flat-node? not ] assoc-filter ] change-children ;
+
 : (flat) ( samples -- flat )
-    collect-threads [
-        [ sum-times ] [ collect-flat ] bi <profile-node>
-    ] assoc-map ;
+    collect-threads
+    [ [ collect-flat ] <profile-root-node> trim-flat ] assoc-map ;
 
 : flat ( -- tree )
     get-raw-profile-data (flat) ;

    dup redundant-root-node? [ children>> values first trim-root ] when ;

: (top-down) ( samples -- tree )
    collect-threads [
        [ sum-times ] [ collect-tops ] bi <profile-node> trim-root
    ] assoc-map ;

: top-down ( -- tree )
    get-raw-profile-data (top-down) ;

: unclip-callstack ( sample -- sample' callstack-top )
    clone 5 over [ unclip swap ] change-nth ;

: leaf-callstack? ( callstack -- ? )
    [ ignore-word? ] all? ;

: sum-times ( samples -- times )
    { 0 0 0 0 } [ 4 head-slice v+ ] reduce ;

TUPLE: profile-node
    total-time gc-time foreign-time foreign-thread-time children ;

: <profile-node> ( times children -- node )
    [ first4 [ samples>time ] 4 napply ] dip profile-node boa ;

: <profile-root-node> ( samples collector-quot -- node )
    [ sum-times ] swap bi <profile-node> ; inline

:: (collect-subtrees) ( samples child-quot -- children )
    samples [ sample-callstack leaf-callstack? not ] filter
