Skip to content

Commit

Permalink
Merge pull request #47 from Qqwy/improved_protocol_api
Browse files Browse the repository at this point in the history
Improved protocol api
  • Loading branch information
Qqwy authored Sep 7, 2021
2 parents 6862062 + cf262fa commit 9788fbf
Show file tree
Hide file tree
Showing 348 changed files with 70,026 additions and 6,617 deletions.
26 changes: 23 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@ jobs:
name: OTP ${{matrix.otp}} / Elixir ${{matrix.elixir}}
strategy:
matrix:
otp: ['22.x', '23.x', '24.x']
elixir: ['1.7.x', '1.8.x', '1.9.x', '1.10.x', '1.11.x', '1.12.x']
otp: ['24.x', '23.x', '22.x']
elixir: ['1.12.x', '1.11.x', '1.10.x', '1.9.x', '1.8.x', '1.7.x']
exclude:
- otp: '24.x'
elixir: '1.7.x'
- otp: '24.x'
elixir: '1.8.x'
- otp: '24.x'
elixir: '1.9.x'
env:
MIX_ENV: test
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand All @@ -19,6 +26,19 @@ jobs:
with:
otp-version: ${{matrix.otp}}
elixir-version: ${{matrix.elixir}}
- run: mix deps.get
- uses: actions/cache@v2
id: mix-cache
with:
path: |
deps
_build
key: ${{ runner.os }}-${{ matrix.otp}}-${{ matrix.elixir }}-mix-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.otp}}-${{ matrix.elixir }}-mix-
- if: steps.mix-cache.outputs.cache-hit != 'true'
run: |
mix deps.get
mix deps.compile
- run: mix compile
- run: mix test
- run: mix coveralls.github
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,10 @@ The linear time many operations on lists take, means that the operation becomes

## Implementing a new Array type

To add array-functionality to a custom datastructure, two things are required:

- Add an implementation for the `Arrays.Protocol` protocol.
- Add the `Arrays.Behaviour` to your datatype's module (`@behaviour Arrays.Behaviour`), and implement a sensible definition for `c:Arrays.Behaviour.empty/1`.
To add array-functionality to a custom datastructure, you'll need to implement the `Arrays.Protocol`.

Besides these, you probably want to implement the above-mentioned protocols as well.
You can look at the source code of `Arrays.CommonProtocolImplementations` for some hints as to how those protocols can be easily implemented on top of the calls that the `Arrays.Protocol` protocol itself already provides.
You can look at the source code of `Arrays.CommonProtocolImplementations` for some hints as to how those protocols can be easily implemented, as many functions can be defined as simple wrappers on top of the functions that `Arrays.Protocol` itself already provides.


----
Expand Down Expand Up @@ -336,6 +333,10 @@ From below benchmarks, we know (caveat emptor):


### [Append a single element](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/append.md)

![append](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/append_graph.png)
![append_focus](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/append_graph_focus.png)

Appending a single element is very fast on arrays, even as sizes grow.
MapArray and ErlangArray perform similarly.

Expand All @@ -347,6 +348,8 @@ As doing this is built-in, it will always be faster than our arrays.
Thus, it serves as a 'maxline'.

### [Random element access](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/random_access.md)
![random_read](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/random_element_read_graph.png)

Accessing a random element is very fast on arrays, even as sizes grow.

Arrays start beating lists significantly once the collection has more than 256 elements.
Expand All @@ -356,6 +359,7 @@ MapArray and ErlangArray seem to perform similarly < 8192 elements.
For larger sizes, ErlangArray seems to be a factor ~2 slower than MapArray again.

### [Random element update](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/random_update.md)
![random_update](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/random_element_update_graph.png)

Arrays start beating lists once the collection has more than 128 elements.

Expand All @@ -367,6 +371,10 @@ This warrants more investigation. Maybe `Access` has some overhead for its calls
or maybe the implementations of `get_and_update_in` could be further optimized.

### [Concatenate two equally-large collections](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/concat.md)
![concat](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/concat_graph.png)
![concat_focus](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/concat_graph_focus.png)
![concat_focus_log](https://github.com/Qqwy/elixir-arrays/blob/master/benchmark_runs/concat_graph_focus_log.png)

Strangely, concatenation of large collections is very fast on lists.
Probably because all of it happens in a single built-in function?

Expand Down
1 change: 1 addition & 0 deletions benchmark_runs/.~lock.concat_graph.ods#
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
,qqwy,Quinn,07.09.2021 10:50,file:///home/qqwy/.config/libreoffice/4;
1 change: 1 addition & 0 deletions benchmark_runs/.~lock.random_access_graph.ods#
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
,qqwy,Quinn,07.09.2021 10:46,file:///home/qqwy/.config/libreoffice/4;
1 change: 1 addition & 0 deletions benchmark_runs/.~lock.random_update_graph.ods#
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
,qqwy,Quinn,07.09.2021 10:46,file:///home/qqwy/.config/libreoffice/4;
65 changes: 65 additions & 0 deletions benchmark_runs/append.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
Name,Input,Iterations per Second,Standard Deviation Iterations Per Second,Run Time Average,Run Time Median,Run Time Minimum,Run Time Maximum,Run Time Standard Deviation,Run Time Standard Deviation Ratio,Run Time Sample Size,Memory Usage Average,Memory Usage Median,Memory Usage Minimum,Memory Usage Maximum,Memory Usage Standard Deviation,Memory Usage Standard Deviation Ratio,Memory Usage Sample Size
"[val | list] (list, backwards)",0000000032 elements,21324511.404205546,464432513.72927874,46.89439214081048,28.0,8.0,89075.0,1021.3261166428372,21.779280421763143,14658,16.0,16.0,16,16,0.0,0.0,3033
Arrays.append/2 (ErlangArray),0000000032 elements,4319847.974645436,22660523.129364587,231.48962784554425,156.0,128.0,40129.0,1214.3196003170715,5.245676066001956,12871,272.0,272.0,272,272,0.0,0.0,3264
list ++ [val] (list),0000000032 elements,2572230.4032369964,22904660.251998674,388.7676620032018,121.0,63.0,91290.0,3461.817107807023,8.90459121514719,14367,528.0,528.0,528,528,0.0,0.0,3147
Arrays.append/2 (MapArray),0000000032 elements,392203.95466099505,486957.38398359687,2549.6938215841265,2097.0,1884.0,55901.0,3165.680046217094,1.241592233317746,12398,920.0,920.0,920,920,0.0,0.0,3099
"[val | list] (list, backwards)",0000000064 elements,16669471.058048373,328483598.2623873,59.98990588949605,30.0,9.0,84381.0,1182.143097245387,19.70570014600364,13176,16.0,16.0,16,16,0.0,0.0,3193
Arrays.append/2 (MapArray),0000000064 elements,4921377.127631686,25102935.072327822,203.19515738498788,152.0,124.0,37355.0,1036.4568108807869,5.100794842846784,10325,224.0,224.0,224,224,0.0,0.0,3419
Arrays.append/2 (ErlangArray),0000000064 elements,3808378.3590531494,24203217.468550976,262.5789524359715,159.0,126.0,52892.0,1668.7563286259676,6.355255488472121,10386,272.0,272.0,272,272,0.0,0.0,3461
list ++ [val] (list),0000000064 elements,1969565.75226758,10112260.14511853,507.7261314321141,212.0,99.0,57971.0,2606.797319462454,5.13425872351618,12904,448.0,448.0,448,448,0.0,0.0,2953
"[val | list] (list, backwards)",0000000128 elements,24040558.579134602,264585207.33038744,41.59637126185266,33.0,12.0,42304.0,457.8006986934675,11.005784514509056,10968,16.0,16.0,16,16,0.0,0.0,3346
Arrays.append/2 (MapArray),0000000128 elements,3476568.7539689615,16225336.21020594,287.639932004327,188.0,141.0,37706.0,1342.4312690272338,4.667054604250982,6471,264.0,264.0,264,264,0.0,0.0,3719
Arrays.append/2 (ErlangArray),0000000128 elements,3448954.330764402,13249918.636869084,289.9429520072442,202.0,164.0,31045.0,1113.8797893500002,3.8417205234296232,6626,368.0,368.0,368,368,0.0,0.0,3873
list ++ [val] (list),0000000128 elements,1095084.3378463292,4244099.733652661,913.1716758607571,390.0,255.0,71136.0,3539.080536866966,3.875591666299793,10514,560.0,560.0,560,560,0.0,0.0,2835
"[val | list] (list, backwards)",0000000256 elements,20298010.740488615,181971274.6137198,49.26591146221494,36.0,15.0,25605.0,441.66794561318255,8.96498070378592,6709,16.0,16.0,16,16,0.0,0.0,3713
Arrays.append/2 (ErlangArray),0000000256 elements,4240693.133235202,4208077.821678177,235.81050752359093,221.0,170.0,12898.0,233.99688108808544,0.9923089668286981,3921,368.0,368.0,368,368,0.0,0.0,3222
Arrays.append/2 (MapArray),0000000256 elements,3850907.2205541143,5959117.366682821,259.67906852248393,238.0,178.0,16136.0,401.84246422163494,1.5474580469963524,3736,328.0,328.0,328,328,0.0,0.0,2261
list ++ [val] (list),0000000256 elements,581700.1329183477,1514059.034424765,1719.0987992096063,750.0,602.0,63637.0,4474.499696181817,2.6028170680120697,6579,384.0,384.0,384,384,0.0,0.0,3509
"[val | list] (list, backwards)",0000000512 elements,18153026.91982996,8553710.623033091,55.08723170060539,52.0,16.0,482.0,25.957116742675293,0.47120023899095353,3634,16.0,16.0,16,16,0.0,0.0,3051
Arrays.append/2 (ErlangArray),0000000512 elements,3337665.002393817,4666306.9843836455,299.6106557377049,232.0,181.0,13981.0,418.87825604483925,1.3980752954646163,1952,368.0,368.0,368,368,0.0,0.0,1610
Arrays.append/2 (MapArray),0000000512 elements,3155358.7541234805,9936637.047329342,316.9211737629459,243.0,175.0,25507.0,998.0261902646241,3.149130676295988,1738,336.0,336.0,336,336,0.0,0.0,1332
list ++ [val] (list),0000000512 elements,477571.2000849495,470887.16876417655,2093.928611738149,1475.0,1409.0,3.15e4,2064.622228895484,0.9860041155756796,3544,4192.0,4192.0,4192,4192,0.0,0.0,2837
"[val | list] (list, backwards)",0000001024 elements,10032032.976583647,76410416.7175447,99.68069306930693,64.0,30.0,22523.0,759.2322826188733,7.616643296119412,1616,16.0,16.0,16,16,0.0,0.0,1572
Arrays.append/2 (ErlangArray),0000001024 elements,2802278.574053657,2428584.558137743,356.8524590163934,291.0,229.0,2204.0,309.2648887676578,0.8666463715006949,915,464.0,464.0,464,464,0.0,0.0,925
Arrays.append/2 (MapArray),0000001024 elements,874865.819866149,2460095.1024283534,1143.0324254215304,282.0,205.0,14560.0,3214.171142411906,2.811968471696309,771,368.0,368.0,368,368,0.0,0.0,669
list ++ [val] (list),0000001024 elements,134602.17284155925,134143.45617942288,7429.300574345883,2943.0,2815.0,55916.0,7403.981934315582,0.9965920560385282,1567,3904.0,3904.0,3904,3904,0.0,0.0,1449
"[val | list] (list, backwards)",0000002048 elements,12986767.127955627,4722771.4454810545,77.00145772594752,73.0,28.0,243.0,28.002372124290854,0.36366028580852144,686,16.0,16.0,16,16,0.0,0.0,671
Arrays.append/2 (MapArray),0000002048 elements,1958556.935250108,7106200.485620734,510.58,310.0,231.0,18352.0,1852.5291650430893,3.628283843948234,350,408.0,408.0,408,408,0.0,0.0,306
Arrays.append/2 (ErlangArray),0000002048 elements,1230874.2801182356,1231364.7623930203,812.4306569343066,300.0,236.0,2656.0,812.7543966071185,1.000398482836718,411,464.0,464.0,464,464,0.0,0.0,386
list ++ [val] (list),0000002048 elements,68937.06230864067,55173.19428535986,14505.985119047618,5845.5,5649.0,88660.0,11609.742400836789,0.8003415352737532,672,320.0,320.0,320,320,0.0,0.0,634
"[val | list] (list, backwards)",0000004096 elements,10236389.90501368,7426148.9855582295,97.69069069069069,90.0,32.0,1054.0,70.87123783901879,0.7254656235711554,333,16.0,16.0,16,16,0.0,0.0,310
Arrays.append/2 (ErlangArray),0000004096 elements,2349558.1427970263,2944039.0327796335,425.6119402985075,316.0,242.0,3229.0,533.299492458709,1.253018165055881,201,464.0,464.0,464,464,0.0,0.0,194
Arrays.append/2 (MapArray),0000004096 elements,523349.19422270614,2246909.732963168,1910.7701149425288,350.5,272.0,47219.0,8203.56277627617,4.293327968719519,174,400.0,400.0,400,400,0.0,0.0,151
list ++ [val] (list),0000004096 elements,32549.286129056618,18313.561861630296,30722.64,24342.0,11349.0,98742.0,17285.815915032617,0.5626409681925973,325,21728.0,21728.0,21728,21728,0.0,0.0,296
"[val | list] (list, backwards)",0000008192 elements,4448865.677415789,28607485.84739877,224.77639751552795,92.0,38.0,18375.0,1445.3768841341832,6.430287610754746,161,16.0,16.0,16,16,0.0,0.0,144
Arrays.append/2 (ErlangArray),0000008192 elements,2350411.3219813467,800956.0527475651,425.4574468085106,389.5,296.0,1499.0,144.98429020522997,0.34077271720780183,94,464.0,464.0,464,464,0.0,0.0,91
Arrays.append/2 (MapArray),0000008192 elements,1834073.0006340006,824074.7405652121,545.2345679012345,505.0,391.0,2565.0,244.98154377447185,0.44931403509039536,81,488.0,488.0,488,488,0.0,0.0,68
list ++ [val] (list),0000008192 elements,15044.255504352916,9934.188464103014,66470.5541401274,26440.0,22908.0,154997.0,43892.568292949276,0.6603310121413883,157,10384.0,10384.0,10384,10384,0.0,0.0,141
"[val | list] (list, backwards)",0000016384 elements,2634252.8130056825,1024361.2387552931,379.6142857142857,333.5,177.0,876.0,147.6176310958551,0.38886215996349144,70,16.0,16.0,16,16,0.0,0.0,60
Arrays.append/2 (ErlangArray),0000016384 elements,1012555.690562981,99971.52883369377,987.6,969.0,806.0,1253.0,97.50760654089163,0.09873188187615596,40,560.0,560.0,560,560,0.0,0.0,40
Arrays.append/2 (MapArray),0000016384 elements,879529.5773232146,115858.46480859924,1136.9714285714285,1106.0,915.0,1541.0,149.77070429675564,0.13172776424552565,35,520.0,520.0,520,520,0.0,0.0,33
list ++ [val] (list),0000016384 elements,5113.725494914625,3647.3751174699873,195552.14705882352,308527.5,46164.0,401179.0,139477.96690680453,0.7132520353501848,68,108832.0,108832.0,108832,108832,0.0,0.0,58
"[val | list] (list, backwards)",0000032768 elements,1386797.686029004,110840.04571982603,721.0857142857143,707.0,606.0,878.0,57.63290085102608,0.07992517353934198,35,16.0,16.0,16,16,0.0,0.0,27
Arrays.append/2 (ErlangArray),0000032768 elements,897142.6008163997,51728.83664963716,1114.65,1114.0,996.0,1280.0,64.27021492352262,0.05765954777151806,20,560.0,560.0,560,560,0.0,0.0,19
Arrays.append/2 (MapArray),0000032768 elements,852636.0665056133,69580.41076181202,1172.8333333333333,1155.0,1048.0,1469.0,95.71050099127055,0.08160622508847852,18,552.0,552.0,552,552,0.0,0.0,17
list ++ [val] (list),0000032768 elements,2796.0706226434104,1926.7910445977664,357644.75757575757,429914.0,91830.0,657264.0,246455.40440349324,0.6891067160443088,33,76224.0,76224.0,76224,76224,0.0,0.0,27
"[val | list] (list, backwards)",0000065536 elements,1186474.1941862763,64459.12817227139,842.8333333333334,835.0,783.0,922.0,45.78970375201143,0.054328301861196075,12,16.0,16.0,16,16,0.0,0.0,12
Arrays.append/2 (ErlangArray),0000065536 elements,796733.3930883378,38705.38092021183,1255.125,1257.0,1170.0,1339.0,60.974087001891924,0.048580091227480866,8,560.0,560.0,560,560,0.0,0.0,8
Arrays.append/2 (MapArray),0000065536 elements,693687.4442572589,97753.90787300488,1441.5714285714287,1405.0,1232.0,1754.0,203.14515101511134,0.14091924062092748,7,592.0,592.0,592,592,0.0,0.0,7
list ++ [val] (list),0000065536 elements,2668.210077962875,1743.7930916033697,374783.0833333333,248663.5,232638.0,908477.0,244937.29221855148,0.6535441515664767,12,524224.0,524224.0,524224,524224,0.0,0.0,12
"[val | list] (list, backwards)",0000131072 elements,1130198.9150090415,62898.28127538339,884.8,863.0,834.0,940.0,49.24124287627192,0.05565239927245923,5,16.0,16.0,16,16,0.0,0.0,5
Arrays.append/2 (ErlangArray),0000131072 elements,758006.4430547659,29159.736645033194,1319.25,1314.0,1273.0,1376.0,50.750205254100536,0.038468982568960045,4,656.0,656.0,656,656,0.0,0.0,4
Arrays.append/2 (MapArray),0000131072 elements,692201.199815413,55527.49623575177,1444.6666666666667,1485.0,1314.0,1535.0,115.88931500933697,0.0802187228952494,3,648.0,648.0,648,648,0.0,0.0,3
list ++ [val] (list),0000131072 elements,1096.3686078969238,951.0143545262873,912102.0,557252.0,533292.0,2326994.0,791177.4275040965,0.8674220947921357,5,447952.0,447952.0,447952,447952,0.0,0.0,5
Arrays.append/2 (ErlangArray),0000262144 elements,726480.2034144569,130244.08158591978,1376.5,1376.5,1202.0,1551.0,246.7802666341051,0.1792809783030186,2,656.0,656.0,656,656,0.0,0.0,2
Arrays.append/2 (MapArray),0000262144 elements,696864.1114982578,46013.57728222868,1435.0,1435.0,1368.0,1502.0,94.75230867899737,0.06602948339999816,2,624.0,624.0,624,624,0,0.0,1
"[val | list] (list, backwards)",0000262144 elements,652528.5481239804,386287.5331439647,1532.5,1532.5,891.0,2174.0,907.2180002623405,0.591985644543126,2,16.0,16.0,16,16,0.0,0.0,2
list ++ [val] (list),0000262144 elements,322.54240827901856,3.505344207089041,3100367.5,3100367.5,3076542.0,3124193.0,33694.34523032018,0.010867855255972132,2,2469504.0,2469504.0,2469504,2469504,0.0,0.0,2
"[val | list] (list, backwards)",0000524288 elements,1243781.094527363,0.0,804.0,804.0,804.0,804.0,0,0.0,1,16.0,16.0,16,16,0,0.0,1
Arrays.append/2 (ErlangArray),0000524288 elements,839630.5625524769,0.0,1191.0,1191.0,1191.0,1191.0,0,0.0,1,656.0,656.0,656,656,0,0.0,1
Arrays.append/2 (MapArray),0000524288 elements,514933.0587023687,0.0,1942.0,1942.0,1942.0,1942.0,0,0.0,1,648.0,648.0,648,648,0,0.0,1
list ++ [val] (list),0000524288 elements,436.6821761619567,0.0,2289995.0,2289995.0,2289995.0,2289995.0,0,0.0,1,1207456.0,1207456.0,1207456,1207456,0,0.0,1
"[val | list] (list, backwards)",0001048576 elements,1191895.1132300359,0.0,839.0,839.0,839.0,839.0,0,0.0,1,16.0,16.0,16,16,0,0.0,1
Arrays.append/2 (ErlangArray),0001048576 elements,730460.1899196494,0.0,1369.0,1369.0,1369.0,1369.0,0,0.0,1,752.0,752.0,752,752,0,0.0,1
Arrays.append/2 (MapArray),0001048576 elements,462534.69010175765,0.0,2162.0,2162.0,2162.0,2162.0,0,0.0,1,704.0,704.0,704,704,0,0.0,1
list ++ [val] (list),0001048576 elements,195.64329766169087,0.0,5111343.0,5111343.0,5111343.0,5111343.0,0,0.0,1,3121584.0,3121584.0,3121584,3121584,0,0.0,1
Loading

0 comments on commit 9788fbf

Please sign in to comment.