on master help sign in
Optimize bytes_for_range - replace with direct ptr access when possible

Ignore-this: c082249814e88500de8243138bcb2fd darcs-hash:20100114022236-f0a0d-d7f114a7c6356f4865ae84ace55d5e377b769e8b.gz

commit409044c764f4d01054ce81b57c061c786ebb95e5 authorcoreyoconnor <coreyoconnor@gmail.com> dateWed 13 Jan 2010, 18:22 (17 years ago) parent04c79d2
4 files changed+45−35
src/Data/Terminfo/Eval.hs+9−11 src/Data/Terminfo/Parse.hs+24−17 test/Verify/Data/Terminfo/Parse.hs+12−5 test/verify_parse_terminfo_caps.hs−2
src/Data/Terminfo/Eval.hs+9−11
@@ -12,10 +12,10 @@
1212 -}
1313module Data.Terminfo.Eval ( cap_expression_required_bytes
1414 , serialize_cap_expression
15− , bytes_for_range
1615 )
1716 where
1817
18+import Data.ByteString.Internal ( memcpy )
1919import Data.Marshalling
2020import Data.Terminfo.Parse
2121
@@ -29,6 +29,8 @@ import Data.Array.Unboxed
2929import Data.Bits ( (.|.), (.&.), xor )
3030import Data.List
3131
32+import Foreign.Ptr
33+
3234import GHC.Prim
3335import GHC.Word
3436
@@ -58,14 +60,9 @@ apply_param_op :: [CapParam] -> ParamOp -> [CapParam]
5860apply_param_op params IncFirstTwo = map (+ 1) params
5961
6062-- | range is 0-based offset into cap_bytes and count
61−--
62−-- todo: The returned list is not assured to have a length st. length == count
63−bytes_for_range :: CapExpression -> Word8 -> Word8 -> [Word8]
64−bytes_for_range cap !offset !count
65− = take (fromEnum count)
66− $ drop (fromEnum offset)
67− $ elems
68− $ cap_bytes cap
63+{-# INLINE ptr_at_offset #-}
64+ptr_at_offset :: CapExpression -> Word8 -> Ptr Word8
65+ptr_at_offset cap !offset = fst ( cap_bytes cap ) `plusPtr` ( fromEnum offset )
6966
7067cap_expression_required_bytes :: CapExpression -> [CapParam] -> Word
7168cap_expression_required_bytes cap params =
@@ -163,8 +160,9 @@ serialize_cap_ops out_ptr ops = foldM serialize_cap_op out_ptr ops
163160serialize_cap_op :: MonadIO m => OutputBuffer -> CapOp -> EvalT m OutputBuffer
164161serialize_cap_op out_ptr (Bytes offset c) = do
165162 (cap, _) <- ask
166− let out_bytes = bytes_for_range cap offset c
167− serialize_bytes out_bytes out_ptr
163+ let src_ptr = ptr_at_offset cap offset
164+ liftIO $! memcpy out_ptr src_ptr ( toEnum $! fromEnum c )
165+ return $! out_ptr `plusPtr` ( fromEnum c)
168166serialize_cap_op out_ptr DecOut = do
169167 p <- pop
170168 let out_str = show p
src/Data/Terminfo/Parse.hs+24−17
@@ -9,6 +9,7 @@ module Data.Terminfo.Parse ( module Data.Terminfo.Parse
99 )
1010 where
1111
12+import Control.Applicative ( Applicative(..), pure, (<*>) )
1213import Control.Monad ( liftM )
1314import Control.Monad.Trans
1415import Control.Parallel.Strategies
@@ -17,11 +18,14 @@ import Data.Array.Unboxed
1718import Data.Monoid
1819import Data.Word
1920
21+import Foreign.Marshal.Array
22+import Foreign.Ptr
23+
2024import Text.ParserCombinators.Parsec
2125
2226type BytesLength = Word8
2327type BytesOffset = Word8
24−type CapBytes = UArray Word8 Word8
28+type CapBytes = ( Ptr Word8, Word )
2529
2630data CapExpression = CapExpression
2731 { cap_ops :: !CapOps
@@ -67,7 +71,11 @@ data ParamOp =
6771 IncFirstTwo
6872 deriving ( Show )
6973
70−parse_cap_expression :: MonadIO m => String -> m ( Either ParseError CapExpression )
74+parse_cap_expression :: ( Applicative m
75+ , MonadIO m
76+ )
77+ => String
78+ -> m ( Either ParseError CapExpression )
7179parse_cap_expression cap_string =
7280 let v = runParser cap_expression_parser
7381 initial_build_state
@@ -75,21 +83,20 @@ parse_cap_expression cap_string =
7583 cap_string
7684 in case v of
7785 Left e -> return $ Left e
78− Right build_results ->
79− return
80− $! Right
81− $! ( CapExpression
82− { cap_ops = out_cap_ops build_results
83− -- The cap bytes are the lower 8 bits of the input string's characters.
84− -- \todo Verify the input string actually contains an 8bit byte per character.
85− , cap_bytes = listArray (0, toEnum $ length cap_string - 1)
86− $ map (toEnum . fromEnum) cap_string
87− , source_string = cap_string
88− , param_count = out_param_count build_results
89− , param_ops = out_param_ops build_results
90− }
91− `using` rdeepseq
92− )
86+ Right build_results -> pure Right <*> construct_cap_expression cap_string build_results
87+
88+construct_cap_expression cap_string build_results = do
89+ byte_array <- liftIO $ newArray (map ( toEnum . fromEnum ) cap_string )
90+ let expr = CapExpression
91+ { cap_ops = out_cap_ops build_results
92+ -- The cap bytes are the lower 8 bits of the input string's characters.
93+ -- \todo Verify the input string actually contains an 8bit byte per character.
94+ , cap_bytes = ( byte_array, toEnum $! length cap_string )
95+ , source_string = cap_string
96+ , param_count = out_param_count build_results
97+ , param_ops = out_param_ops build_results
98+ }
99+ return $! expr `using` rdeepseq
93100
94101type CapParser a = GenParser Char BuildState a
95102
test/Verify/Data/Terminfo/Parse.hs+12−5
@@ -16,11 +16,11 @@ import Numeric
1616instance Show CapExpression where
1717 show c
1818 = "CapExpression { " ++ show (cap_ops c) ++ " }"
19− ++ " <- [" ++ hex_dump (cap_bytes c) ++ "]"
19+ ++ " <- [" ++ hex_dump ( map ( toEnum . fromEnum ) $! source_string c ) ++ "]"
2020 ++ " <= " ++ show (source_string c)
2121
22−hex_dump :: CapBytes -> String
23−hex_dump bytes = foldr (\b s -> showHex b s) "" $ elems bytes
22+hex_dump :: [Word8] -> String
23+hex_dump bytes = foldr (\b s -> showHex b s) "" bytes
2424
2525data NonParamCapString = NonParamCapString String
2626 deriving Show
@@ -95,20 +95,27 @@ is_bytes_op :: CapOp -> Bool
9595is_bytes_op (Bytes {}) = True
9696-- is_bytes_op _ = False
9797
98+bytes_for_range cap offset c
99+ = take (fromEnum c)
100+ $ drop (fromEnum offset)
101+ $ ( map ( toEnum . fromEnum ) $! source_string cap )
102+
98103collect_bytes :: CapExpression -> [Word8]
99104collect_bytes e = concat [ bytes
100105 | Bytes offset c <- cap_ops e
101106 , let bytes = bytes_for_range e offset c
102107 ]
108+
103109
110+verify_bytes_equal :: [Word8] -> [Word8] -> Result
104111verify_bytes_equal out_bytes expected_bytes
105112 = if out_bytes == expected_bytes
106113 then succeeded
107114 else failed
108115 { reason = "out_bytes ["
109− ++ hex_dump ( listArray (0, toEnum $ length out_bytes - 1) out_bytes )
116+ ++ hex_dump out_bytes
110117 ++ "] /= expected_bytes ["
111− ++ hex_dump ( listArray (0, toEnum $ length expected_bytes - 1) expected_bytes )
118+ ++ hex_dump expected_bytes
112119 ++ "]"
113120 }
114121
test/verify_parse_terminfo_caps.hs−2
@@ -4,8 +4,6 @@ module Main where
44
55import Prelude hiding ( catch )
66
7−import Data.Terminfo.Eval ( bytes_for_range )
8−
97import qualified System.Console.Terminfo as Terminfo
108
119import Verify.Data.Terminfo.Parse