Skip to content

Commit 8aa8647

Browse files
authored
Improve performance of graphFromEdges (#1151)
* Replace `array` with `listArray` so we don't need to allocate `(index, element)` pairs. * Return -1 from the binary search when the key is not found to avoid `Just` allocations graphFromEdges benchmarks show reduced allocations by 18-39% and reduced time by 3-35%.
1 parent 97af0e8 commit 8aa8647

File tree

1 file changed

+17
-11
lines changed

1 file changed

+17
-11
lines changed

containers/src/Data/Graph.hs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ import Data.Foldable as F
126126
import qualified Data.Foldable1 as F1
127127
#endif
128128
import Control.DeepSeq (NFData(rnf),NFData1(liftRnf))
129-
import Data.Maybe
130129
import Data.Array
131130
#if USE_UNBOXED_ARRAYS
132131
import qualified Data.Array.Unboxed as UA
@@ -523,23 +522,30 @@ graphFromEdges edges0
523522
max_v = length edges0 - 1
524523
bounds0 = (0,max_v) :: (Vertex, Vertex)
525524
sorted_edges = L.sortBy lt edges0
526-
edges1 = zipWith (,) [0..] sorted_edges
527525

528-
graph = array bounds0 [(,) v (mapMaybe key_vertex ks) | (,) v (_, _, ks) <- edges1]
529-
key_map = array bounds0 [(,) v k | (,) v (_, k, _ ) <- edges1]
530-
vertex_map = array bounds0 edges1
526+
graph = listArray bounds0 [keysToVertices ks | (_, _, ks) <- sorted_edges]
527+
key_map = listArray bounds0 [k | (_, k, _) <- sorted_edges]
528+
vertex_map = listArray bounds0 sorted_edges
531529

532530
(_,k1,_) `lt` (_,k2,_) = k1 `compare` k2
533531

534-
-- key_vertex :: key -> Maybe Vertex
535-
-- returns Nothing for non-interesting vertices
536-
key_vertex k = findVertex 0 max_v
532+
keysToVertices = foldr f []
533+
where
534+
f k vs =
535+
let v = keyVertexGo k
536+
in if v < 0 then vs else v:vs
537+
538+
key_vertex k =
539+
let v = keyVertexGo k
540+
in if v < 0 then Nothing else Just v
541+
542+
-- Binary search. Returns -1 when not found.
543+
keyVertexGo k = findVertex 0 max_v
537544
where
538-
findVertex a b | a > b
539-
= Nothing
545+
findVertex a b | a > b = -1
540546
findVertex a b = case compare k (key_map ! mid) of
541547
LT -> findVertex a (mid-1)
542-
EQ -> Just mid
548+
EQ -> mid
543549
GT -> findVertex (mid+1) b
544550
where
545551
mid = a + (b - a) `div` 2

0 commit comments

Comments
 (0)