Skip to content

Commit 240d0e7

Browse files
committed
Inline the common case of balance functions
1 parent 8c47ec9 commit 240d0e7

File tree

2 files changed

+67
-28
lines changed

2 files changed

+67
-28
lines changed

containers/src/Data/Map/Internal.hs

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4205,7 +4205,14 @@ ratio = 2
42054205
-- It is only written in such a way that every node is pattern-matched only once.
42064206

42074207
balance :: k -> a -> Map k a -> Map k a -> Map k a
4208-
balance k x l r = case l of
4208+
balance k x l r = case (l, r) of
4209+
(Bin ls _ _ _ _, Bin rs _ _ _ _)
4210+
| rs <= delta*ls && ls <= delta*rs -> Bin (1+ls+rs) k x l r
4211+
_ -> balance_ k x l r
4212+
{-# INLINE balance #-} -- See Note [Inlining balance] in Data.Set.Internal
4213+
4214+
balance_ :: k -> a -> Map k a -> Map k a -> Map k a
4215+
balance_ k x l r = case l of
42094216
Tip -> case r of
42104217
Tip -> Bin 1 k x Tip Tip
42114218
(Bin _ _ _ Tip Tip) -> Bin 2 k x Tip r
@@ -4229,13 +4236,12 @@ balance k x l r = case l of
42294236
| rls < ratio*rrs -> Bin (1+ls+rs) rk rx (Bin (1+ls+rls) k x l rl) rr
42304237
| otherwise -> Bin (1+ls+rs) rlk rlx (Bin (1+ls+size rll) k x l rll) (Bin (1+rrs+size rlr) rk rx rlr rr)
42314238
(_, _) -> error "Failure in Data.Map.balance"
4232-
| ls > delta*rs -> case (ll, lr) of
4239+
| {- ls > delta*rs -} otherwise -> case (ll, lr) of
42334240
(Bin lls _ _ _ _, Bin lrs lrk lrx lrl lrr)
42344241
| lrs < ratio*lls -> Bin (1+ls+rs) lk lx ll (Bin (1+rs+lrs) k x lr r)
42354242
| otherwise -> Bin (1+ls+rs) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+rs+size lrr) k x lrr r)
42364243
(_, _) -> error "Failure in Data.Map.balance"
4237-
| otherwise -> Bin (1+ls+rs) k x l r
4238-
{-# NOINLINE balance #-}
4244+
{-# NOINLINE balance_ #-}
42394245

42404246
-- Functions balanceL and balanceR are specialised versions of balance.
42414247
-- balanceL only checks whether the left subtree is too big,
@@ -4244,7 +4250,14 @@ balance k x l r = case l of
42444250
-- balanceL is called when left subtree might have been inserted to or when
42454251
-- right subtree might have been deleted from.
42464252
balanceL :: k -> a -> Map k a -> Map k a -> Map k a
4247-
balanceL k x l r = case r of
4253+
balanceL k x l r = case (l, r) of
4254+
(Bin ls _ _ _ _, Bin rs _ _ _ _)
4255+
| ls <= delta*rs -> Bin (1+ls+rs) k x l r
4256+
_ -> balanceL_ k x l r
4257+
{-# INLINE balanceL #-} -- See Note [Inlining balance] in Data.Set.Internal
4258+
4259+
balanceL_ :: k -> a -> Map k a -> Map k a -> Map k a
4260+
balanceL_ k x l r = case r of
42484261
Tip -> case l of
42494262
Tip -> Bin 1 k x Tip Tip
42504263
(Bin _ _ _ Tip Tip) -> Bin 2 k x l Tip
@@ -4257,19 +4270,24 @@ balanceL k x l r = case r of
42574270
(Bin rs _ _ _ _) -> case l of
42584271
Tip -> Bin (1+rs) k x Tip r
42594272

4260-
(Bin ls lk lx ll lr)
4261-
| ls > delta*rs -> case (ll, lr) of
4273+
(Bin ls lk lx ll lr) -> case (ll, lr) of
42624274
(Bin lls _ _ _ _, Bin lrs lrk lrx lrl lrr)
42634275
| lrs < ratio*lls -> Bin (1+ls+rs) lk lx ll (Bin (1+rs+lrs) k x lr r)
42644276
| otherwise -> Bin (1+ls+rs) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+rs+size lrr) k x lrr r)
4265-
(_, _) -> error "Failure in Data.Map.balanceL"
4266-
| otherwise -> Bin (1+ls+rs) k x l r
4267-
{-# NOINLINE balanceL #-}
4277+
(_, _) -> error "Failure in Data.Map.balanceL_"
4278+
{-# NOINLINE balanceL_ #-}
42684279

42694280
-- balanceR is called when right subtree might have been inserted to or when
42704281
-- left subtree might have been deleted from.
42714282
balanceR :: k -> a -> Map k a -> Map k a -> Map k a
4272-
balanceR k x l r = case l of
4283+
balanceR k x l r = case (l, r) of
4284+
(Bin ls _ _ _ _, Bin rs _ _ _ _)
4285+
| rs <= delta*ls -> Bin (1+ls+rs) k x l r
4286+
_ -> balanceR_ k x l r
4287+
{-# INLINE balanceR #-} -- See Note [Inlining balance] in Data.Set.Internal
4288+
4289+
balanceR_ :: k -> a -> Map k a -> Map k a -> Map k a
4290+
balanceR_ k x l r = case l of
42734291
Tip -> case r of
42744292
Tip -> Bin 1 k x Tip Tip
42754293
(Bin _ _ _ Tip Tip) -> Bin 2 k x Tip r
@@ -4282,14 +4300,12 @@ balanceR k x l r = case l of
42824300
(Bin ls _ _ _ _) -> case r of
42834301
Tip -> Bin (1+ls) k x l Tip
42844302

4285-
(Bin rs rk rx rl rr)
4286-
| rs > delta*ls -> case (rl, rr) of
4303+
(Bin rs rk rx rl rr) -> case (rl, rr) of
42874304
(Bin rls rlk rlx rll rlr, Bin rrs _ _ _ _)
42884305
| rls < ratio*rrs -> Bin (1+ls+rs) rk rx (Bin (1+ls+rls) k x l rl) rr
42894306
| otherwise -> Bin (1+ls+rs) rlk rlx (Bin (1+ls+size rll) k x l rll) (Bin (1+rrs+size rlr) rk rx rlr rr)
4290-
(_, _) -> error "Failure in Data.Map.balanceR"
4291-
| otherwise -> Bin (1+ls+rs) k x l r
4292-
{-# NOINLINE balanceR #-}
4307+
(_, _) -> error "Failure in Data.Map.balanceR_"
4308+
{-# NOINLINE balanceR_ #-}
42934309

42944310

42954311
{--------------------------------------------------------------------

containers/src/Data/Set/Internal.hs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,10 +1847,30 @@ ratio = 2
18471847
-- balanceL only checks whether the left subtree is too big,
18481848
-- balanceR only checks whether the right subtree is too big.
18491849

1850+
-- Note [Inlining balance]
1851+
-- ~~~~~~~~~~~~~~~~~~~~~~~
1852+
-- According to benchmarks, we benefit from inlining balanceL and balanceR. But
1853+
-- we don't want to cause code bloat from inlining these large functions too
1854+
-- much. As a compromise, we inline only one case: Both trees are Bins already
1855+
-- balanced with respect to each other.
1856+
--
1857+
-- For typical use cases this is the most frequently applicable case. For
1858+
-- instance, for n inserts there may be O(n log n) calls to balanceL/balanceR
1859+
-- but at most O(n) of them actually require rebalancing. Benchmarks show that
1860+
-- inlining this case provides most of the potential benefits of inlining the
1861+
-- full function.
1862+
18501863
-- balanceL is called when left subtree might have been inserted to or when
18511864
-- right subtree might have been deleted from.
18521865
balanceL :: a -> Set a -> Set a -> Set a
1853-
balanceL x l r = case r of
1866+
balanceL x l r = case (l, r) of
1867+
(Bin ls _ _ _, Bin rs _ _ _)
1868+
| ls <= delta*rs -> Bin (1+ls+rs) x l r
1869+
_ -> balanceL_ x l r
1870+
{-# INLINE balanceL #-} -- See Note [Inlining balance]
1871+
1872+
balanceL_ :: a -> Set a -> Set a -> Set a
1873+
balanceL_ x l r = case r of
18541874
Tip -> case l of
18551875
Tip -> Bin 1 x Tip Tip
18561876
(Bin _ _ Tip Tip) -> Bin 2 x l Tip
@@ -1863,19 +1883,24 @@ balanceL x l r = case r of
18631883
(Bin rs _ _ _) -> case l of
18641884
Tip -> Bin (1+rs) x Tip r
18651885

1866-
(Bin ls lx ll lr)
1867-
| ls > delta*rs -> case (ll, lr) of
1886+
(Bin ls lx ll lr) -> case (ll, lr) of
18681887
(Bin lls _ _ _, Bin lrs lrx lrl lrr)
18691888
| lrs < ratio*lls -> Bin (1+ls+rs) lx ll (Bin (1+rs+lrs) x lr r)
18701889
| otherwise -> Bin (1+ls+rs) lrx (Bin (1+lls+size lrl) lx ll lrl) (Bin (1+rs+size lrr) x lrr r)
1871-
(_, _) -> error "Failure in Data.Set.balanceL"
1872-
| otherwise -> Bin (1+ls+rs) x l r
1873-
{-# NOINLINE balanceL #-}
1890+
(_, _) -> error "Failure in Data.Set.balanceL_"
1891+
{-# NOINLINE balanceL_ #-}
18741892

18751893
-- balanceR is called when right subtree might have been inserted to or when
18761894
-- left subtree might have been deleted from.
18771895
balanceR :: a -> Set a -> Set a -> Set a
1878-
balanceR x l r = case l of
1896+
balanceR x l r = case (l, r) of
1897+
(Bin ls _ _ _, Bin rs _ _ _)
1898+
| rs <= delta*ls -> Bin (1+ls+rs) x l r
1899+
_ -> balanceR_ x l r
1900+
{-# INLINE balanceR #-} -- See Note [Inlining balance]
1901+
1902+
balanceR_ :: a -> Set a -> Set a -> Set a
1903+
balanceR_ x l r = case l of
18791904
Tip -> case r of
18801905
Tip -> Bin 1 x Tip Tip
18811906
(Bin _ _ Tip Tip) -> Bin 2 x Tip r
@@ -1888,14 +1913,12 @@ balanceR x l r = case l of
18881913
(Bin ls _ _ _) -> case r of
18891914
Tip -> Bin (1+ls) x l Tip
18901915

1891-
(Bin rs rx rl rr)
1892-
| rs > delta*ls -> case (rl, rr) of
1916+
(Bin rs rx rl rr) -> case (rl, rr) of
18931917
(Bin rls rlx rll rlr, Bin rrs _ _ _)
18941918
| rls < ratio*rrs -> Bin (1+ls+rs) rx (Bin (1+ls+rls) x l rl) rr
18951919
| otherwise -> Bin (1+ls+rs) rlx (Bin (1+ls+size rll) x l rll) (Bin (1+rrs+size rlr) rx rlr rr)
1896-
(_, _) -> error "Failure in Data.Set.balanceR"
1897-
| otherwise -> Bin (1+ls+rs) x l r
1898-
{-# NOINLINE balanceR #-}
1920+
(_, _) -> error "Failure in Data.Set.balanceR_"
1921+
{-# NOINLINE balanceR_ #-}
18991922

19001923
{--------------------------------------------------------------------
19011924
The bin constructor maintains the size of the tree

0 commit comments

Comments
 (0)