Skip to content

Commit 41f63aa

Browse files
authored
Improve foldr performance ~4x on large lists (#180)
* Add foldr benchmarking * even exponential spacing of list sizes * faster foldr
1 parent d00254b commit 41f63aa

File tree

2 files changed

+22
-35
lines changed

2 files changed

+22
-35
lines changed

bench/Bench/Data/List.purs

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,32 @@
11
module Bench.Data.List where
22

33
import Prelude
4+
import Data.Foldable (maximum)
5+
import Data.Int (pow)
6+
import Data.List (List(..), take, range, foldr, length)
7+
import Data.Maybe (fromMaybe)
8+
import Data.Traversable (traverse_)
49
import Effect (Effect)
510
import Effect.Console (log)
611
import Performance.Minibench (bench)
712

8-
import Data.List as L
9-
1013
benchList :: Effect Unit
1114
benchList = do
12-
log "map"
13-
log "---"
14-
benchMap
15+
benchLists "map" $ map (_ + 1)
16+
benchLists "foldr" $ foldr add 0
1517

1618
where
1719

18-
benchMap = do
19-
let nats = L.range 0 999999
20-
mapFn = map (_ + 1)
21-
list1000 = L.take 1000 nats
22-
list2000 = L.take 2000 nats
23-
list5000 = L.take 5000 nats
24-
list10000 = L.take 10000 nats
25-
list100000 = L.take 100000 nats
26-
27-
log "map: empty list"
28-
let emptyList = L.Nil
29-
bench \_ -> mapFn emptyList
30-
31-
log "map: singleton list"
32-
let singletonList = L.Cons 0 L.Nil
33-
bench \_ -> mapFn singletonList
34-
35-
log $ "map: list (" <> show (L.length list1000) <> " elems)"
36-
bench \_ -> mapFn list1000
37-
38-
log $ "map: list (" <> show (L.length list2000) <> " elems)"
39-
bench \_ -> mapFn list2000
40-
41-
log $ "map: list (" <> show (L.length list5000) <> " elems)"
42-
bench \_ -> mapFn list5000
20+
listSizes = Cons 0 $ map (pow 10) $ range 0 5
21+
nats = range 0 $ (fromMaybe 0 $ maximum listSizes) - 1
22+
lists = map (\n -> take n nats) listSizes
4323

44-
log $ "map: list (" <> show (L.length list10000) <> " elems)"
45-
bench \_ -> mapFn list10000
24+
benchLists :: forall b. String -> (List Int -> b) -> Effect Unit
25+
benchLists label func =
26+
traverse_ (benchAList label func) lists
4627

47-
log $ "map: list (" <> show (L.length list100000) <> " elems)"
48-
bench \_ -> mapFn list100000
28+
benchAList :: forall a b. String -> (List a -> b) -> List a -> Effect Unit
29+
benchAList label func list = do
30+
log "---"
31+
log $ label <> ": list (" <> show (length list) <> " elems)"
32+
bench \_ -> func list

src/Data/List/Types.purs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,10 @@ instance functorWithIndexList :: FunctorWithIndex Int List where
103103
instance foldableList :: Foldable List where
104104
foldr f b = foldl (flip f) b <<< rev
105105
where
106-
rev = foldl (flip Cons) Nil
106+
rev = go Nil
107+
where
108+
go acc Nil = acc
109+
go acc (x : xs) = go (x : acc) xs
107110
foldl f = go
108111
where
109112
go b = case _ of

0 commit comments

Comments
 (0)