mirror of
https://github.com/anoma/juvix.git
synced 2024-12-25 16:45:20 +03:00
87c5f0af44
This PR: * Adds a new implementation of {decode, encode}ByteString functions, used by anomaEncode and anomaDecode in the Core evaluator * Adds property tests for roundtripping and benchmarks for the new functions. The old implementation used [bitvec](https://hackage.haskell.org/package/bitvec) to manipulate the ByteString. This was far too slow. The new implementation uses bit operations directly on the input integer and ByteArray. It's now possible to run [anoma-app-patterns:`Tests/Swap.juvix`](https://github.com/anoma/anoma-app-patterns/blob/feature/tests/Tests/Swap.juvix) to completion. For encoding, if the size of the output integer exceeds 64 bits (and therefore a BigInt must be used) then the new implementation has quadratic time complexity in the number of input bytes if an implementation of `ByteString -> Integer` is used as follows: ``` byteStringToIntegerLE :: ByteString -> Integer byteStringToIntegerLE = BS.foldr (\b acc -> acc `shiftL` 8 .|. fromIntegral b) 0 ``` ``` byteStringToInteger' :: ByteString -> Integer byteStringToInteger' = BS.foldl' (\acc b -> acc `shiftL` 8 .|. fromIntegral b) 0 ``` I think this is because `shiftL` is expensive for large Integers. To mitigate this I'm splitting the input ByteString into 1024 byte chunks and processing each separately. Using this we get 100x speed up at ~0.25Mb input over the non-chunked approach and linear time-complexity thereafter. ## Benchmarks The benchmarks for encoding and decoding 250000 bytes: ``` ByteString Encoding to/from integer encode bytes to integer: OK 59.1 ms ± 5.3 ms decode bytes from integer: OK 338 ms ± 16 ms ``` The previous implementation would never complete for this input. Benchmarks for encoding and decoding 2 * 250000 bytes: ``` ByteString Encoding to/from integer encode bytes to integer: OK 121 ms ± 8.3 ms decode bytes from integer: OK 651 ms ± 27 ms ``` Benchmarks for encoding and decoding 4 * 250000 bytes: ``` ByteString Encoding to/from integer encode bytes to integer: OK 249 ms ± 17 ms decode bytes from integer: OK 1.317 s ± 16 ms ``` --------- Co-authored-by: Lukasz Czajka <lukasz@heliax.dev>
11 lines
324 B
Haskell
11 lines
324 B
Haskell
module Nockma where
|
|
|
|
import Base
|
|
import Nockma.Compile qualified as Compile
|
|
import Nockma.Encoding qualified as Encoding
|
|
import Nockma.Eval qualified as Eval
|
|
import Nockma.Parse qualified as Parse
|
|
|
|
allTests :: TestTree
|
|
allTests = testGroup "Nockma tests" [Parse.allTests, Eval.allTests, Compile.allTests, Encoding.allTests]
|