Exported extendLeft and added test for it. Added performance metrics and TODOs to README

This commit is contained in:
Nocturn9x 2022-03-16 10:11:38 +01:00
parent b24d00af83
commit 6f450cb5ca
3 changed files with 128 additions and 2 deletions

119
README.md
View File

@ -102,3 +102,122 @@ some benchmarks as well as the test suite used to validate the behavior of the q
3. The deque in that module is a value type
4. I was bored during my programming class
## Performance metrics
------------------------------------------
To outline just how much faster a deque is than a regular dynamic array when doing insertion and popping
near the ends, here are some performance metrics I took on my laptop with an 8-core Ryzen 7 4700U.
Both collections have been filled with 500000 elements and the time taken for each operation has been
recorded. The average, minimum and maximum time taken are shown here, as well as the standard deviation
for each micro-benchmark.
## Appending at the end
### LinkedDeque
Time taken: `0.325591755` seconds. Results:
- min: `0.0`
- max: `0.010444388`
- avg: `3.415999800000153e-07`
- stdev: `1.643969031599315e-05`
### seq
Time taken: `0.283606824` seconds. Results:
- min: `2.499999999239222e-07`
- max: `0.001853333999999984`
- avg: `2.750403260000028e-07`
- stdev: `3.929418946682074e-06`
## Popping the head
### LinkedDeque
Time taken: `0.008184640000000076` seconds. Results:
- min: `2.499999999239222e-07`
- max: `1.186499999994428e-05`
- avg: `2.64712133333553e-07`
- stdev: `9.675646231323721e-08`
### seq
Time taken: `2.3356288` seconds. Results:
- min: `0.0001166700000001519`
- max: `0.002396426000000229`
- avg: `0.0001549421693333322`
- stdev: `8.55174518472766e-05`
## Adding at the left side
### LinkedDeque
Time taken: `0.3028111230000001` seconds. Results:
- min: `2.699999996913505e-07`
- max: `0.01986077199999992`
- avg: `3.19837340000251e-07`
- stdev: `2.808711098829249e-05`
### seq
Time taken: `23.515489255` seconds. Results:
- min: `2.700000001354397e-07`
- max: `0.002371210999999818`
- avg: `4.657242209800181e-05`
- stdev: `3.14827288610087e-05`
## Random access (10000 times)
### LinkedDeque
Time taken: `8.208724628999995` seconds. Results:
- min: `9.920000003660334e-07`
- max: `0.002548661999998814`
- avg: `0.0008192961785821358`
- stdev: `0.0004795569727666707`
### seq
Time taken: `0.00333773400000581` seconds. Results:
- min: `1.599999990276046e-07`
- max: `9.759999997527302e-06`
- avg: `1.632506749111258e-07`
- stdev: `9.612951140246536e-08`
## Popping the tail
### LinkedDeque
Time taken: `0.004907793000000993` seconds. Results:
- min: `1.499999982002009e-07`
- max: '8.515999994074264e-06`
- avg: `1.609196000041869e-07`
- stdev: `9.069790474947947e-08`
### seq
Time taken: `0.004914629999994702` seconds. Results:
- min: `1.499999982002009e-07`
- max: `6.697999999971671e-06`
- avg: `1.62365333385613e-07`
- stdev: `5.410771724203826e-08`
## TODOs
There are many possible implementations for double-ended queues: the current one is based on the usual textbook implementation of
a doubly linked list, but that isn't the best choice for cache locality and has significant memory overhead for each link in
the chain; Other possibilities involve using a list of subarrays to alleviate both of these issues, while some other options
make use of ring buffers or specialized dynamic arrays growing from the center that can be used to allow even fast random accessing
and can be made really efficient using lazy evaluation. The goal of this module is to implement most (possibly all) of these approaches,
because I find them fascinating.

View File

@ -34,4 +34,5 @@ export insert
export extend
export reversedPairs
export clear
export clearPop
export clearPop
export extendLeft

View File

@ -20,7 +20,7 @@ import ../src/nimdeque
when isMainModule:
const size = 1500
const benchSize = 1500000
const benchSize = 500000
echo &"Running tests with queue of size {size}"
var deque = newLinkedDeque[int]()
@ -129,6 +129,12 @@ when isMainModule:
doAssert deque[i] == s[i]
doAssert old + len(s) == deque.len()
echo "\t- Testing extendLeft()"
old = deque.len()
deque.extendLeft(s)
for i in countup(0, 5):
doAssert deque[i] == s[5 - i]
echo "\t- Testing clear()"
deque.clear()
doAssert deque.len() == 0