on master help sign in
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 ```

commit6b8d0639c3ce4eb2e248170b4bd0c1f926d2726f authoriphydf <iphydf@users.noreply.github.com> dateWed 9 Mar 2022, 18:49 (5 years ago) parentb3504fb
1 file changed+6−13
src/Graphics/Vty/Input/Paste.hs+6−13
src/Graphics/Vty/Input/Paste.hs+6−13
@@ -34,16 +34,9 @@ bracketedPasteFinished = isInfixOf bracketedPasteEnd
3434-- 'True'.
3535parseBracketedPaste :: String -> KClass
3636parseBracketedPaste s =
37− let (p, rest) = takeUntil (drop (length bracketedPasteStart) s) bracketedPasteEnd
38− rest' = if bracketedPasteEnd `isPrefixOf` rest
39− then drop (length bracketedPasteEnd) rest
40− else rest
41− in Valid (EvPaste $ BS8.pack p) rest'
42−
43−takeUntil :: (Eq a) => [a] -> [a] -> ([a],[a])
44−takeUntil [] _ = ([], [])
45−takeUntil cs sub
46− | length cs < length sub = (cs, [])
47− | take (length sub) cs == sub = ([], drop (length sub) cs)
48− | otherwise = let (pre, suf) = takeUntil (tail cs) sub
49− in (head cs:pre, suf)
37+ Valid (EvPaste p) (BS8.unpack $ BS8.drop (BS8.length end) rest')
38+ where
39+ start = BS8.pack bracketedPasteStart
40+ end = BS8.pack bracketedPasteEnd
41+ (_, rest ) = BS8.breakSubstring start . BS8.pack $ s
42+ (p, rest') = BS8.breakSubstring end . BS8.drop (BS8.length start) $ rest