Skip to content

Optimization potential #121

@sjakobi

Description

@sjakobi

In #116 (comment) I shared a profile from a prettyprinter-heavy dhall task. Multiple functions from prettyprinter and prettyprinter-ansi-terminal show up:

COST CENTRE               MODULE                                             SRC                                                                         %time %alloc
layoutWadlerLeijen        Data.Text.Prettyprint.Doc.Internal                 src/Data/Text/Prettyprint/Doc/Internal.hs:(1775,1)-(1843,60)                  5.5    3.0
renderLazy                Data.Text.Prettyprint.Doc.Render.Terminal.Internal src/Data/Text/Prettyprint/Doc/Render/Terminal/Internal.hs:(108,1)-(148,60)    3.7    3.7
removeTrailingWhitespace  Data.Text.Prettyprint.Doc.Internal                 src/Data/Text/Prettyprint/Doc/Internal.hs:(1477,1)-(1537,119)                 2.3    1.1
styleToRawText            Data.Text.Prettyprint.Doc.Render.Terminal.Internal src/Data/Text/Prettyprint/Doc/Render/Terminal/Internal.hs:(278,1)-(304,29)    1.8    2.0
layoutSmart               Data.Text.Prettyprint.Doc.Internal                 src/Data/Text/Prettyprint/Doc/Internal.hs:(1741,1)-(1767,59)                  1.6    0.2
changesUponFlattening     Data.Text.Prettyprint.Doc.Internal                 src/Data/Text/Prettyprint/Doc/Internal.hs:(567,1)-(607,21)                    1.5    1.1

The most interesting candidates are IMHO removeTrailingWhitespace and styleToRawText:

removeTrailingWhitespace :: SimpleDocStream ann -> SimpleDocStream ann
removeTrailingWhitespace = go (RecordedWhitespace [] 0)
where
commitWhitespace
:: [Int] -- Withheld lines
-> Int -- Withheld spaces
-> SimpleDocStream ann
-> SimpleDocStream ann
commitWhitespace is0 n0 = commitLines is0 . commitSpaces n0
where
commitLines [] = id
commitLines (i:is) = foldr (\_ f -> SLine 0 . f) (SLine i) is
commitSpaces 0 = id
commitSpaces 1 = SChar ' '
commitSpaces n = SText n (T.replicate n " ")
go :: WhitespaceStrippingState -> SimpleDocStream ann -> SimpleDocStream ann
-- We do not strip whitespace inside annotated documents, since it might
-- actually be relevant there.
go annLevel@(AnnotationLevel annLvl) = \sds -> case sds of
SFail -> SFail
SEmpty -> SEmpty
SChar c rest -> SChar c (go annLevel rest)
SText l text rest -> SText l text (go annLevel rest)
SLine i rest -> SLine i (go annLevel rest)
SAnnPush ann rest -> let !annLvl' = annLvl+1
in SAnnPush ann (go (AnnotationLevel annLvl') rest)
SAnnPop rest
| annLvl > 1 -> let !annLvl' = annLvl-1
in SAnnPop (go (AnnotationLevel annLvl') rest)
| otherwise -> SAnnPop (go (RecordedWhitespace [] 0) rest)
-- Record all spaces/lines encountered, and once proper text starts again,
-- release only the necessary ones.
go (RecordedWhitespace withheldLines withheldSpaces) = \sds -> case sds of
SFail -> SFail
SEmpty -> foldr (\_i sds' -> SLine 0 sds') SEmpty withheldLines
SChar c rest
| c == ' ' -> go (RecordedWhitespace withheldLines (withheldSpaces+1)) rest
| otherwise -> commitWhitespace
withheldLines
withheldSpaces
(SChar c (go (RecordedWhitespace [] 0) rest))
SText textLength text rest ->
let stripped = T.dropWhileEnd (== ' ') text
strippedLength = T.length stripped
trailingLength = textLength - strippedLength
isOnlySpace = strippedLength == 0
in if isOnlySpace
then go (RecordedWhitespace withheldLines (withheldSpaces + textLength)) rest
else commitWhitespace
withheldLines
withheldSpaces
(SText strippedLength
stripped
(go (RecordedWhitespace [] trailingLength) rest))
SLine i rest -> go (RecordedWhitespace (i:withheldLines) 0) rest
SAnnPush ann rest -> commitWhitespace
withheldLines
withheldSpaces
(SAnnPush ann (go (AnnotationLevel 1) rest))
SAnnPop _ -> error "Tried skipping spaces in unannotated data! Please report this as a bug in 'prettyprinter'."

styleToRawText :: AnsiStyle -> Text
styleToRawText = T.pack . ANSI.setSGRCode . stylesToSgrs
where
stylesToSgrs :: AnsiStyle -> [ANSI.SGR]
stylesToSgrs (SetAnsiStyle fg bg b i u) = catMaybes
[ Just ANSI.Reset
, fmap (\(intensity, c) -> ANSI.SetColor ANSI.Foreground (convertIntensity intensity) (convertColor c)) fg
, fmap (\(intensity, c) -> ANSI.SetColor ANSI.Background (convertIntensity intensity) (convertColor c)) bg
, fmap (\_ -> ANSI.SetConsoleIntensity ANSI.BoldIntensity) b
, fmap (\_ -> ANSI.SetItalicized True) i
, fmap (\_ -> ANSI.SetUnderlining ANSI.SingleUnderline) u
]
convertIntensity :: Intensity -> ANSI.ColorIntensity
convertIntensity = \i -> case i of
Vivid -> ANSI.Vivid
Dull -> ANSI.Dull
convertColor :: Color -> ANSI.Color
convertColor = \c -> case c of
Black -> ANSI.Black
Red -> ANSI.Red
Green -> ANSI.Green
Yellow -> ANSI.Yellow
Blue -> ANSI.Blue
Magenta -> ANSI.Magenta
Cyan -> ANSI.Cyan
White -> ANSI.White

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions