}
 
 static bool unix_graph_maybe_cyclic;
+static bool unix_graph_grouped;
 
 static void unix_update_graph(struct unix_vertex *vertex)
 {
                return;
 
        unix_graph_maybe_cyclic = true;
+       unix_graph_grouped = false;
 }
 
 static LIST_HEAD(unix_unvisited_vertices);
                vertex->index = unix_vertex_unvisited_index;
                vertex->out_degree = 0;
                INIT_LIST_HEAD(&vertex->edges);
+               INIT_LIST_HEAD(&vertex->scc_entry);
 
                list_move_tail(&vertex->entry, &unix_unvisited_vertices);
                edge->predecessor->vertex = vertex;
 
        list_replace_init(&unix_visited_vertices, &unix_unvisited_vertices);
        swap(unix_vertex_unvisited_index, unix_vertex_grouped_index);
+
+       unix_graph_grouped = true;
+}
+
+static void unix_walk_scc_fast(void)
+{
+       while (!list_empty(&unix_unvisited_vertices)) {
+               struct unix_vertex *vertex;
+               struct list_head scc;
+
+               vertex = list_first_entry(&unix_unvisited_vertices, typeof(*vertex), entry);
+               list_add(&scc, &vertex->scc_entry);
+
+               list_for_each_entry_reverse(vertex, &scc, scc_entry)
+                       list_move_tail(&vertex->entry, &unix_visited_vertices);
+
+               list_del(&scc);
+       }
+
+       list_replace_init(&unix_visited_vertices, &unix_unvisited_vertices);
 }
 
 static LIST_HEAD(gc_candidates);
        if (!unix_graph_maybe_cyclic)
                goto skip_gc;
 
-       unix_walk_scc();
+       if (unix_graph_grouped)
+               unix_walk_scc_fast();
+       else
+               unix_walk_scc();
 
        /* First, select candidates for garbage collection.  Only
         * in-flight sockets are considered, and from those only ones