Exported extendLeft and added test for it. Added performance metrics and TODOs to README
This commit is contained in:
parent
b24d00af83
commit
6f450cb5ca
119
README.md
119
README.md
|
@ -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.
|
||||
|
|
|
@ -34,4 +34,5 @@ export insert
|
|||
export extend
|
||||
export reversedPairs
|
||||
export clear
|
||||
export clearPop
|
||||
export clearPop
|
||||
export extendLeft
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue