From 6b8d0639c3ce4eb2e248170b4bd0c1f926d2726f Mon Sep 17 00:00:00 2001 From: iphydf Date: Wed, 9 Mar 2022 18:49:34 +0000 Subject: [PATCH] perf: Improve performance for large bracketed pastes. The current algorithm has polynomial time complexity. The new algorithm runs in linear time and is generally much more efficient because it operates on packed byte strings instead of linked lists of Char. Some timing: * 100KB: 1 second * 200KB: 2.5 seconds * 300KB: 4 seconds * 400KB: 7 seconds * 500KB: 12 seconds * 600KB: 16 seconds * 700KB: 22 seconds As we can see, it's still `O(n^2)` overall, probably because of the calls to `bracketedPasteFinished`. I'll investigate that next. The constant factor overall is much lower now: ``` Before: 2.866E-6n^3 - 1.784E-4n^2 + 0.114n - 2.622 After: -1.389E-8n^3 + 5.53E-5n^2 - 1.604E-3n + 0.273 ``` --- src/Graphics/Vty/Input/Paste.hs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/Graphics/Vty/Input/Paste.hs b/src/Graphics/Vty/Input/Paste.hs index a6af9c8..0b97961 100644 --- a/src/Graphics/Vty/Input/Paste.hs +++ b/src/Graphics/Vty/Input/Paste.hs @@ -34,16 +34,9 @@ bracketedPasteFinished = isInfixOf bracketedPasteEnd -- 'True'. parseBracketedPaste :: String -> KClass parseBracketedPaste s = - let (p, rest) = takeUntil (drop (length bracketedPasteStart) s) bracketedPasteEnd - rest' = if bracketedPasteEnd `isPrefixOf` rest - then drop (length bracketedPasteEnd) rest - else rest - in Valid (EvPaste $ BS8.pack p) rest' - -takeUntil :: (Eq a) => [a] -> [a] -> ([a],[a]) -takeUntil [] _ = ([], []) -takeUntil cs sub - | length cs < length sub = (cs, []) - | take (length sub) cs == sub = ([], drop (length sub) cs) - | otherwise = let (pre, suf) = takeUntil (tail cs) sub - in (head cs:pre, suf) + Valid (EvPaste p) (BS8.unpack $ BS8.drop (BS8.length end) rest') + where + start = BS8.pack bracketedPasteStart + end = BS8.pack bracketedPasteEnd + (_, rest ) = BS8.breakSubstring start . BS8.pack $ s + (p, rest') = BS8.breakSubstring end . BS8.drop (BS8.length start) $ rest