[commit: packages/bytestring] master, revert-46-patch-1, wip/nix-local-build: Improve the performance of `partition` for lazy and strict bytestrings (fae6927)

git at git.haskell.org git at git.haskell.org
Tue May 3 22:43:22 UTC 2016


Repository : ssh://git@git.haskell.org/bytestring

On branches: master,revert-46-patch-1,wip/nix-local-build
Link       : http://git.haskell.org/packages/bytestring.git/commitdiff/fae6927d42b8c9d31e670adfb2b80bbe18bacff9

>---------------------------------------------------------------

commit fae6927d42b8c9d31e670adfb2b80bbe18bacff9
Author: Sean <burton.seanr at gmail.com>
Date:   Fri Sep 18 09:14:01 2015 +0100

    Improve the performance of `partition` for lazy and strict bytestrings


>---------------------------------------------------------------

fae6927d42b8c9d31e670adfb2b80bbe18bacff9
 Data/ByteString.hs          | 46 ++++++++++++++++++++++++++++++++++++---------
 Data/ByteString/Internal.hs |  2 +-
 Data/ByteString/Lazy.hs     |  7 +++++--
 3 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/Data/ByteString.hs b/Data/ByteString.hs
index 42263a6..c141441 100644
--- a/Data/ByteString.hs
+++ b/Data/ByteString.hs
@@ -231,7 +231,7 @@ import Data.Maybe               (isJust, listToMaybe)
 #ifndef __NHC__
 import Control.Exception        (finally, bracket, assert, throwIO)
 #else
-import Control.Exception	(bracket, finally)
+import Control.Exception       (bracket, finally)
 #endif
 import Control.Monad            (when)
 
@@ -1259,14 +1259,42 @@ find f p = case findIndex f p of
 -- > partition p bs == (filter p xs, filter (not . p) xs)
 --
 partition :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
-partition p bs = (filter p bs, filter (not . p) bs)
---TODO: use a better implementation
-
--- ---------------------------------------------------------------------
--- Searching for substrings
-
--- | /O(n)/ The 'isPrefixOf' function takes two ByteStrings and returns 'True'
--- iff the first is a prefix of the second.
+partition f s = unsafeDupablePerformIO $
+    do fp' <- mallocByteString len
+       withForeignPtr fp' $ \p ->
+           do let end = p `plusPtr` (len - 1)
+              mid <- sep 0 p end
+              rev mid end
+              let i = mid `minusPtr` p
+              return (PS fp' 0 i,
+                      PS fp' i (len - i))
+  where
+    len  = length s
+    incr = (`plusPtr` 1)
+    decr = (`plusPtr` (-1))
+
+    sep !i !p1 !p2
+       | i == len  = return p1
+       | f w       = do poke p1 w
+                        sep (i + 1) (incr p1) p2
+       | otherwise = do poke p2 w
+                        sep (i + 1) p1 (decr p2)
+      where
+        w = s `unsafeIndex` i
+
+    rev !p1 !p2
+      | p1 >= p2  = return ()
+      | otherwise = do a <- peek p1
+                       b <- peek p2
+                       poke p1 b
+                       poke p2 a
+                       rev (incr p1) (decr p2)
+
+-- --------------------------------------------------------------------
+-- Sarching for substrings
+
+-- |/O(n)/ The 'isPrefixOf' function takes two ByteStrings and returns 'True'
+-- if the first is a prefix of the second.
 isPrefixOf :: ByteString -> ByteString -> Bool
 isPrefixOf (PS x1 s1 l1) (PS x2 s2 l2)
     | l1 == 0   = True
diff --git a/Data/ByteString/Internal.hs b/Data/ByteString/Internal.hs
index 0346d01..9747d10 100644
--- a/Data/ByteString/Internal.hs
+++ b/Data/ByteString/Internal.hs
@@ -169,7 +169,7 @@ import Foreign.ForeignPtr       (newForeignPtr_)
 
 -- An alternative to Control.Exception (assert) for nhc98
 #ifdef __NHC__
-#define assert	assertS "__FILE__ : __LINE__"
+#define assert  assertS "__FILE__ : __LINE__"
 assertS :: String -> Bool -> a -> a
 assertS _ True  = id
 assertS s False = error ("assertion failed at "++s)
diff --git a/Data/ByteString/Lazy.hs b/Data/ByteString/Lazy.hs
index ad8938b..5a0b0bd 100644
--- a/Data/ByteString/Lazy.hs
+++ b/Data/ByteString/Lazy.hs
@@ -1017,8 +1017,11 @@ filterNotByte w (LPS xs) = LPS (filterMap (P.filterNotByte w) xs)
 -- > partition p bs == (filter p xs, filter (not . p) xs)
 --
 partition :: (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
-partition f p = (filter f p, filter (not . f) p)
---TODO: use a better implementation
+partition _ Empty = (Empty, Empty)
+partition p (Chunk x xs) = (chunk t ts, chunk f fs)
+  where
+    (t,   f) = S.partition p x
+    (ts, fs) = partition   p xs
 
 -- ---------------------------------------------------------------------
 -- Searching for substrings



More information about the ghc-commits mailing list