Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.0.0 #1

Closed
wants to merge 12 commits into from
Closed

1.0.0 #1

wants to merge 12 commits into from

Conversation

safareli
Copy link
Owner

@safareli safareli commented Dec 12, 2017

TODO

@safareli
Copy link
Owner Author

npm run bench:

bench type n mean stddev min max
bind assocR build Eff 100 945.04 ns 10.50 μs 230.00 ns 319.94 μs
bind assocR build Ef 100 548.83 ns 5.81 μs 273.00 ns 201.78 μs
bind assocR run Eff 100 83.45 μs 81.41 μs 57.24 μs 924.19 μs
bind assocR run Ef 100 51.51 μs 22.02 μs 43.43 μs 566.60 μs
bind assocR build Eff 500 352.04 ns 1.33 μs 242.00 ns 46.88 μs
bind assocR build Ef 500 524.96 ns 3.16 μs 282.00 ns 95.86 μs
bind assocR run Eff 500 414.97 μs 298.30 μs 300.30 μs 2.93 ms
bind assocR run Ef 500 238.37 μs 47.15 μs 213.71 μs 1.06 ms
bind assocR build Eff 1000 391.90 ns 1.58 μs 283.00 ns 58.36 μs
bind assocR build Ef 1000 514.28 ns 2.77 μs 281.00 ns 71.48 μs
bind assocR run Eff 1000 881.69 μs 554.14 μs 600.23 μs 4.13 ms
bind assocR run Ef 1000 479.24 μs 105.77 μs 424.65 μs 1.99 ms
bind assocR build Eff 2000 369.02 ns 1.57 μs 242.00 ns 50.18 μs
bind assocR build Ef 2000 533.73 ns 3.87 μs 280.00 ns 107.84 μs
bind assocR run Eff 2000 2.02 ms 1.05 ms 1.20 ms 7.28 ms
bind assocR run Ef 2000 1.00 ms 254.26 μs 848.04 μs 3.75 ms
bind assocR build Eff 4000 365.82 ns 1.64 μs 241.00 ns 51.16 μs
bind assocR build Ef 4000 484.45 ns 3.33 μs 276.00 ns 96.11 μs
bind assocR run Eff 4000 4.91 ms 2.43 ms 2.50 ms 22.13 ms
bind assocR run Ef 4000 2.29 ms 869.33 μs 1.69 ms 8.49 ms
bind assocR build Eff 8000 414.06 ns 2.12 μs 240.00 ns 68.76 μs
bind assocR build Ef 8000 515.46 ns 3.27 μs 281.00 ns 109.83 μs
bind assocR run Eff 8000 38.28 ms 12.09 ms 9.59 ms 115.95 ms
bind assocR run Ef 8000 6.56 ms 1.85 ms 4.30 ms 20.08 ms
bind assocR build Eff 10000 355.31 ns 1.97 μs 240.00 ns 76.57 μs
bind assocR build Ef 10000 573.82 ns 3.71 μs 311.00 ns 127.65 μs
bind assocR run Eff 10000 79.64 ms 22.74 ms 36.48 ms 175.16 ms
bind assocR run Ef 10000 7.19 ms 1.71 ms 5.24 ms 18.04 ms
bind assocL build Eff 100 26.71 μs 51.22 μs 18.42 μs 1.07 ms
bind assocL build Ef 100 11.38 μs 6.15 μs 9.26 μs 156.43 μs
bind assocL run Eff 100 23.48 μs 69.28 μs 16.14 μs 1.55 ms
bind assocL run Ef 100 14.85 μs 6.59 μs 13.92 μs 201.76 μs
bind assocL build Eff 500 123.36 μs 103.25 μs 97.92 μs 1.36 ms
bind assocL build Ef 500 53.55 μs 13.99 μs 47.51 μs 298.39 μs
bind assocL run Eff 500 125.17 μs 192.44 μs 84.35 μs 2.31 ms
bind assocL run Ef 500 86.09 μs 15.38 μs 79.21 μs 418.90 μs
bind assocL build Eff 1000 264.39 μs 210.22 μs 195.13 μs 2.62 ms
bind assocL build Ef 1000 105.60 μs 20.97 μs 94.77 μs 324.32 μs
bind assocL run Eff 1000 245.24 μs 305.97 μs 162.13 μs 3.01 ms
bind assocL run Ef 1000 195.82 μs 29.13 μs 183.39 μs 892.48 μs
bind assocL build Eff 2000 575.85 μs 467.32 μs 386.96 μs 2.82 ms
bind assocL build Ef 2000 207.73 μs 32.90 μs 187.73 μs 614.57 μs
bind assocL run Eff 2000 527.22 μs 574.34 μs 317.74 μs 4.84 ms
bind assocL run Ef 2000 501.78 μs 81.22 μs 460.96 μs 1.43 ms
bind assocL build Eff 4000 1.16 ms 688.34 μs 785.20 μs 4.84 ms
bind assocL build Ef 4000 536.46 μs 75.97 μs 482.31 μs 1.47 ms
bind assocL run Eff 4000 1.22 ms 1.07 ms 658.75 μs 8.80 ms
bind assocL run Ef 4000 1.46 ms 182.78 μs 1.34 ms 3.53 ms
bind assocL build Eff 8000 3.16 ms 1.31 ms 1.78 ms 10.66 ms
bind assocL build Ef 8000 1.11 ms 174.88 μs 960.70 μs 2.11 ms
bind assocL run Eff 8000 2.59 ms 1.18 ms 1.69 ms 16.49 ms
bind assocL run Ef 8000 7.75 ms 496.34 μs 7.23 ms 12.62 ms
map build Eff 100 34.77 μs 97.12 μs 21.64 μs 1.90 ms
map build Ef 100 13.59 μs 6.34 μs 11.69 μs 171.24 μs
map run Eff 100 25.82 μs 76.17 μs 17.50 μs 2.16 ms
map run Ef 100 15.89 μs 6.72 μs 14.30 μs 212.64 μs
map build Eff 500 159.03 μs 195.17 μs 111.58 μs 1.72 ms
map build Ef 500 68.44 μs 24.79 μs 60.14 μs 1.02 ms
map run Eff 500 129.92 μs 171.99 μs 89.72 μs 2.01 ms
map run Ef 500 90.90 μs 23.53 μs 82.72 μs 905.56 μs
map build Eff 1000 330.00 μs 343.87 μs 221.16 μs 3.08 ms
map build Ef 1000 129.78 μs 28.88 μs 119.38 μs 1.04 ms
map run Eff 1000 252.79 μs 260.77 μs 173.81 μs 3.16 ms
map run Ef 1000 210.18 μs 39.49 μs 190.60 μs 1.10 ms
map build Eff 2000 718.99 μs 660.78 μs 441.72 μs 3.88 ms
map build Ef 2000 257.94 μs 38.65 μs 237.90 μs 1.21 ms
map run Eff 2000 506.02 μs 378.42 μs 349.51 μs 4.14 ms
map run Ef 2000 518.35 μs 79.27 μs 473.70 μs 1.47 ms
map build Eff 4000 1.42 ms 934.59 μs 878.94 μs 5.55 ms
map build Ef 4000 525.22 μs 77.05 μs 473.96 μs 1.45 ms
map run Eff 4000 1.04 ms 549.08 μs 722.80 μs 7.05 ms
map run Ef 4000 1.47 ms 144.09 μs 1.37 ms 2.73 ms
map build Eff 5000 1.90 ms 1.18 ms 1.11 ms 6.46 ms
map build Ef 5000 668.66 μs 103.73 μs 595.40 μs 1.82 ms
map run Eff 5000 1.56 ms 941.81 μs 973.49 μs 4.82 ms
map run Ef 5000 2.57 ms 245.36 μs 2.27 ms 4.84 ms
apply build Eff 100 531.69 ns 5.37 μs 235.00 ns 175.61 μs
apply build Ef 100 509.32 ns 3.02 μs 331.00 ns 134.36 μs
apply run Eff 100 173.57 μs 201.45 μs 122.28 μs 2.02 ms
apply run Ef 100 136.74 μs 38.67 μs 116.69 μs 1.04 ms
apply build Eff 500 373.04 ns 2.14 μs 243.00 ns 94.56 μs
apply build Ef 500 484.92 ns 2.35 μs 337.00 ns 104.17 μs
apply run Eff 500 999.63 μs 675.73 μs 629.89 μs 3.92 ms
apply run Ef 500 764.32 μs 101.96 μs 683.45 μs 1.78 ms
apply build Eff 1000 369.24 ns 1.80 μs 244.00 ns 79.92 μs
apply build Ef 1000 478.92 ns 1.95 μs 333.00 ns 86.81 μs
apply run Eff 1000 2.18 ms 1.12 ms 1.30 ms 6.93 ms
apply run Ef 1000 1.73 ms 181.83 μs 1.56 ms 2.94 ms
apply build Eff 2000 368.49 ns 1.43 μs 244.00 ns 62.42 μs
apply build Ef 2000 471.56 ns 2.74 μs 328.00 ns 122.78 μs
apply run Eff 2000 5.80 ms 1.82 ms 3.18 ms 14.53 ms
apply run Ef 2000 4.61 ms 455.07 μs 4.07 ms 8.09 ms
apply build Eff 4000 338.17 ns 1.45 μs 243.00 ns 64.89 μs
apply build Ef 4000 457.02 ns 1.97 μs 334.00 ns 87.52 μs
apply run Eff 4000 23.54 ms 5.64 ms 15.22 ms 47.46 ms
apply run Ef 4000 18.73 ms 893.71 μs 17.42 ms 24.71 ms
apply build Eff 5000 354.67 ns 1.35 μs 246.00 ns 60.00 μs
apply build Ef 5000 467.07 ns 2.14 μs 336.00 ns 96.00 μs
apply run Eff 5000 63.64 ms 24.42 ms 35.99 ms 149.47 ms
apply run Ef 5000 29.13 ms 1.11 ms 27.65 ms 35.49 ms

npm run bench:run:extended

bench type n mean stddev min max
bind assocR Ef 100000 226.42 ms 30.44 ms 183.64 ms 251.06 ms
bind assocR Ef 1000000 2.22 s 58.55 ms 2.14 s 2.29 s
bind assocL Ef 20000 145.42 ms 16.64 ms 123.93 ms 170.62 ms
bind assocL Ef 40000 1.15 s 833.35 ms 517.74 ms 2.07 s
bind assocL Ef 80000 19.65 s 3.03 s 14.90 s 23.20 s
map Ef 10000 12.64 ms 1.01 ms 12.02 ms 14.43 ms
map Ef 20000 50.15 ms 276.48 μs 49.77 ms 50.46 ms
map Ef 40000 214.09 ms 3.09 ms 210.74 ms 217.56 ms
map Ef 80000 15.36 s 77.80 ms 15.25 s 15.46 s
apply Ef 10000 330.49 ms 273.96 ms 119.76 ms 634.09 ms
apply Ef 20000 487.34 ms 5.83 ms 479.07 ms 494.23 ms
apply Ef 40000 25.53 s 431.47 ms 25.14 s 26.11 s

@safareli
Copy link
Owner Author

npm run bench:

bench type n mean stddev min max
bind assocR build Eff 100 1.07 μs 13.10 μs 225.00 ns 342.97 μs
bind assocR build Ef 100 592.34 ns 6.56 μs 270.00 ns 224.92 μs
bind assocR run Eff 100 78.08 μs 76.51 μs 53.94 μs 969.08 μs
bind assocR run Ef 100 36.19 μs 21.14 μs 27.98 μs 451.29 μs
bind assocR build Eff 500 330.31 ns 1.38 μs 236.00 ns 52.60 μs
bind assocR build Ef 500 471.72 ns 3.17 μs 273.00 ns 90.08 μs
bind assocR run Eff 500 402.77 μs 305.56 μs 280.04 μs 2.23 ms
bind assocR run Ef 500 168.54 μs 59.26 μs 145.53 μs 1.13 ms
bind assocR build Eff 1000 337.98 ns 1.70 μs 234.00 ns 66.74 μs
bind assocR build Ef 1000 493.50 ns 3.23 μs 271.00 ns 94.04 μs
bind assocR run Eff 1000 809.16 μs 441.44 μs 563.95 μs 3.42 ms
bind assocR run Ef 1000 350.92 μs 114.66 μs 290.28 μs 1.85 ms
bind assocR build Eff 2000 477.95 ns 2.08 μs 242.00 ns 79.33 μs
bind assocR build Ef 2000 720.08 ns 5.75 μs 279.00 ns 154.55 μs
bind assocR run Eff 2000 1.81 ms 764.95 μs 1.13 ms 6.91 ms
bind assocR run Ef 2000 717.64 μs 238.34 μs 582.61 μs 3.24 ms
bind assocR build Eff 4000 386.89 ns 1.96 μs 240.00 ns 58.98 μs
bind assocR build Ef 4000 456.13 ns 2.59 μs 277.00 ns 79.25 μs
bind assocR run Eff 4000 3.41 ms 920.06 μs 2.38 ms 16.35 ms
bind assocR run Ef 4000 1.40 ms 376.05 μs 1.17 ms 6.81 ms
bind assocR build Eff 8000 353.69 ns 1.95 μs 235.00 ns 59.56 μs
bind assocR build Ef 8000 470.33 ns 2.60 μs 273.00 ns 76.77 μs
bind assocR run Eff 8000 7.60 ms 2.32 ms 6.18 ms 51.94 ms
bind assocR run Ef 8000 4.26 ms 1.04 ms 3.19 ms 16.76 ms
bind assocR build Eff 10000 444.67 ns 2.33 μs 258.00 ns 78.46 μs
bind assocR build Ef 10000 579.49 ns 3.76 μs 326.00 ns 136.65 μs
bind assocR run Eff 10000 59.06 ms 18.74 ms 17.24 ms 133.24 ms
bind assocR run Ef 10000 4.90 ms 1.09 ms 3.88 ms 11.25 ms
bind assocL build Eff 100 26.55 μs 56.68 μs 18.17 μs 1.00 ms
bind assocL build Ef 100 11.03 μs 7.04 μs 8.89 μs 148.55 μs
bind assocL run Eff 100 27.39 μs 82.11 μs 16.53 μs 1.78 ms
bind assocL run Ef 100 2.60 μs 7.62 μs 1.97 μs 228.19 μs
bind assocL build Eff 500 125.83 μs 107.60 μs 98.89 μs 1.29 ms
bind assocL build Ef 500 73.55 μs 40.79 μs 46.42 μs 1.05 ms
bind assocL run Eff 500 176.11 μs 296.01 μs 85.26 μs 7.10 ms
bind assocL run Ef 500 11.30 μs 9.38 μs 8.53 μs 250.18 μs
bind assocL build Eff 1000 316.47 μs 287.27 μs 196.75 μs 6.48 ms
bind assocL build Ef 1000 111.53 μs 53.30 μs 92.73 μs 1.33 ms
bind assocL run Eff 1000 264.51 μs 319.44 μs 163.48 μs 3.14 ms
bind assocL run Ef 1000 20.04 μs 23.65 μs 16.78 μs 902.12 μs
bind assocL build Eff 2000 590.44 μs 476.66 μs 387.38 μs 3.33 ms
bind assocL build Ef 2000 251.51 μs 102.59 μs 187.91 μs 1.25 ms
bind assocL run Eff 2000 555.28 μs 580.38 μs 314.27 μs 4.50 ms
bind assocL run Ef 2000 41.17 μs 32.79 μs 34.01 μs 971.66 μs
bind assocL build Eff 4000 1.21 ms 747.20 μs 773.77 μs 6.08 ms
bind assocL build Ef 4000 453.54 μs 177.13 μs 367.08 μs 2.98 ms
bind assocL run Eff 4000 1.44 ms 1.23 ms 666.65 μs 9.56 ms
bind assocL run Ef 4000 97.13 μs 98.26 μs 66.79 μs 2.38 ms
bind assocL build Eff 8000 3.36 ms 1.46 ms 1.76 ms 12.17 ms
bind assocL build Ef 8000 1.07 ms 205.74 μs 944.47 μs 3.28 ms
bind assocL run Eff 8000 2.55 ms 1.17 ms 1.69 ms 17.08 ms
bind assocL run Ef 8000 197.78 μs 91.12 μs 172.07 μs 1.77 ms
map build Eff 100 32.87 μs 91.87 μs 20.98 μs 1.53 ms
map build Ef 100 13.22 μs 6.29 μs 11.26 μs 174.25 μs
map run Eff 100 25.76 μs 66.29 μs 16.93 μs 1.27 ms
map run Ef 100 3.22 μs 6.60 μs 2.21 μs 199.89 μs
map build Eff 500 156.63 μs 192.61 μs 110.74 μs 1.61 ms
map build Ef 500 64.29 μs 22.29 μs 58.20 μs 927.55 μs
map run Eff 500 128.05 μs 153.05 μs 87.62 μs 1.92 ms
map run Ef 500 16.10 μs 9.05 μs 11.27 μs 254.84 μs
map build Eff 1000 336.34 μs 366.75 μs 218.91 μs 2.99 ms
map build Ef 1000 129.87 μs 30.97 μs 117.62 μs 1.10 ms
map run Eff 1000 252.68 μs 234.18 μs 179.22 μs 2.35 ms
map run Ef 1000 25.59 μs 29.67 μs 22.04 μs 913.62 μs
map build Eff 2000 699.03 μs 651.74 μs 435.52 μs 3.73 ms
map build Ef 2000 257.73 μs 45.95 μs 232.63 μs 1.18 ms
map run Eff 2000 517.26 μs 361.48 μs 355.91 μs 4.20 ms
map run Ef 2000 51.67 μs 33.56 μs 44.95 μs 995.56 μs
map build Eff 4000 1.43 ms 950.64 μs 870.08 μs 5.01 ms
map build Ef 4000 496.93 μs 65.05 μs 463.81 μs 1.55 ms
map run Eff 4000 1.08 ms 563.89 μs 730.60 μs 7.41 ms
map run Ef 4000 106.78 μs 60.04 μs 87.63 μs 1.07 ms
map build Eff 5000 1.95 ms 1.24 ms 1.10 ms 6.78 ms
map build Ef 5000 640.89 μs 98.72 μs 581.11 μs 1.70 ms
map run Eff 5000 1.58 ms 926.79 μs 975.66 μs 4.80 ms
map run Ef 5000 125.07 μs 65.76 μs 108.92 μs 1.50 ms
apply build Eff 100 433.30 ns 4.51 μs 239.00 ns 143.75 μs
apply build Ef 100 454.29 ns 2.12 μs 320.00 ns 94.01 μs
apply run Eff 100 171.56 μs 190.27 μs 122.45 μs 2.87 ms
apply run Ef 100 64.13 μs 36.84 μs 54.87 μs 1.12 ms
apply build Eff 500 303.69 ns 1.17 μs 242.00 ns 52.59 μs
apply build Ef 500 421.70 ns 1.70 μs 321.00 ns 74.92 μs
apply run Eff 500 970.98 μs 583.27 μs 612.69 μs 3.86 ms
apply run Ef 500 308.34 μs 54.92 μs 271.85 μs 1.28 ms
apply build Eff 1000 319.60 ns 1.52 μs 242.00 ns 67.53 μs
apply build Ef 1000 415.83 ns 1.69 μs 321.00 ns 74.76 μs
apply run Eff 1000 2.18 ms 1.09 ms 1.27 ms 11.66 ms
apply run Ef 1000 649.82 μs 137.22 μs 548.30 μs 2.23 ms
apply build Eff 2000 344.88 ns 2.01 μs 245.00 ns 89.67 μs
apply build Ef 2000 447.89 ns 2.35 μs 330.00 ns 105.16 μs
apply run Eff 2000 5.61 ms 2.09 ms 2.91 ms 15.06 ms
apply run Ef 2000 1.35 ms 238.45 μs 1.11 ms 3.28 ms
apply build Eff 4000 312.94 ns 1.10 μs 242.00 ns 48.18 μs
apply build Ef 4000 414.19 ns 1.67 μs 321.00 ns 74.88 μs
apply run Eff 4000 26.05 ms 7.00 ms 13.72 ms 79.20 ms
apply run Ef 4000 2.94 ms 761.51 μs 2.34 ms 22.61 ms
apply build Eff 5000 322.27 ns 1.39 μs 239.00 ns 61.33 μs
apply build Ef 5000 459.24 ns 2.31 μs 330.00 ns 103.42 μs
apply run Eff 5000 65.66 ms 20.73 ms 37.99 ms 136.15 ms
apply run Ef 5000 4.05 ms 906.83 μs 3.03 ms 11.31 ms

npm run bench:run:extended

bench type n mean stddev min max
bind assocR Ef 20000 31.10 ms 11.50 ms 13.87 ms 42.72 ms
bind assocR Ef 50000 76.90 ms 20.10 ms 59.85 ms 111.80 ms
bind assocR Ef 100000 166.82 ms 16.35 ms 145.08 ms 188.14 ms
bind assocR Ef 1000000 2.22 s 283.14 ms 1.84 s 2.59 s
bind assocL Ef 20000 34.56 ms 14.32 ms 20.91 ms 53.50 ms
bind assocL Ef 50000 93.31 ms 14.31 ms 77.26 ms 111.25 ms
bind assocL Ef 100000 185.56 ms 24.32 ms 154.12 ms 218.03 ms
bind assocL Ef 1000000 2.34 s 231.97 ms 2.02 s 2.57 s
map Ef 10000 1.43 ms 437.95 μs 1.18 ms 2.21 ms
map Ef 20000 2.15 ms 244.78 μs 1.95 ms 2.55 ms
map Ef 50000 6.21 ms 888.34 μs 5.25 ms 7.22 ms
map Ef 100000 11.38 ms 592.67 μs 10.65 ms 12.06 ms
map Ef 1000000 122.13 ms 4.46 ms 115.44 ms 127.37 ms
map Ef 10000000 2.57 s 618.45 ms 1.48 s 2.96 s
apply Ef 10000 19.98 ms 6.64 ms 11.29 ms 28.79 ms
apply Ef 20000 30.26 ms 5.03 ms 25.01 ms 37.17 ms
apply Ef 50000 81.35 ms 13.06 ms 68.95 ms 100.05 ms
apply Ef 100000 194.60 ms 32.15 ms 175.02 ms 251.35 ms
apply Ef 1000000 2.07 s 72.61 ms 1.99 s 2.15 s

😬👆

@natefaubion
Copy link

I wonder if Effect could be an unlifted thunk (checking for it with typeof), then you could define it directly against the FFI. The FFI doesn't really need to use bind/map etc.

Some things to consider:

  • Eff do blocks get inlined into imperative statements, and in the 0.12 branch EffFn gets directly inlined, which means you can potentially write code with basically no overhead (though I'm sure it will be ugly).
  • These benchmarks benchmark the pure data structure aspect of Eff, but don't consider compiler optimizations since the trees are programmatically generated.
  • If you had an unlifted Effect constructor, you could have an unsafeCoerce implementation of liftEff as well which would make compatibility nice.
  • With an unlifted Effect you could probably do the same sort optimizations as Eff pretty easily.

@safareli
Copy link
Owner Author

Yes typeof x == "function" could totally work instead of Effect node, I was planning to do that.

With an unlifted Effect you could probably do the same sort optimizations as Eff pretty easily.

What you mean here? the optimizations are done compile time right? is the optimization specialized to Eff? If there are couple Ef statements I would still need to build Bind nodes.

@safareli
Copy link
Owner Author

safareli commented Dec 13, 2017

This made it a bit faster in some cases

bench type n mean stddev min max
bind assocR build Eff 100 1.54 μs 14.12 μs 231.00 ns 265.04 μs
bind assocR build Ef 100 860.41 ns 10.79 μs 267.00 ns 307.18 μs
bind assocR run Eff 100 82.18 μs 80.18 μs 52.94 μs 962.34 μs
bind assocR run Ef 100 39.24 μs 28.98 μs 31.32 μs 605.14 μs
bind assocR build Eff 500 565.36 ns 2.91 μs 259.00 ns 70.92 μs
bind assocR build Ef 500 558.95 ns 3.16 μs 279.00 ns 78.20 μs
bind assocR run Eff 500 404.03 μs 303.58 μs 276.04 μs 2.24 ms
bind assocR run Ef 500 180.79 μs 76.61 μs 155.57 μs 1.19 ms
bind assocR build Eff 1000 378.98 ns 2.07 μs 234.00 ns 55.07 μs
bind assocR build Ef 1000 523.71 ns 2.94 μs 271.00 ns 67.02 μs
bind assocR run Eff 1000 795.81 μs 434.58 μs 563.81 μs 3.44 ms
bind assocR run Ef 1000 346.14 μs 109.81 μs 305.53 μs 1.79 ms
bind assocR build Eff 2000 392.70 ns 2.34 μs 234.00 ns 61.28 μs
bind assocR build Ef 2000 640.35 ns 3.86 μs 271.00 ns 94.31 μs
bind assocR run Eff 2000 1.61 ms 605.90 μs 1.13 ms 6.45 ms
bind assocR run Ef 2000 734.17 μs 216.11 μs 607.85 μs 2.52 ms
bind assocR build Eff 4000 397.37 ns 2.16 μs 234.00 ns 53.88 μs
bind assocR build Ef 4000 489.49 ns 2.75 μs 271.00 ns 65.92 μs
bind assocR run Eff 4000 3.43 ms 1.02 ms 2.39 ms 15.92 ms
bind assocR run Ef 4000 1.44 ms 364.73 μs 1.22 ms 4.03 ms
bind assocR build Eff 8000 392.61 ns 2.23 μs 233.00 ns 56.89 μs
bind assocR build Ef 8000 541.04 ns 3.16 μs 264.00 ns 70.48 μs
bind assocR run Eff 8000 8.42 ms 3.33 ms 6.06 ms 47.50 ms
bind assocR run Ef 8000 3.93 ms 947.32 μs 2.94 ms 13.17 ms
bind assocR build Eff 10000 382.11 ns 1.97 μs 233.00 ns 44.81 μs
bind assocR build Ef 10000 465.88 ns 2.59 μs 274.00 ns 69.81 μs
bind assocR run Eff 10000 60.10 ms 18.69 ms 17.04 ms 136.96 ms
bind assocR run Ef 10000 5.41 ms 1.58 ms 3.64 ms 16.28 ms
bind assocL build Eff 100 25.53 μs 53.02 μs 17.96 μs 884.77 μs
bind assocL build Ef 100 11.98 μs 8.34 μs 9.68 μs 178.49 μs
bind assocL run Eff 100 27.51 μs 93.66 μs 15.83 μs 2.06 ms
bind assocL run Ef 100 3.30 μs 10.59 μs 2.05 μs 219.43 μs
bind assocL build Eff 500 120.82 μs 107.51 μs 95.88 μs 1.59 ms
bind assocL build Ef 500 62.38 μs 22.78 μs 50.48 μs 287.69 μs
bind assocL run Eff 500 119.65 μs 167.43 μs 85.30 μs 1.98 ms
bind assocL run Ef 500 12.26 μs 26.70 μs 8.80 μs 778.41 μs
bind assocL build Eff 1000 260.22 μs 211.02 μs 191.63 μs 1.83 ms
bind assocL build Ef 1000 111.31 μs 27.18 μs 100.84 μs 415.88 μs
bind assocL run Eff 1000 253.98 μs 304.55 μs 162.10 μs 2.82 ms
bind assocL run Ef 1000 19.47 μs 29.81 μs 17.04 μs 813.45 μs
bind assocL build Eff 2000 576.14 μs 483.90 μs 383.13 μs 3.46 ms
bind assocL build Ef 2000 266.29 μs 95.36 μs 200.17 μs 1.09 ms
bind assocL run Eff 2000 652.16 μs 776.47 μs 325.22 μs 6.84 ms
bind assocL run Ef 2000 47.79 μs 47.87 μs 35.53 μs 930.58 μs
bind assocL build Eff 4000 1.25 ms 806.64 μs 770.20 μs 5.74 ms
bind assocL build Ef 4000 584.74 μs 114.68 μs 517.19 μs 1.92 ms
bind assocL run Eff 4000 1.30 ms 1.08 ms 701.22 μs 9.20 ms
bind assocL run Ef 4000 74.78 μs 69.70 μs 67.02 μs 1.37 ms
bind assocL build Eff 8000 3.12 ms 1.33 ms 1.77 ms 13.67 ms
bind assocL build Ef 8000 1.20 ms 245.79 μs 1.03 ms 2.93 ms
bind assocL run Eff 8000 2.54 ms 1.27 ms 1.65 ms 16.99 ms
bind assocL run Ef 8000 206.06 μs 131.35 μs 179.96 μs 3.08 ms
map build Eff 100 40.07 μs 99.19 μs 21.63 μs 1.54 ms
map build Ef 100 14.87 μs 7.17 μs 12.54 μs 195.28 μs
map run Eff 100 26.26 μs 72.61 μs 16.71 μs 1.49 ms
map run Ef 100 4.05 μs 11.85 μs 2.34 μs 278.85 μs
map build Eff 500 171.53 μs 209.84 μs 112.81 μs 1.78 ms
map build Ef 500 72.81 μs 16.28 μs 63.95 μs 211.12 μs
map run Eff 500 129.44 μs 163.46 μs 87.17 μs 2.30 ms
map run Ef 500 13.23 μs 12.19 μs 11.11 μs 247.87 μs
map build Eff 1000 356.81 μs 393.99 μs 223.88 μs 4.08 ms
map build Ef 1000 152.29 μs 45.67 μs 126.98 μs 498.26 μs
map run Eff 1000 252.13 μs 238.58 μs 171.45 μs 2.50 ms
map run Ef 1000 29.97 μs 30.76 μs 22.71 μs 790.31 μs
map build Eff 2000 757.29 μs 745.33 μs 443.87 μs 6.76 ms
map build Ef 2000 267.71 μs 34.91 μs 252.32 μs 539.37 μs
map run Eff 2000 490.65 μs 331.30 μs 355.59 μs 3.97 ms
map run Ef 2000 51.85 μs 37.46 μs 46.41 μs 1.00 ms
map build Eff 4000 1.42 ms 948.94 μs 887.71 μs 6.12 ms
map build Ef 4000 554.65 μs 85.19 μs 503.57 μs 1.09 ms
map run Eff 4000 1.09 ms 585.87 μs 748.40 μs 5.18 ms
map run Ef 4000 106.51 μs 72.34 μs 90.39 μs 1.39 ms
map build Eff 5000 1.88 ms 1.18 ms 1.10 ms 7.90 ms
map build Ef 5000 736.66 μs 188.45 μs 631.34 μs 2.82 ms
map run Eff 5000 1.51 ms 953.11 μs 925.47 μs 7.52 ms
map run Ef 5000 130.58 μs 67.27 μs 112.88 μs 1.65 ms
apply build Eff 100 603.83 ns 6.53 μs 232.00 ns 149.49 μs
apply build Ef 100 436.87 ns 2.18 μs 276.00 ns 66.54 μs
apply run Eff 100 174.77 μs 199.01 μs 116.81 μs 1.96 ms
apply run Ef 100 63.79 μs 33.04 μs 54.66 μs 912.83 μs
apply build Eff 500 337.46 ns 1.56 μs 236.00 ns 48.66 μs
apply build Ef 500 431.56 ns 2.62 μs 285.00 ns 82.55 μs
apply run Eff 500 978.28 μs 595.58 μs 620.88 μs 3.80 ms
apply run Ef 500 308.85 μs 74.92 μs 269.64 μs 1.15 ms
apply build Eff 1000 342.55 ns 1.88 μs 234.00 ns 59.55 μs
apply build Ef 1000 446.46 ns 2.90 μs 285.00 ns 89.73 μs
apply run Eff 1000 2.18 ms 1.08 ms 1.25 ms 7.32 ms
apply run Ef 1000 629.16 μs 214.26 μs 538.05 μs 4.37 ms
apply build Eff 2000 355.54 ns 2.15 μs 244.00 ns 68.15 μs
apply build Ef 2000 460.14 ns 3.05 μs 292.00 ns 96.15 μs
apply run Eff 2000 5.48 ms 2.05 ms 2.91 ms 13.62 ms
apply run Ef 2000 1.27 ms 229.82 μs 1.11 ms 3.39 ms
apply build Eff 4000 343.87 ns 1.93 μs 241.00 ns 61.05 μs
apply build Ef 4000 397.49 ns 1.94 μs 277.00 ns 60.76 μs
apply run Eff 4000 27.31 ms 8.73 ms 14.03 ms 73.46 ms
apply run Ef 4000 2.78 ms 594.66 μs 2.25 ms 6.82 ms
apply build Eff 5000 333.29 ns 1.76 μs 232.00 ns 55.78 μs
apply build Ef 5000 421.57 ns 2.56 μs 275.00 ns 80.51 μs
apply run Eff 5000 67.62 ms 21.46 ms 35.71 ms 144.26 ms
apply run Ef 5000 3.75 ms 505.63 μs 3.05 ms 7.09 ms
bench type n mean stddev min max
bind assocR Ef 20000 33.47 ms 2.58 ms 31.19 ms 37.62 ms
bind assocR Ef 50000 72.61 ms 19.12 ms 52.33 ms 103.82 ms
bind assocR Ef 100000 175.08 ms 46.69 ms 133.62 ms 251.27 ms
bind assocR Ef 1000000 1.91 s 240.86 ms 1.58 s 2.26 s
bind assocL Ef 20000 22.34 ms 15.20 ms 7.99 ms 46.87 ms
bind assocL Ef 50000 82.20 ms 22.12 ms 66.01 ms 119.93 ms
bind assocL Ef 100000 187.54 ms 51.87 ms 139.80 ms 247.96 ms
bind assocL Ef 1000000 2.31 s 305.29 ms 2.06 s 2.79 s
map Ef 10000 2.57 ms 846.93 μs 1.67 ms 3.43 ms
map Ef 20000 2.15 ms 265.70 μs 1.96 ms 2.60 ms
map Ef 50000 6.92 ms 679.14 μs 6.16 ms 7.69 ms
map Ef 100000 17.03 ms 3.51 ms 12.79 ms 21.19 ms
map Ef 1000000 117.77 ms 1.42 ms 115.48 ms 119.07 ms
map Ef 10000000 2.72 s 707.12 ms 1.51 s 3.27 s
apply Ef 10000 10.00 ms 2.57 ms 7.49 ms 13.90 ms
apply Ef 20000 26.25 ms 2.15 ms 23.74 ms 29.02 ms
apply Ef 50000 74.68 ms 7.74 ms 66.42 ms 84.51 ms
apply Ef 100000 154.23 ms 17.32 ms 133.69 ms 172.05 ms
apply Ef 1000000 1.75 s 120.94 ms 1.65 s 1.92 s

};
};

exports.toEff = function (inputEff) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you could do a typeof inputEff === "function" check here so you can avoid creating another thunk to run the inner thunk.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so something like this:

if (typeof inputEff === "function") {
  return inputEff
}

thanks!

@natefaubion
Copy link

What you mean here? the optimizations are done compile time right? is the optimization specialized to Eff? If there are couple Ef statements I would still need to build Bind nodes.

Since you have an unlifted thunk as a representation for Ef, you could directly inline the binds as imperative statements the same way as Eff does, and then wrap each "bind" with toEff. This optimization works for both Eff and Ef, since the core representation (an unlifted thunk) is still the same. Ie., calling toEff on an Ef that's just Eff is an identity function. This gives you the best of both current worlds, where syntactic do blocks are largely 0-overhead imperative statements, and combinator based transformations are stack safe and fast.

@safareli
Copy link
Owner Author

safareli commented Dec 13, 2017

Since you have an unlifted thunk as a representation for Ef, you could directly inline the binds as imperative statements the same way as Eff does, and then wrap each "bind" with toEff

I don't understand how should I inline statements the same way? This is what I tired, but i'm not seeing same optimization happening on Ef, is there some way to force that? /cc @paf31:

test.purs

x :: Eff TestEff Unit
x = do
  ar <- mkArr
  _ <- pushToArr ar 1
  _ <- pushToArr ar 1
  _ <- pushToArr ar 1
  pure unit

x' :: Ef TestEff Unit
x' = do
  ar <- mkArr_
  _ <- pushToArr_ ar 1
  _ <- pushToArr_ ar 1
  _ <- pushToArr_ ar 1
  pure unit

foreign import mkArr :: forall e a. Eff e (Arr a)
foreign import mkArr_ :: forall e a. Ef e (Arr a)
foreign import pushToArr :: forall e a. Arr a -> a -> Eff e a
foreign import pushToArr_ :: forall e a. Arr a -> a -> Ef e a

out.js

var x$prime = Control_Bind.bind(Control_Monad_Ef.bindEf)($foreign.mkArr_)(function (v) {
    return Control_Bind.bind(Control_Monad_Ef.bindEf)($foreign.pushToArr_(v)(1))(function (v1) {
        return Control_Bind.bind(Control_Monad_Ef.bindEf)($foreign.pushToArr_(v)(1))(function (v2) {
            return Control_Bind.bind(Control_Monad_Ef.bindEf)($foreign.pushToArr_(v)(1))(function (v3) {
                return Control_Applicative.pure(Control_Monad_Ef.applicativeEf)(Data_Unit.unit);
            });
        });
    });
});

var x = function __do() {
    var v = $foreign.mkArr();
    var v1 = $foreign.pushToArr(v)(1)();
    var v2 = $foreign.pushToArr(v)(1)();
    var v3 = $foreign.pushToArr(v)(1)();
    return Data_Unit.unit;
};

test.js

exports.mkArr = function(){
  return [];
};

exports.pushToArr = function(xs) {
  return function(x) {
    return function() {
      xs.push(x);
      return x;
    };
  };
};

exports.mkArr_ = function(){
  return [];
};

exports.pushToArr_ = function(xs) {
  return function(x) {
    return function() {
      xs.push(x);
      return x;
    };
  };
};

@paf31
Copy link

paf31 commented Dec 13, 2017

You would need to either

a) change the compiler, but this would need to be in a fork
b) write a corefn pass (but this isn't really a practical option just yet)
c) (horrible) trick the compiler by naming your module and instances to match Eff 😈

@natefaubion
Copy link

Oh sorry, I meant as a hypothetical 😄. Yes, it would still require built-in compiler optimizations. My point was that the optimizations can be made to be identical for both types due to the representation.

@natefaubion
Copy link

b) write a corefn pass (but this isn't really a practical option just yet)

I think it would have to be coreimp, as corefn has no way to write raw statements.

@safareli
Copy link
Owner Author

ah :d gotcha

@safareli
Copy link
Owner Author

safareli commented Dec 13, 2017

Added Aff to benc for comparison, It was expected that Ef would be faster, as it's synchronous and has to dial with less staff. /cc @jdegoes

npm run bench:run

bench type n mean stddev min max
>>=R build Eff 100 1.49 μs 16.23 μs 231.00 ns 442.54 μs
>>=R build Aff 100 816.83 ns 7.55 μs 275.00 ns 151.82 μs
>>=R build Ef 100 812.19 ns 9.26 μs 271.00 ns 225.59 μs
>>=R run Eff 100 85.35 μs 94.94 μs 52.72 μs 1.45 ms
>>=R run Aff 100 117.84 μs 362.92 μs 59.50 μs 4.27 ms
>>=R run Ef 100 45.17 μs 66.93 μs 29.79 μs 898.93 μs
>>=R build Eff 500 461.85 ns 2.48 μs 243.00 ns 51.89 μs
>>=R build Aff 500 554.29 ns 2.85 μs 289.00 ns 70.86 μs
>>=R build Ef 500 571.89 ns 4.03 μs 282.00 ns 110.71 μs
>>=R run Eff 500 396.02 μs 306.05 μs 278.65 μs 3.11 ms
>>=R run Aff 500 349.41 μs 216.55 μs 288.14 μs 2.14 ms
>>=R run Ef 500 211.91 μs 214.10 μs 157.57 μs 3.05 ms
>>=R build Eff 1000 451.43 ns 2.90 μs 240.00 ns 64.74 μs
>>=R build Aff 1000 423.80 ns 1.96 μs 282.00 ns 48.23 μs
>>=R build Ef 1000 484.42 ns 2.72 μs 271.00 ns 64.27 μs
>>=R run Eff 1000 782.83 μs 447.02 μs 553.43 μs 4.33 ms
>>=R run Aff 1000 698.41 μs 298.77 μs 575.56 μs 2.64 ms
>>=R run Ef 1000 425.18 μs 319.81 μs 311.37 μs 2.47 ms
>>=R build Eff 2000 467.45 ns 2.88 μs 241.00 ns 71.70 μs
>>=R build Aff 2000 434.82 ns 2.11 μs 280.00 ns 51.48 μs
>>=R build Ef 2000 617.60 ns 3.70 μs 309.00 ns 99.49 μs
>>=R run Eff 2000 1.64 ms 711.80 μs 1.12 ms 7.69 ms
>>=R run Aff 2000 1.50 ms 668.52 μs 1.14 ms 4.22 ms
>>=R run Ef 2000 890.26 μs 556.44 μs 621.80 μs 3.61 ms
>>=R build Eff 4000 414.43 ns 2.40 μs 239.00 ns 52.51 μs
>>=R build Aff 4000 425.75 ns 2.14 μs 280.00 ns 48.56 μs
>>=R build Ef 4000 560.42 ns 2.69 μs 288.00 ns 59.95 μs
>>=R run Eff 4000 3.31 ms 817.00 μs 2.37 ms 12.42 ms
>>=R run Aff 4000 3.14 ms 1.09 ms 2.31 ms 9.21 ms
>>=R run Ef 4000 1.84 ms 863.40 μs 1.27 ms 6.14 ms
>>=R build Eff 8000 436.05 ns 3.00 μs 234.00 ns 83.83 μs
>>=R build Aff 8000 625.85 ns 2.10 μs 286.00 ns 52.33 μs
>>=R build Ef 8000 489.29 ns 2.80 μs 271.00 ns 68.00 μs
>>=R run Eff 8000 8.28 ms 2.12 ms 7.22 ms 44.06 ms
>>=R run Aff 8000 7.82 ms 2.43 ms 4.68 ms 20.10 ms
>>=R run Ef 8000 4.95 ms 1.92 ms 2.86 ms 14.96 ms
>>=R build Eff 10000 434.23 ns 2.93 μs 243.00 ns 70.57 μs
>>=R build Aff 10000 493.17 ns 3.74 μs 276.00 ns 110.81 μs
>>=R build Ef 10000 610.73 ns 4.86 μs 260.00 ns 129.78 μs
>>=R run Eff 10000 68.41 ms 17.47 ms 22.87 ms 145.99 ms
>>=R run Aff 10000 12.33 ms 1.21 ms 6.52 ms 28.35 ms
>>=R run Ef 10000 6.45 ms 2.33 ms 3.48 ms 13.76 ms
>>=L build Eff 100 775.32 ns 9.66 μs 242.00 ns 249.20 μs
>>=L build Aff 100 467.65 ns 2.55 μs 283.00 ns 66.55 μs
>>=L build Ef 100 476.92 ns 2.40 μs 285.00 ns 64.84 μs
>>=L run Eff 100 84.26 μs 145.72 μs 55.31 μs 1.86 ms
>>=L run Aff 100 81.92 μs 89.33 μs 65.97 μs 1.17 ms
>>=L run Ef 100 45.72 μs 83.40 μs 32.32 μs 1.55 ms
>>=L build Eff 500 444.27 ns 3.07 μs 243.00 ns 79.22 μs
>>=L build Aff 500 556.77 ns 2.39 μs 281.00 ns 54.30 μs
>>=L build Ef 500 572.30 ns 3.64 μs 294.00 ns 105.45 μs
>>=L run Eff 500 457.22 μs 427.23 μs 286.88 μs 3.45 ms
>>=L run Aff 500 387.24 μs 198.47 μs 324.16 μs 1.59 ms
>>=L run Ef 500 227.00 μs 197.79 μs 169.05 μs 1.73 ms
>>=L build Eff 1000 461.00 ns 2.83 μs 250.00 ns 55.62 μs
>>=L build Aff 1000 417.99 ns 1.86 μs 284.00 ns 45.41 μs
>>=L build Ef 1000 505.28 ns 2.92 μs 291.00 ns 82.59 μs
>>=L run Eff 1000 926.61 μs 616.93 μs 557.85 μs 5.31 ms
>>=L run Aff 1000 787.18 μs 292.33 μs 648.23 μs 2.33 ms
>>=L run Ef 1000 461.75 μs 302.23 μs 349.27 μs 2.23 ms
>>=L build Eff 2000 418.84 ns 2.55 μs 245.00 ns 59.24 μs
>>=L build Aff 2000 508.96 ns 3.20 μs 283.00 ns 72.93 μs
>>=L build Ef 2000 483.00 ns 2.55 μs 286.00 ns 62.51 μs
>>=L run Eff 2000 2.04 ms 1.04 ms 1.28 ms 9.27 ms
>>=L run Aff 2000 1.62 ms 426.38 μs 1.29 ms 3.74 ms
>>=L run Ef 2000 927.16 μs 396.91 μs 677.70 μs 3.07 ms
>>=L build Eff 4000 377.22 ns 1.97 μs 245.00 ns 59.11 μs
>>=L build Aff 4000 417.36 ns 1.98 μs 286.00 ns 60.09 μs
>>=L build Ef 4000 477.56 ns 2.65 μs 287.00 ns 80.87 μs
>>=L run Eff 4000 4.12 ms 1.39 ms 2.69 ms 17.59 ms
>>=L run Aff 4000 3.83 ms 1.35 ms 2.67 ms 7.42 ms
>>=L run Ef 4000 2.28 ms 1.23 ms 1.37 ms 5.84 ms
>>=L build Eff 8000 339.91 ns 1.68 μs 246.00 ns 53.28 μs
>>=L build Aff 8000 382.33 ns 1.77 μs 287.00 ns 56.21 μs
>>=L build Ef 8000 472.56 ns 2.75 μs 291.00 ns 85.35 μs
>>=L run Eff 8000 15.33 ms 3.14 ms 8.10 ms 50.90 ms
>>=L run Aff 8000 8.31 ms 2.46 ms 5.71 ms 25.55 ms
>>=L run Ef 8000 4.59 ms 1.38 ms 3.01 ms 8.39 ms
map build Eff 100 1.04 μs 13.47 μs 267.00 ns 337.24 μs
map build Aff 100 398.43 ns 1.72 μs 289.00 ns 54.45 μs
map build Ef 100 450.71 ns 2.91 μs 294.00 ns 91.69 μs
map run Eff 100 67.64 μs 148.88 μs 41.13 μs 2.39 ms
map run Aff 100 34.45 μs 36.22 μs 29.09 μs 1.10 ms
map run Ef 100 22.52 μs 29.50 μs 17.11 μs 850.09 μs
map build Eff 500 336.66 ns 1.61 μs 246.00 ns 50.98 μs
map build Aff 500 621.61 ns 4.27 μs 295.00 ns 83.55 μs
map build Ef 500 476.36 ns 2.59 μs 318.00 ns 81.12 μs
map run Eff 500 312.46 μs 318.26 μs 206.00 μs 2.57 ms
map run Aff 500 162.39 μs 72.26 μs 138.00 μs 1.74 ms
map run Ef 500 99.62 μs 52.59 μs 82.32 μs 1.10 ms
map build Eff 1000 350.86 ns 1.83 μs 255.00 ns 58.04 μs
map build Aff 1000 666.53 ns 4.48 μs 290.00 ns 75.19 μs
map build Ef 1000 429.57 ns 2.05 μs 292.00 ns 63.74 μs
map run Eff 1000 611.24 μs 458.89 μs 413.79 μs 3.10 ms
map run Aff 1000 298.13 μs 79.09 μs 269.90 μs 1.96 ms
map run Ef 1000 186.69 μs 58.39 μs 162.50 μs 1.10 ms
map build Eff 2000 386.81 ns 2.29 μs 250.00 ns 72.65 μs
map build Aff 2000 628.85 ns 5.01 μs 293.00 ns 135.23 μs
map build Ef 2000 469.41 ns 2.96 μs 294.00 ns 92.62 μs
map run Eff 2000 1.31 ms 729.52 μs 844.60 μs 5.33 ms
map run Aff 2000 727.74 μs 150.59 μs 641.74 μs 2.74 ms
map run Ef 2000 366.51 μs 73.29 μs 323.57 μs 1.35 ms
map build Eff 4000 390.74 ns 2.15 μs 251.00 ns 63.23 μs
map build Aff 4000 560.09 ns 3.09 μs 357.00 ns 93.56 μs
map build Ef 4000 451.80 ns 2.89 μs 293.00 ns 91.13 μs
map run Eff 4000 2.83 ms 1.16 ms 1.82 ms 11.20 ms
map run Aff 4000 1.68 ms 220.56 μs 1.51 ms 4.29 ms
map run Ef 4000 750.44 μs 148.78 μs 649.37 μs 2.15 ms
map build Eff 5000 353.79 ns 2.22 μs 246.00 ns 70.36 μs
map build Aff 5000 548.62 ns 3.26 μs 363.00 ns 102.53 μs
map build Ef 5000 444.05 ns 2.41 μs 296.00 ns 75.04 μs
map run Eff 5000 4.77 ms 2.18 ms 2.37 ms 13.35 ms
map run Aff 5000 2.15 ms 315.96 μs 1.88 ms 5.28 ms
map run Ef 5000 1.08 ms 482.85 μs 797.27 μs 5.99 ms
apply build Eff 100 854.43 ns 8.09 μs 251.00 ns 176.91 μs
apply build Aff 100 535.31 ns 2.70 μs 372.00 ns 85.08 μs
apply build Ef 100 460.71 ns 2.50 μs 297.00 ns 78.60 μs
apply run Eff 100 183.71 μs 248.92 μs 117.09 μs 2.91 ms
apply run Aff 100 210.72 μs 113.11 μs 170.22 μs 1.67 ms
apply run Ef 100 73.85 μs 78.71 μs 54.57 μs 958.33 μs
apply build Eff 500 351.47 ns 2.15 μs 247.00 ns 68.35 μs
apply build Aff 500 553.04 ns 3.13 μs 363.00 ns 98.30 μs
apply build Ef 500 455.55 ns 2.73 μs 292.00 ns 85.24 μs
apply run Eff 500 1.02 ms 655.54 μs 629.29 μs 4.14 ms
apply run Aff 500 1.08 ms 360.78 μs 848.25 μs 3.42 ms
apply run Ef 500 346.69 μs 160.20 μs 273.48 μs 1.33 ms
apply build Eff 1000 348.80 ns 1.93 μs 247.00 ns 61.13 μs
apply build Aff 1000 516.73 ns 2.41 μs 363.00 ns 75.88 μs
apply build Ef 1000 502.20 ns 4.05 μs 294.00 ns 126.36 μs
apply run Eff 1000 2.30 ms 1.17 ms 1.29 ms 8.21 ms
apply run Aff 1000 2.18 ms 562.34 μs 1.73 ms 4.95 ms
apply run Ef 1000 697.71 μs 220.07 μs 549.14 μs 2.11 ms
apply build Eff 2000 352.05 ns 1.89 μs 256.00 ns 59.94 μs
apply build Aff 2000 538.76 ns 2.97 μs 362.00 ns 93.42 μs
apply build Ef 2000 479.01 ns 3.43 μs 291.00 ns 107.71 μs
apply run Eff 2000 5.53 ms 1.98 ms 3.00 ms 15.27 ms
apply run Aff 2000 4.65 ms 1.07 ms 3.49 ms 8.77 ms
apply run Ef 2000 1.45 ms 367.98 μs 1.12 ms 4.70 ms
apply build Eff 4000 353.27 ns 1.71 μs 245.00 ns 53.51 μs
apply build Aff 4000 670.78 ns 2.88 μs 371.00 ns 87.53 μs
apply build Ef 4000 507.00 ns 3.63 μs 294.00 ns 109.41 μs
apply run Eff 4000 28.25 ms 6.09 ms 14.86 ms 53.36 ms
apply run Aff 4000 9.73 ms 1.71 ms 7.08 ms 15.10 ms
apply run Ef 4000 3.21 ms 769.60 μs 2.47 ms 8.24 ms
apply build Eff 5000 355.53 ns 1.81 μs 250.00 ns 57.46 μs
apply build Aff 5000 797.64 ns 5.99 μs 369.00 ns 189.10 μs
apply build Ef 5000 476.37 ns 3.53 μs 292.00 ns 111.36 μs
apply run Eff 5000 79.21 ms 26.47 ms 36.88 ms 188.51 ms
apply run Aff 5000 13.59 ms 2.04 ms 11.89 ms 29.44 ms
apply run Ef 5000 4.04 ms 729.38 μs 3.08 ms 8.37 ms

npm run bench:run:extended

bench type n mean stddev min max
>>=R build Aff 20000 63.59 μs 111.81 μs 3.10 μs 231.14 μs
>>=R build Ef 20000 46.44 μs 79.11 μs 757.00 ns 164.38 μs
>>=R run Aff 20000 53.51 ms 12.01 ms 40.71 ms 66.93 ms
>>=R run Ef 20000 26.01 ms 12.07 ms 8.79 ms 36.01 ms
>>=R build Aff 50000 15.56 μs 29.81 μs 518.00 ns 60.27 μs
>>=R build Ef 50000 23.09 μs 38.01 μs 568.00 ns 79.59 μs
>>=R run Aff 50000 143.41 ms 34.44 ms 115.83 ms 193.77 ms
>>=R run Ef 50000 67.65 ms 14.46 ms 48.13 ms 79.33 ms
>>=R build Aff 100000 51.05 μs 96.89 μs 573.00 ns 196.33 μs
>>=R build Ef 100000 21.01 μs 32.37 μs 841.00 ns 69.12 μs
>>=R run Aff 100000 224.61 ms 42.60 ms 192.33 ms 285.06 ms
>>=R run Ef 100000 143.07 ms 14.66 ms 128.64 ms 157.06 ms
>>=R build Aff 1000000 15.97 μs 29.76 μs 896.00 ns 60.61 μs
>>=R build Ef 1000000 27.82 μs 44.41 μs 758.00 ns 93.58 μs
>>=R run Aff 1000000 2.53 s 194.15 ms 2.38 s 2.81 s
>>=R run Ef 1000000 2.22 s 325.62 ms 1.74 s 2.44 s
>>=L build Aff 20000 38.49 μs 70.62 μs 583.00 ns 144.29 μs
>>=L build Ef 20000 38.12 μs 62.43 μs 618.00 ns 130.78 μs
>>=L run Aff 20000 53.55 ms 5.38 ms 46.70 ms 59.74 ms
>>=L run Ef 20000 22.72 ms 10.96 ms 10.18 ms 32.41 ms
>>=L build Aff 50000 14.97 μs 28.53 μs 582.00 ns 57.77 μs
>>=L build Ef 50000 33.43 μs 48.62 μs 979.00 ns 104.18 μs
>>=L run Aff 50000 246.69 ms 77.03 ms 146.78 ms 332.67 ms
>>=L run Ef 50000 113.16 ms 42.66 ms 68.15 ms 166.69 ms
>>=L build Aff 100000 157.46 μs 295.74 μs 1.52 μs 600.77 μs
>>=L build Ef 100000 41.53 μs 63.13 μs 2.10 μs 134.95 μs
>>=L run Aff 100000 403.56 ms 219.39 ms 235.79 ms 707.30 ms
>>=L run Ef 100000 189.61 ms 43.81 ms 158.03 ms 254.45 ms
>>=L build Aff 1000000 31.65 μs 57.03 μs 2.60 μs 117.20 μs
>>=L build Ef 1000000 42.08 μs 54.68 μs 1.35 μs 118.22 μs
>>=L run Aff 1000000 3.04 s 520.98 ms 2.65 s 3.79 s
>>=L run Ef 1000000 2.12 s 240.13 ms 1.88 s 2.44 s
map build Aff 10000 66.50 μs 117.12 μs 2.90 μs 242.09 μs
map build Ef 10000 33.23 μs 53.26 μs 716.00 ns 112.08 μs
map run Aff 10000 11.91 ms 6.50 ms 6.28 ms 21.22 ms
map run Ef 10000 2.61 ms 1.65 ms 1.43 ms 4.99 ms
map build Aff 20000 30.53 μs 51.70 μs 884.00 ns 107.87 μs
map build Ef 20000 18.35 μs 29.02 μs 550.00 ns 61.32 μs
map run Aff 20000 23.16 ms 12.29 ms 10.52 ms 39.54 ms
map run Ef 20000 4.69 ms 1.48 ms 3.13 ms 6.25 ms
map build Aff 50000 23.79 μs 40.19 μs 763.00 ns 83.77 μs
map build Ef 50000 27.86 μs 41.34 μs 1.35 μs 89.08 μs
map run Aff 50000 64.11 ms 40.20 ms 35.95 ms 123.66 ms
map run Ef 50000 15.03 ms 5.24 ms 10.19 ms 20.75 ms
map build Aff 100000 24.35 μs 41.58 μs 578.00 ns 86.40 μs
map build Ef 100000 22.57 μs 37.04 μs 563.00 ns 77.62 μs
map run Aff 100000 139.77 ms 66.61 ms 96.66 ms 238.15 ms
map run Ef 100000 48.34 ms 15.66 ms 33.24 ms 68.65 ms
map build Aff 1000000 31.40 μs 55.62 μs 622.00 ns 114.59 μs
map build Ef 1000000 70.68 μs 129.09 μs 532.00 ns 263.95 μs
map run Aff 1000000 1.42 s 839.80 ms 874.74 ms 2.66 s
map run Ef 1000000 474.92 ms 54.45 ms 405.97 ms 535.28 ms
map Ef 10000000 8.76 s 143.23 ms 8.51 s 8.87 s
apply build Aff 10000 75.54 μs 133.12 μs 901.00 ns 274.51 μs
apply build Ef 10000 34.96 μs 60.99 μs 545.00 ns 126.07 μs
apply run Aff 10000 47.83 ms 11.93 ms 36.43 ms 61.47 ms
apply run Ef 10000 9.84 ms 1.52 ms 8.18 ms 11.69 ms
apply build Aff 20000 25.97 μs 45.47 μs 493.00 ns 93.91 μs
apply build Ef 20000 24.17 μs 38.85 μs 396.00 ns 81.69 μs
apply run Aff 20000 114.99 ms 22.36 ms 96.32 ms 147.39 ms
apply run Ef 20000 28.27 ms 4.86 ms 22.32 ms 34.13 ms
apply build Aff 50000 25.58 μs 44.63 μs 459.00 ns 92.25 μs
apply build Ef 50000 24.69 μs 41.43 μs 448.00 ns 86.39 μs
apply run Aff 50000 252.50 ms 58.62 ms 220.01 ms 340.35 ms
apply run Ef 50000 79.21 ms 11.33 ms 70.81 ms 95.53 ms
apply build Aff 100000 26.68 μs 44.40 μs 535.00 ns 93.05 μs
apply build Ef 100000 25.22 μs 42.96 μs 387.00 ns 89.25 μs
apply run Aff 100000 512.79 ms 51.73 ms 451.08 ms 561.61 ms
apply run Ef 100000 166.15 ms 17.98 ms 147.43 ms 186.04 ms
apply build Aff 1000000 67.80 μs 120.27 μs 1.32 μs 247.80 μs
apply build Ef 1000000 32.53 μs 56.14 μs 526.00 ns 116.34 μs
apply run Aff 1000000 5.88 s 554.09 ms 5.21 s 6.42 s
apply run Ef 1000000 1.83 s 108.59 ms 1.73 s 1.92 s

@safareli
Copy link
Owner Author

The implementation is pretty fast and stack safe.
By accepting function as effect node doing FFI is also trivial.

So what you think how could we "integrate" work done in Ef in ps-eff/in PS/etc?

/cc @paf31 @natefaubion @garyb @jdegoes

@natefaubion
Copy link

These are great benchmarks! It's nice to know that Aff is at least faster than Eff 😈

How about this:

function makeEff(tag, _1, _2) {
  var eff = function () {
    return runEff(eff);
  };
  eff.tag = tag;
  eff._1 = _1;
  eff._2 = _2;
  return eff;
}

And then every Eff node is also a unary function that can interpret itself. This means it can be a drop in replacement.

@natefaubion
Copy link

That may result in too much heap due to the closure. I wonder if you could do something with this? I guess you'd need to do a function bind.

@paf31
Copy link

paf31 commented Dec 13, 2017

I think this is interesting, and makes a useful library, but as I said above, not a good default for the core libraries. The default should be as close to the JS as possible, so that the FFI can be simple and the optimizations straightforward.

@natefaubion
Copy link

Maybe you could take a self reference:

function makeEff(tag, _1, _2) {
  var eff = function thisEff() {
    return runEff(thisEff);
  };
  eff.tag = tag;
  eff._1 = _1;
  eff._2 = _2;
  return eff;
}

I'd be interested to see the difference.

Mapping was happening on pure node, such operation was optimised explicitly in Aff, so switched to do map on effect so it's more fair
@safareli
Copy link
Owner Author

1. store meta prop with EfMeta object on function

on timed ["map", "Ef", "10000000"] $ testMap 10000000 test Ef no runs out of memory as Aff did

diff:

Iraklis-MacBook-Pro:purescript-ef safareli$ cat asEff.patch 
diff --git a/bower.json b/bower.json
index f20d14e..1dfcde0 100644
--- a/bower.json
+++ b/bower.json
@@ -18,7 +18,8 @@
   ],
   "dependencies": {
     "purescript-prelude": "^3.0.0",
-    "purescript-eff": "^3.1.0"
+    "purescript-eff": "^3.1.0",
+    "purescript-unsafe-coerce": "^3.0.0"
   },
   "devDependencies": {
     "purescript-foldable-traversable": "^3.6.1",
diff --git a/src/Control/Monad/Ff.js b/src/Control/Monad/Ff.js
index e6b3aee..5101bde 100644
--- a/src/Control/Monad/Ff.js
+++ b/src/Control/Monad/Ff.js
@@ -1,7 +1,9 @@
 "use strict";
 
 
-// Ef a 
+// Ef a = { Eff a, meta :: EfMeta a }
+
+// EfMeta a
 // = () -> a
 // | { tag: "PURE",   _0 :: a,         _1 :: Void  }
 // | { tag: "MAP",    _0 :: b -> a,    _1 :: Ef b }
@@ -15,7 +17,7 @@
 // | { tag: "BIND",       _0 :: a -> Ef b }
 
 
-function Ef(tag, _0, _1) {
+function EfMeta(tag, _0, _1) {
   this.tag = tag;
   this._0 = _0;
   this._1 = _1;
@@ -27,52 +29,53 @@ var APPLY = "APPLY";
 var BIND = "BIND";
 var APPLY_FUNC = "APPLY_FUNC";
 
-exports.liftEffE = function (eff) {
-  return eff;
-};
-
 exports.pureE = function (x) {
-  return new Ef(PURE, x);
+  return asEff(new EfMeta(PURE, x));
 };
 
 exports.mapE = function (f) {
   return function (eff) {
-    return new Ef(MAP, f, eff);
+    return asEff(new EfMeta(MAP, f, eff));
   };
 };
 
 exports.applyE = function (effF) {
   return function (eff) {
-    return new Ef(APPLY, eff, effF);
+    return asEff(new EfMeta(APPLY, eff, effF));
   };
 };
 
 exports.bindE = function (eff) {
   return function (f) {
-    return new Ef(BIND, f, eff);
+    return asEff(new EfMeta(BIND, f, eff));
   };
 };
 
-exports.toEff = function (inputEff) {
-  if (typeof inputEff === "function") {
-    return inputEff;
-  }
+var asEff = function (meta) {
+  var eff = toEff(meta)
+  eff.meta = meta
+  return eff
+}
+
+var toEff = function (inputMeta) {
   return function() {
     var operations = [];
-    var eff = inputEff;
+    var eff = { meta: inputMeta };
+    var meta;
     var res;
     var op;
     var tag;
     effLoop: for (;;) {
-      tag = eff.tag;
-      if (tag !== undefined) {
+      meta = eff.meta
+      if (meta !== undefined) {
+        tag = meta.tag
         if (tag === MAP || tag === BIND || tag === APPLY) {
-          operations.push(eff);
-          eff = eff._1;
+          operations.push(meta);
+          eff = meta._1;
           continue;
         }
         // here `tag === PURE`
-        res = eff._0;
+        res = meta._0;
       } else {
         // here `typeof eff == "function"`
         res = eff();
@@ -85,7 +88,7 @@ exports.toEff = function (inputEff) {
           res = op._0(res);
         } else if (op.tag === APPLY) {
           eff = op._0;
-          operations.push(new Ef(APPLY_FUNC, res));
+          operations.push(new EfMeta(APPLY_FUNC, res));
           continue effLoop;
         } else { // op.tag === BIND
           eff = op._0(res);
diff --git a/src/Control/Monad/Ff.purs b/src/Control/Monad/Ff.purs
index bf890e2..8c2f216 100644
--- a/src/Control/Monad/Ff.purs
+++ b/src/Control/Monad/Ff.purs
@@ -1,7 +1,4 @@
-module Control.Monad.Ef
-  ( Ef
-  , toEff
-  ) where
+module Control.Monad.Ef (Ef) where
 
 import Control.Applicative (class Applicative)
 -- import Control.Applicative (class Applicative, liftA1)
@@ -12,6 +9,7 @@ import Control.Monad (class Monad)
 import Control.Monad.Eff (Eff, kind Effect)
 import Data.Functor (class Functor)
 import Control.Monad.Eff.Class (class MonadEff)
+import Unsafe.Coerce (unsafeCoerce)
 
 
 foreign import data Ef :: # Effect -> Type -> Type
@@ -33,11 +31,8 @@ instance bindEf :: Bind (Ef e) where
 instance monadEf :: Monad (Ef e)
 
 instance monadEEFff :: MonadEff eff (Ef eff) where
-  liftEff = liftEffE
+  liftEff = unsafeCoerce
 
-foreign import toEff :: forall e a. Ef e a -> Eff e a
-
-foreign import liftEffE :: forall e a. Eff e a -> Ef e a
 foreign import mapE :: forall e a b. (a -> b) -> Ef e a -> Ef e b
 foreign import applyE :: forall e a b. Ef e (a -> b) -> Ef e a-> Ef e b
 foreign import pureE :: forall e a. a -> Ef e a
diff --git a/src/Control/Monad/Ff/Class.purs b/src/Control/Monad/Ff/Class.purs
index 0e898e2..2a398a1 100644
--- a/src/Control/Monad/Ff/Class.purs
+++ b/src/Control/Monad/Ff/Class.purs
@@ -1,9 +1,13 @@
-module Control.Monad.Ef.Class where
+module Control.Monad.Ef.Class
+  ( class MonadEf
+  , liftEf
+  ) where
 
 import Control.Category (id)
 import Control.Monad (class Monad)
-import Control.Monad.Ef (Ef, toEff)
+import Control.Monad.Ef (Ef)
 import Control.Monad.Eff (Eff)
+import Unsafe.Coerce (unsafeCoerce)
 
 class Monad m <= MonadEf eff m | m -> eff where
   liftEf :: forall a. Ef eff a -> m a
@@ -12,4 +16,4 @@ instance monadEfEf :: MonadEf eff (Ef eff) where
   liftEf = id
 
 instance monadEfEff :: MonadEf eff (Eff eff) where
-  liftEf = toEff
+  liftEf = unsafeCoerce
\ No newline at end of file

bench:

bench type n mean stddev min max
>>=R build Eff 100 1.71 μs 15.70 μs 260.00 ns 310.62 μs
>>=R build Aff 100 785.61 ns 7.02 μs 279.00 ns 149.53 μs
>>=R build Ef 100 1.12 μs 14.36 μs 360.00 ns 368.61 μs
>>=R run Eff 100 78.59 μs 83.71 μs 52.63 μs 1.03 ms
>>=R run Aff 100 114.23 μs 353.41 μs 60.22 μs 3.85 ms
>>=R run Ef 100 74.37 μs 99.36 μs 55.50 μs 1.06 ms
>>=R build Eff 500 423.09 ns 2.56 μs 239.00 ns 68.21 μs
>>=R build Aff 500 498.83 ns 2.66 μs 287.00 ns 57.79 μs
>>=R build Ef 500 674.51 ns 3.76 μs 366.00 ns 95.76 μs
>>=R run Eff 500 389.44 μs 297.95 μs 279.99 μs 2.09 ms
>>=R run Aff 500 343.42 μs 205.56 μs 288.75 μs 1.94 ms
>>=R run Ef 500 329.51 μs 247.80 μs 261.15 μs 2.74 ms
>>=R build Eff 1000 472.30 ns 3.28 μs 241.00 ns 74.95 μs
>>=R build Aff 1000 488.50 ns 2.49 μs 288.00 ns 61.29 μs
>>=R build Ef 1000 693.37 ns 3.77 μs 373.00 ns 94.18 μs
>>=R run Eff 1000 758.93 μs 425.89 μs 558.46 μs 3.76 ms
>>=R run Aff 1000 670.60 μs 255.59 μs 575.84 μs 2.82 ms
>>=R run Ef 1000 680.97 μs 451.23 μs 517.09 μs 3.50 ms
>>=R build Eff 2000 387.29 ns 1.98 μs 243.00 ns 49.06 μs
>>=R build Aff 2000 477.95 ns 2.47 μs 285.00 ns 47.09 μs
>>=R build Ef 2000 645.97 ns 3.69 μs 370.00 ns 80.18 μs
>>=R run Eff 2000 1.57 ms 599.66 μs 1.13 ms 6.77 ms
>>=R run Aff 2000 1.47 ms 647.71 μs 1.15 ms 4.64 ms
>>=R run Ef 2000 1.39 ms 660.42 μs 1.04 ms 4.83 ms
>>=R build Eff 4000 405.36 ns 2.38 μs 244.00 ns 62.05 μs
>>=R build Aff 4000 817.42 ns 2.97 μs 480.00 ns 69.95 μs
>>=R build Ef 4000 711.11 ns 4.36 μs 380.00 ns 118.39 μs
>>=R run Eff 4000 3.39 ms 845.87 μs 2.41 ms 12.32 ms
>>=R run Aff 4000 3.27 ms 1.22 ms 2.32 ms 10.56 ms
>>=R run Ef 4000 3.26 ms 1.41 ms 2.09 ms 9.02 ms
>>=R build Eff 8000 413.41 ns 2.50 μs 242.00 ns 59.22 μs
>>=R build Aff 8000 465.01 ns 2.09 μs 289.00 ns 51.52 μs
>>=R build Ef 8000 604.56 ns 3.03 μs 369.00 ns 73.41 μs
>>=R run Eff 8000 8.34 ms 1.85 ms 6.99 ms 43.05 ms
>>=R run Aff 8000 7.38 ms 2.27 ms 4.69 ms 21.16 ms
>>=R run Ef 8000 11.09 ms 918.20 μs 6.68 ms 27.11 ms
>>=R build Eff 10000 426.69 ns 2.65 μs 236.00 ns 68.14 μs
>>=R build Aff 10000 501.91 ns 3.54 μs 287.00 ns 104.13 μs
>>=R build Ef 10000 830.32 ns 5.52 μs 357.00 ns 122.04 μs
>>=R run Eff 10000 67.56 ms 16.43 ms 17.30 ms 121.04 ms
>>=R run Aff 10000 12.14 ms 1.15 ms 6.43 ms 29.68 ms
>>=R run Ef 10000 11.13 ms 1.03 ms 7.87 ms 26.05 ms
>>=L build Eff 100 688.34 ns 8.74 μs 242.00 ns 222.75 μs
>>=L build Aff 100 479.38 ns 2.86 μs 283.00 ns 80.35 μs
>>=L build Ef 100 614.15 ns 3.33 μs 374.00 ns 90.97 μs
>>=L run Eff 100 86.19 μs 162.23 μs 54.91 μs 2.32 ms
>>=L run Aff 100 83.65 μs 111.48 μs 66.41 μs 2.28 ms
>>=L run Ef 100 75.63 μs 139.61 μs 56.95 μs 2.44 ms
>>=L build Eff 500 409.27 ns 2.24 μs 250.00 ns 56.94 μs
>>=L build Aff 500 463.48 ns 2.29 μs 289.00 ns 61.53 μs
>>=L build Ef 500 586.78 ns 2.80 μs 374.00 ns 71.66 μs
>>=L run Eff 500 424.87 μs 404.61 μs 289.11 μs 2.84 ms
>>=L run Aff 500 385.35 μs 209.29 μs 321.56 μs 2.47 ms
>>=L run Ef 500 339.54 μs 251.37 μs 271.77 μs 2.59 ms
>>=L build Eff 1000 440.45 ns 2.88 μs 243.00 ns 75.65 μs
>>=L build Aff 1000 450.12 ns 2.34 μs 284.00 ns 63.00 μs
>>=L build Ef 1000 597.32 ns 3.46 μs 375.00 ns 100.11 μs
>>=L run Eff 1000 878.17 μs 619.18 μs 561.76 μs 4.61 ms
>>=L run Aff 1000 776.17 μs 311.28 μs 640.45 μs 3.03 ms
>>=L run Ef 1000 687.25 μs 360.89 μs 538.21 μs 2.92 ms
>>=L build Eff 2000 387.05 ns 2.11 μs 243.00 ns 53.99 μs
>>=L build Aff 2000 442.71 ns 2.17 μs 283.00 ns 50.22 μs
>>=L build Ef 2000 595.97 ns 2.76 μs 373.00 ns 70.33 μs
>>=L run Eff 2000 1.87 ms 880.22 μs 1.28 ms 8.48 ms
>>=L run Aff 2000 1.56 ms 433.59 μs 1.29 ms 4.66 ms
>>=L run Ef 2000 1.90 ms 712.17 μs 1.46 ms 4.82 ms
>>=L build Eff 4000 393.94 ns 2.70 μs 247.00 ns 83.52 μs
>>=L build Aff 4000 410.92 ns 2.04 μs 285.00 ns 62.55 μs
>>=L build Ef 4000 550.97 ns 2.68 μs 377.00 ns 81.39 μs
>>=L run Eff 4000 4.12 ms 1.43 ms 2.71 ms 19.78 ms
>>=L run Aff 4000 3.79 ms 1.36 ms 2.65 ms 7.87 ms
>>=L run Ef 4000 3.85 ms 940.81 μs 2.98 ms 6.82 ms
>>=L build Eff 8000 350.50 ns 1.74 μs 245.00 ns 54.50 μs
>>=L build Aff 8000 413.31 ns 2.10 μs 286.00 ns 65.69 μs
>>=L build Ef 8000 521.19 ns 2.52 μs 380.00 ns 78.53 μs
>>=L run Eff 8000 14.89 ms 2.89 ms 8.47 ms 53.77 ms
>>=L run Aff 8000 7.94 ms 2.25 ms 5.73 ms 22.69 ms
>>=L run Ef 8000 12.69 ms 629.11 μs 9.06 ms 16.57 ms
map build Eff 100 603.87 ns 6.99 μs 242.00 ns 165.81 μs
map build Aff 100 393.05 ns 1.89 μs 284.00 ns 59.30 μs
map build Ef 100 524.01 ns 2.32 μs 383.00 ns 71.62 μs
map run Eff 100 66.05 μs 156.95 μs 41.84 μs 3.04 ms
map run Aff 100 34.61 μs 32.64 μs 29.93 μs 979.52 μs
map run Ef 100 43.46 μs 31.86 μs 36.85 μs 939.45 μs
map build Eff 500 377.58 ns 2.33 μs 254.00 ns 73.18 μs
map build Aff 500 766.19 ns 5.03 μs 290.00 ns 99.31 μs
map build Ef 500 544.15 ns 2.53 μs 383.00 ns 77.67 μs
map run Eff 500 291.56 μs 301.25 μs 204.47 μs 2.42 ms
map run Aff 500 152.43 μs 59.56 μs 138.00 μs 1.60 ms
map run Ef 500 191.71 μs 43.82 μs 173.74 μs 1.15 ms
map build Eff 1000 366.88 ns 2.04 μs 249.00 ns 64.72 μs
map build Aff 1000 590.20 ns 4.10 μs 286.00 ns 87.98 μs
map build Ef 1000 560.40 ns 3.35 μs 380.00 ns 104.16 μs
map run Eff 1000 591.60 μs 461.28 μs 407.66 μs 3.17 ms
map run Aff 1000 307.60 μs 76.74 μs 277.95 μs 1.96 ms
map run Ef 1000 381.15 μs 63.60 μs 348.81 μs 1.30 ms
map build Eff 2000 352.88 ns 1.62 μs 248.00 ns 51.23 μs
map build Aff 2000 550.17 ns 3.41 μs 290.00 ns 76.72 μs
map build Ef 2000 615.11 ns 3.44 μs 382.00 ns 105.38 μs
map run Eff 2000 1.27 ms 727.35 μs 829.96 μs 5.44 ms
map run Aff 2000 705.77 μs 139.14 μs 636.44 μs 2.68 ms
map run Ef 2000 758.22 μs 86.64 μs 690.01 μs 1.74 ms
map build Eff 4000 379.64 ns 1.89 μs 247.00 ns 58.91 μs
map build Aff 4000 610.16 ns 4.25 μs 359.00 ns 130.67 μs
map build Ef 4000 884.60 ns 6.79 μs 381.00 ns 212.99 μs
map run Eff 4000 2.63 ms 1.11 ms 1.79 ms 9.18 ms
map run Aff 4000 1.65 ms 200.53 μs 1.54 ms 4.51 ms
map run Ef 4000 1.57 ms 258.31 μs 1.40 ms 3.23 ms
map build Eff 5000 402.61 ns 2.72 μs 247.00 ns 85.80 μs
map build Aff 5000 576.00 ns 3.46 μs 361.00 ns 108.35 μs
map build Ef 5000 569.57 ns 4.04 μs 380.00 ns 126.99 μs
map run Eff 5000 4.59 ms 2.13 ms 2.33 ms 11.31 ms
map run Aff 5000 2.12 ms 283.92 μs 1.90 ms 5.19 ms
map run Ef 5000 2.00 ms 324.50 μs 1.74 ms 4.25 ms
apply build Eff 100 753.18 ns 7.39 μs 242.00 ns 163.91 μs
apply build Aff 100 623.71 ns 3.77 μs 357.00 ns 116.91 μs
apply build Ef 100 591.71 ns 2.71 μs 414.00 ns 82.43 μs
apply run Eff 100 174.97 μs 232.80 μs 115.41 μs 1.97 ms
apply run Aff 100 204.46 μs 119.15 μs 171.84 μs 1.61 ms
apply run Ef 100 143.56 μs 82.78 μs 121.26 μs 1.06 ms
apply build Eff 500 436.73 ns 2.30 μs 247.00 ns 67.09 μs
apply build Aff 500 571.61 ns 2.94 μs 359.00 ns 91.65 μs
apply build Ef 500 599.88 ns 4.19 μs 382.00 ns 130.64 μs
apply run Eff 500 964.92 μs 679.49 μs 615.91 μs 5.04 ms
apply run Aff 500 1.04 ms 393.97 μs 849.20 μs 3.16 ms
apply run Ef 500 716.98 μs 208.73 μs 617.84 μs 2.01 ms
apply build Eff 1000 360.04 ns 2.08 μs 246.00 ns 66.11 μs
apply build Aff 1000 532.21 ns 2.60 μs 363.00 ns 81.88 μs
apply build Ef 1000 576.99 ns 2.91 μs 381.00 ns 89.14 μs
apply run Eff 1000 2.11 ms 1.10 ms 1.28 ms 7.17 ms
apply run Aff 1000 2.14 ms 644.01 μs 1.70 ms 5.10 ms
apply run Ef 1000 1.47 ms 270.63 μs 1.26 ms 2.88 ms
apply build Eff 2000 383.30 ns 2.18 μs 256.00 ns 68.31 μs
apply build Aff 2000 549.86 ns 2.60 μs 364.00 ns 80.79 μs
apply build Ef 2000 590.85 ns 4.25 μs 383.00 ns 132.21 μs
apply run Eff 2000 5.42 ms 1.99 ms 2.93 ms 14.68 ms
apply run Aff 2000 4.57 ms 1.12 ms 3.46 ms 8.16 ms
apply run Ef 2000 2.98 ms 434.08 μs 2.52 ms 5.39 ms
apply build Eff 4000 359.07 ns 1.70 μs 246.00 ns 53.87 μs
apply build Aff 4000 632.66 ns 3.66 μs 373.00 ns 115.70 μs
apply build Ef 4000 584.80 ns 3.62 μs 388.00 ns 113.48 μs
apply run Eff 4000 26.81 ms 5.19 ms 15.51 ms 50.33 ms
apply run Aff 4000 9.41 ms 1.72 ms 6.91 ms 15.40 ms
apply run Ef 4000 5.99 ms 526.85 μs 5.39 ms 9.36 ms
apply build Eff 5000 342.75 ns 1.87 μs 245.00 ns 59.27 μs
apply build Aff 5000 530.40 ns 3.14 μs 353.00 ns 98.75 μs
apply build Ef 5000 552.04 ns 3.11 μs 380.00 ns 97.23 μs
apply run Eff 5000 72.99 ms 23.32 ms 36.56 ms 158.01 ms
apply run Aff 5000 12.65 ms 1.35 ms 11.74 ms 31.80 ms
apply run Ef 5000 9.81 ms 2.06 ms 6.95 ms 19.70 ms

extended bench:

bench type n mean stddev min max
>>=R build Aff 20000 59.24 μs 103.16 μs 3.06 μs 213.81 μs
>>=R build Ef 20000 69.12 μs 119.96 μs 781.00 ns 248.26 μs
>>=R run Aff 20000 58.35 ms 6.37 ms 49.21 ms 63.38 ms
>>=R run Ef 20000 67.08 ms 21.99 ms 45.10 ms 95.20 ms
>>=R build Aff 50000 25.13 μs 47.41 μs 1.11 μs 96.23 μs
>>=R build Ef 50000 26.24 μs 40.09 μs 652.00 ns 85.16 μs
>>=R run Aff 50000 133.90 ms 25.01 ms 115.01 ms 168.75 ms
>>=R run Ef 50000 137.69 ms 38.34 ms 113.59 ms 194.91 ms
>>=R build Aff 100000 19.27 μs 36.70 μs 663.00 ns 74.32 μs
>>=R build Ef 100000 37.30 μs 58.93 μs 1.23 μs 124.89 μs
>>=R run Aff 100000 220.46 ms 52.33 ms 192.06 ms 298.87 ms
>>=R run Ef 100000 289.22 ms 18.41 ms 263.64 ms 303.31 ms
>>=R build Aff 1000000 47.52 μs 87.66 μs 648.00 ns 178.85 μs
>>=R build Ef 1000000 32.69 μs 51.68 μs 594.00 ns 109.09 μs
>>=R run Aff 1000000 2.43 s 102.44 ms 2.30 s 2.55 s
>>=R run Ef 1000000 3.08 s 433.87 ms 2.82 s 3.73 s
>>=L build Aff 20000 43.12 μs 79.90 μs 560.00 ns 162.85 μs
>>=L build Ef 20000 36.79 μs 59.48 μs 680.00 ns 124.98 μs
>>=L run Aff 20000 56.54 ms 7.98 ms 47.12 ms 63.54 ms
>>=L run Ef 20000 62.14 ms 27.68 ms 41.02 ms 100.93 ms
>>=L build Aff 50000 16.64 μs 31.09 μs 854.00 ns 63.27 μs
>>=L build Ef 50000 25.03 μs 36.60 μs 646.00 ns 78.30 μs
>>=L run Aff 50000 147.03 ms 39.37 ms 113.96 ms 199.06 ms
>>=L run Ef 50000 148.35 ms 33.50 ms 116.78 ms 191.63 ms
>>=L build Aff 100000 56.91 μs 107.77 μs 1.62 μs 218.55 μs
>>=L build Ef 100000 33.46 μs 52.53 μs 877.00 ns 111.08 μs
>>=L run Aff 100000 290.46 ms 59.60 ms 241.86 ms 371.72 ms
>>=L run Ef 100000 307.69 ms 31.11 ms 271.62 ms 347.12 ms
>>=L build Aff 1000000 68.43 μs 128.18 μs 632.00 ns 260.54 μs
>>=L build Ef 1000000 30.22 μs 47.15 μs 626.00 ns 99.75 μs
>>=L run Aff 1000000 3.02 s 217.05 ms 2.84 s 3.33 s
>>=L run Ef 1000000 3.41 s 384.64 ms 3.12 s 3.95 s
map build Aff 10000 65.59 μs 115.13 μs 3.15 μs 238.10 μs
map build Ef 10000 65.39 μs 114.29 μs 675.00 ns 236.10 μs
map run Aff 10000 15.10 ms 9.14 ms 6.85 ms 27.63 ms
map run Ef 10000 7.62 ms 3.64 ms 3.64 ms 11.95 ms
map build Aff 20000 25.98 μs 40.96 μs 732.00 ns 86.48 μs
map build Ef 20000 41.60 μs 65.87 μs 681.00 ns 138.89 μs
map run Aff 20000 25.72 ms 11.23 ms 11.42 ms 38.88 ms
map run Ef 20000 15.47 ms 6.87 ms 9.05 ms 25.01 ms
map build Aff 50000 30.67 μs 52.96 μs 652.00 ns 109.75 μs
map build Ef 50000 26.61 μs 37.17 μs 693.00 ns 79.90 μs
map run Aff 50000 63.48 ms 36.50 ms 35.91 ms 117.19 ms
map run Ef 50000 60.90 ms 18.52 ms 41.93 ms 80.25 ms
map build Aff 100000 37.18 μs 62.22 μs 1.07 μs 129.88 μs
map build Ef 100000 24.45 μs 35.40 μs 677.00 ns 75.98 μs
map run Aff 100000 145.08 ms 73.58 ms 95.31 ms 253.62 ms
map run Ef 100000 116.41 ms 28.09 ms 98.57 ms 158.30 ms
map build Aff 1000000 23.51 μs 38.48 μs 563.00 ns 80.67 μs
map build Ef 1000000 31.83 μs 49.70 μs 637.00 ns 105.11 μs
map run Aff 1000000 1.44 s 810.81 ms 877.74 ms 2.63 s
map run Ef 1000000 1.24 s 182.04 ms 1.01 s 1.39 s
apply build Aff 10000 61.05 μs 109.44 μs 638.00 ns 224.79 μs
apply build Ef 10000 41.17 μs 64.33 μs 703.00 ns 136.05 μs
apply run Aff 10000 47.19 ms 12.73 ms 36.01 ms 63.88 ms
apply run Ef 10000 31.67 ms 11.11 ms 17.72 ms 41.68 ms
apply build Aff 20000 29.84 μs 52.05 μs 663.00 ns 107.62 μs
apply build Ef 20000 26.61 μs 40.97 μs 647.00 ns 86.91 μs
apply run Aff 20000 112.90 ms 25.53 ms 91.10 ms 149.44 ms
apply run Ef 20000 75.06 ms 11.76 ms 66.09 ms 91.28 ms
apply build Aff 50000 22.61 μs 38.23 μs 600.00 ns 79.62 μs
apply build Ef 50000 40.43 μs 66.50 μs 655.00 ns 139.23 μs
apply run Aff 50000 253.01 ms 63.15 ms 217.79 ms 347.65 ms
apply run Ef 50000 212.55 ms 33.33 ms 194.51 ms 262.46 ms
apply build Aff 100000 38.94 μs 60.60 μs 3.37 μs 129.58 μs
apply build Ef 100000 44.52 μs 71.15 μs 617.00 ns 149.68 μs
apply run Aff 100000 497.15 ms 61.48 ms 438.15 ms 560.08 ms
apply run Ef 100000 434.29 ms 47.56 ms 392.31 ms 495.25 ms
apply build Aff 1000000 107.85 μs 191.44 μs 1.24 μs 394.36 μs
apply build Ef 1000000 67.12 μs 117.97 μs 689.00 ns 243.41 μs
apply run Aff 1000000 5.97 s 442.12 ms 5.52 s 6.41 s
apply run Ef 1000000 5.23 s 433.15 ms 4.64 s 5.64 s

@natefaubion
Copy link

natefaubion commented Dec 13, 2017

So in some cases, it's worse off, but you are allocating an extra meta object. The reason why I suggested adding properties to the function itself is to avoid the allocation of the meta object.

@safareli
Copy link
Owner Author

2. store tag, _0 and _1 props on function directly

diff

diff --git a/src/Control/Monad/Ff.js b/src/Control/Monad/Ff.js
index e6b3aee..1fb94ac 100644
--- a/src/Control/Monad/Ff.js
+++ b/src/Control/Monad/Ff.js
@@ -1,12 +1,12 @@
 "use strict";
 
 
-// Ef a 
+// Ef a
 // = () -> a
-// | { tag: "PURE",   _0 :: a,         _1 :: Void  }
-// | { tag: "MAP",    _0 :: b -> a,    _1 :: Ef b }
-// | { tag: "APPLY",  _0 :: Ef b,      _1 :: Ef (b -> a) }
-// | { tag: "BIND",   _0 :: b -> Ef a, _1 :: Ef b }
+// | { Ef a, tag: "PURE",   _0 :: a,         _1 :: Void  }
+// | { Ef a, tag: "MAP",    _0 :: b -> a,    _1 :: Ef b }
+// | { Ef a, tag: "APPLY",  _0 :: Ef b,      _1 :: Ef (b -> a) }
+// | { Ef a, tag: "BIND",   _0 :: b -> Ef a, _1 :: Ef b }
 
 // Operation a b
 // = { tag: "MAP",        _0 :: a -> b }
@@ -15,57 +15,51 @@
 // | { tag: "BIND",       _0 :: a -> Ef b }
 
 
-function Ef(tag, _0, _1) {
-  this.tag = tag;
-  this._0 = _0;
-  this._1 = _1;
-}
-
 var PURE = "PURE";
 var MAP = "MAP";
 var APPLY = "APPLY";
 var BIND = "BIND";
 var APPLY_FUNC = "APPLY_FUNC";
 
-exports.liftEffE = function (eff) {
-  return eff;
-};
-
 exports.pureE = function (x) {
-  return new Ef(PURE, x);
+  return mkEf(PURE, x);
 };
 
 exports.mapE = function (f) {
   return function (eff) {
-    return new Ef(MAP, f, eff);
+    return mkEf(MAP, f, eff);
   };
 };
 
 exports.applyE = function (effF) {
   return function (eff) {
-    return new Ef(APPLY, eff, effF);
+    return mkEf(APPLY, eff, effF);
   };
 };
 
 exports.bindE = function (eff) {
   return function (f) {
-    return new Ef(BIND, f, eff);
+    return mkEf(BIND, f, eff);
   };
 };
 
-exports.toEff = function (inputEff) {
-  if (typeof inputEff === "function") {
-    return inputEff;
-  }
-  return function() {
+
+var mkEf = function (tag, _0, _1) {
+  var eff = function eff_() { return toEff(eff_) }
+  eff.tag = tag
+  eff._0 = _0
+  eff._1 = _1
+  return eff
+}
+
+var toEff = function (eff) {
     var operations = [];
-    var eff = inputEff;
     var res;
     var op;
     var tag;
     effLoop: for (;;) {
-      tag = eff.tag;
-      if (tag !== undefined) {
+      if (eff.tag !== undefined) {
+        tag = eff.tag
         if (tag === MAP || tag === BIND || tag === APPLY) {
           operations.push(eff);
           eff = eff._1;
@@ -94,5 +88,4 @@ exports.toEff = function (inputEff) {
       }
       return res;
     }
-  };
 };
\ No newline at end of file

bench

bench type n mean stddev min max
>>=R build Eff 100 1.56 μs 15.28 μs 231.00 ns 330.73 μs
>>=R build Aff 100 804.35 ns 7.47 μs 275.00 ns 155.00 μs
>>=R build Ef 100 844.88 ns 9.19 μs 279.00 ns 233.30 μs
>>=R run Eff 100 79.80 μs 78.14 μs 52.77 μs 1.02 ms
>>=R run Aff 100 115.69 μs 349.13 μs 60.63 μs 3.84 ms
>>=R run Ef 100 68.76 μs 65.05 μs 55.41 μs 801.61 μs
>>=R build Eff 500 429.48 ns 2.42 μs 239.00 ns 62.72 μs
>>=R build Aff 500 453.56 ns 2.48 μs 282.00 ns 58.27 μs
>>=R build Ef 500 513.77 ns 2.85 μs 282.00 ns 60.86 μs
>>=R run Eff 500 387.53 μs 308.36 μs 274.28 μs 2.49 ms
>>=R run Aff 500 344.03 μs 210.55 μs 287.03 μs 1.82 ms
>>=R run Ef 500 296.10 μs 186.94 μs 245.79 μs 1.53 ms
>>=R build Eff 1000 446.37 ns 2.70 μs 239.00 ns 67.54 μs
>>=R build Aff 1000 477.74 ns 2.38 μs 280.00 ns 57.73 μs
>>=R build Ef 1000 521.51 ns 3.23 μs 281.00 ns 61.50 μs
>>=R run Eff 1000 771.10 μs 438.47 μs 553.35 μs 3.79 ms
>>=R run Aff 1000 693.87 μs 285.45 μs 580.55 μs 3.16 ms
>>=R run Ef 1000 526.83 μs 356.63 μs 397.50 μs 2.16 ms
>>=R build Eff 2000 402.33 ns 2.28 μs 236.00 ns 56.57 μs
>>=R build Aff 2000 531.05 ns 2.46 μs 280.00 ns 51.87 μs
>>=R build Ef 2000 535.98 ns 3.40 μs 282.00 ns 63.77 μs
>>=R run Eff 2000 1.63 ms 703.93 μs 1.11 ms 6.49 ms
>>=R run Aff 2000 1.50 ms 667.88 μs 1.14 ms 4.18 ms
>>=R run Ef 2000 998.89 μs 594.59 μs 704.75 μs 3.24 ms
>>=R build Eff 4000 420.46 ns 2.34 μs 237.00 ns 53.21 μs
>>=R build Aff 4000 456.66 ns 2.11 μs 281.00 ns 46.66 μs
>>=R build Ef 4000 534.09 ns 3.04 μs 283.00 ns 63.99 μs
>>=R run Eff 4000 3.32 ms 801.06 μs 2.37 ms 12.29 ms
>>=R run Aff 4000 3.17 ms 1.16 ms 2.33 ms 8.35 ms
>>=R run Ef 4000 1.89 ms 820.67 μs 1.33 ms 4.17 ms
>>=R build Eff 8000 423.48 ns 2.66 μs 237.00 ns 67.36 μs
>>=R build Aff 8000 459.44 ns 2.26 μs 280.00 ns 55.02 μs
>>=R build Ef 8000 548.23 ns 3.78 μs 283.00 ns 83.15 μs
>>=R run Eff 8000 7.89 ms 1.72 ms 6.96 ms 38.57 ms
>>=R run Aff 8000 7.27 ms 2.24 ms 4.70 ms 19.45 ms
>>=R run Ef 8000 3.94 ms 944.80 μs 2.92 ms 6.40 ms
>>=R build Eff 10000 428.80 ns 2.45 μs 240.00 ns 59.21 μs
>>=R build Aff 10000 443.61 ns 2.43 μs 280.00 ns 65.63 μs
>>=R build Ef 10000 669.84 ns 5.22 μs 268.00 ns 122.86 μs
>>=R run Eff 10000 64.64 ms 15.12 ms 18.11 ms 105.76 ms
>>=R run Aff 10000 12.01 ms 1.21 ms 6.54 ms 27.84 ms
>>=R run Ef 10000 5.44 ms 1.68 ms 3.59 ms 8.89 ms
>>=L build Eff 100 762.68 ns 8.91 μs 243.00 ns 221.87 μs
>>=L build Aff 100 426.06 ns 2.00 μs 280.00 ns 44.38 μs
>>=L build Ef 100 473.54 ns 2.47 μs 286.00 ns 60.47 μs
>>=L run Eff 100 82.15 μs 153.77 μs 53.50 μs 2.58 ms
>>=L run Aff 100 83.57 μs 94.82 μs 66.51 μs 1.18 ms
>>=L run Ef 100 69.68 μs 103.69 μs 53.90 μs 1.57 ms
>>=L build Eff 500 407.37 ns 2.40 μs 243.00 ns 63.91 μs
>>=L build Aff 500 437.43 ns 2.09 μs 285.00 ns 46.83 μs
>>=L build Ef 500 501.64 ns 2.94 μs 288.00 ns 67.99 μs
>>=L run Eff 500 430.74 μs 426.52 μs 276.61 μs 3.23 ms
>>=L run Aff 500 382.30 μs 199.80 μs 324.92 μs 1.57 ms
>>=L run Ef 500 301.45 μs 214.48 μs 238.89 μs 1.88 ms
>>=L build Eff 1000 455.65 ns 2.76 μs 245.00 ns 63.94 μs
>>=L build Aff 1000 427.56 ns 2.20 μs 281.00 ns 57.41 μs
>>=L build Ef 1000 521.37 ns 3.22 μs 286.00 ns 83.16 μs
>>=L run Eff 1000 888.88 μs 617.73 μs 570.93 μs 5.32 ms
>>=L run Aff 1000 768.97 μs 291.08 μs 647.39 μs 2.82 ms
>>=L run Ef 1000 496.86 μs 282.55 μs 389.00 μs 1.97 ms
>>=L build Eff 2000 411.58 ns 2.30 μs 244.00 ns 52.92 μs
>>=L build Aff 2000 425.66 ns 1.87 μs 282.00 ns 44.74 μs
>>=L build Ef 2000 490.73 ns 2.72 μs 288.00 ns 60.70 μs
>>=L run Eff 2000 1.88 ms 848.57 μs 1.27 ms 7.59 ms
>>=L run Aff 2000 1.54 ms 378.53 μs 1.31 ms 2.89 ms
>>=L run Ef 2000 1.02 ms 611.88 μs 717.28 μs 3.18 ms
>>=L build Eff 4000 389.58 ns 2.00 μs 244.00 ns 60.37 μs
>>=L build Aff 4000 425.28 ns 2.10 μs 283.00 ns 63.38 μs
>>=L build Ef 4000 470.53 ns 2.71 μs 291.00 ns 81.62 μs
>>=L run Eff 4000 3.97 ms 1.33 ms 2.71 ms 18.20 ms
>>=L run Aff 4000 3.78 ms 1.31 ms 2.68 ms 7.55 ms
>>=L run Ef 4000 2.07 ms 844.54 μs 1.44 ms 4.78 ms
>>=L build Eff 8000 351.05 ns 1.60 μs 245.00 ns 50.67 μs
>>=L build Aff 8000 396.03 ns 1.91 μs 285.00 ns 59.90 μs
>>=L build Ef 8000 424.15 ns 2.14 μs 295.00 ns 66.03 μs
>>=L run Eff 8000 14.18 ms 2.62 ms 7.32 ms 51.36 ms
>>=L run Aff 8000 7.78 ms 2.04 ms 5.77 ms 13.86 ms
>>=L run Ef 8000 4.26 ms 951.65 μs 3.14 ms 7.86 ms
map build Eff 100 811.38 ns 8.59 μs 314.00 ns 189.12 μs
map build Aff 100 388.66 ns 1.46 μs 284.00 ns 46.29 μs
map build Ef 100 417.27 ns 1.92 μs 294.00 ns 59.88 μs
map run Eff 100 65.52 μs 169.18 μs 41.48 μs 3.54 ms
map run Aff 100 34.76 μs 37.12 μs 29.39 μs 1.11 ms
map run Ef 100 30.70 μs 12.90 μs 26.91 μs 289.64 μs
map build Eff 500 406.55 ns 2.33 μs 269.00 ns 73.86 μs
map build Aff 500 632.89 ns 4.70 μs 317.00 ns 125.04 μs
map build Ef 500 480.03 ns 3.67 μs 299.00 ns 115.07 μs
map run Eff 500 308.57 μs 325.95 μs 202.75 μs 2.79 ms
map run Aff 500 159.48 μs 65.32 μs 138.09 μs 1.70 ms
map run Ef 500 143.59 μs 38.31 μs 123.87 μs 1.02 ms
map build Eff 1000 374.13 ns 2.34 μs 246.00 ns 74.22 μs
map build Aff 1000 591.15 ns 3.75 μs 292.00 ns 84.37 μs
map build Ef 1000 418.45 ns 2.09 μs 293.00 ns 65.14 μs
map run Eff 1000 606.13 μs 485.10 μs 404.96 μs 3.37 ms
map run Aff 1000 301.25 μs 78.10 μs 271.71 μs 1.97 ms
map run Ef 1000 266.60 μs 45.69 μs 246.73 μs 1.23 ms
map build Eff 2000 400.07 ns 2.26 μs 250.00 ns 69.92 μs
map build Aff 2000 595.01 ns 4.38 μs 286.00 ns 108.34 μs
map build Ef 2000 456.99 ns 3.12 μs 294.00 ns 98.00 μs
map run Eff 2000 1.26 ms 728.33 μs 818.29 μs 5.47 ms
map run Aff 2000 715.17 μs 140.31 μs 637.98 μs 2.88 ms
map run Ef 2000 444.46 μs 99.49 μs 359.40 μs 1.52 ms
map build Eff 4000 379.40 ns 2.41 μs 246.00 ns 76.38 μs
map build Aff 4000 561.97 ns 2.82 μs 356.00 ns 84.31 μs
map build Ef 4000 506.10 ns 2.73 μs 296.00 ns 79.10 μs
map run Eff 4000 2.70 ms 1.15 ms 1.76 ms 8.80 ms
map run Aff 4000 1.73 ms 396.25 μs 1.54 ms 6.99 ms
map run Ef 4000 772.77 μs 188.27 μs 677.22 μs 2.44 ms
map build Eff 5000 347.42 ns 1.83 μs 250.00 ns 58.20 μs
map build Aff 5000 618.04 ns 2.85 μs 369.00 ns 87.33 μs
map build Ef 5000 465.33 ns 3.01 μs 295.00 ns 94.03 μs
map run Eff 5000 5.00 ms 2.58 ms 2.31 ms 19.12 ms
map run Aff 5000 2.12 ms 283.83 μs 1.92 ms 5.29 ms
map run Ef 5000 1.02 ms 247.71 μs 862.65 μs 3.08 ms
apply build Eff 100 723.69 ns 7.80 μs 244.00 ns 184.79 μs
apply build Aff 100 521.72 ns 2.61 μs 356.00 ns 82.21 μs
apply build Ef 100 418.62 ns 1.97 μs 294.00 ns 61.65 μs
apply run Eff 100 171.71 μs 230.24 μs 114.77 μs 2.29 ms
apply run Aff 100 211.13 μs 145.15 μs 173.34 μs 2.86 ms
apply run Ef 100 118.80 μs 82.30 μs 95.33 μs 1.03 ms
apply build Eff 500 384.12 ns 2.86 μs 250.00 ns 90.72 μs
apply build Aff 500 580.11 ns 3.87 μs 369.00 ns 122.00 μs
apply build Ef 500 487.41 ns 3.85 μs 293.00 ns 121.05 μs
apply run Eff 500 1.14 ms 838.02 μs 609.47 μs 6.60 ms
apply run Aff 500 1.22 ms 483.01 μs 892.31 μs 4.60 ms
apply run Ef 500 431.78 μs 218.46 μs 318.22 μs 2.39 ms
apply build Eff 1000 373.86 ns 2.46 μs 246.00 ns 77.60 μs
apply build Aff 1000 551.04 ns 2.85 μs 366.00 ns 89.89 μs
apply build Ef 1000 527.46 ns 3.66 μs 304.00 ns 113.54 μs
apply run Eff 1000 2.14 ms 1.07 ms 1.25 ms 6.54 ms
apply run Aff 1000 2.19 ms 643.58 μs 1.74 ms 5.09 ms
apply run Ef 1000 734.70 μs 307.66 μs 554.76 μs 3.38 ms
apply build Eff 2000 378.94 ns 2.55 μs 249.00 ns 80.17 μs
apply build Aff 2000 549.62 ns 3.64 μs 354.00 ns 114.86 μs
apply build Ef 2000 459.91 ns 3.49 μs 294.00 ns 109.33 μs
apply run Eff 2000 5.48 ms 2.06 ms 2.98 ms 14.43 ms
apply run Aff 2000 4.80 ms 1.16 ms 3.57 ms 9.39 ms
apply run Ef 2000 1.51 ms 570.43 μs 1.10 ms 5.05 ms
apply build Eff 4000 341.78 ns 1.53 μs 245.00 ns 47.56 μs
apply build Aff 4000 537.14 ns 3.24 μs 356.00 ns 102.04 μs
apply build Ef 4000 446.32 ns 2.40 μs 294.00 ns 74.13 μs
apply run Eff 4000 28.57 ms 6.45 ms 15.18 ms 68.81 ms
apply run Aff 4000 10.27 ms 2.03 ms 7.15 ms 16.72 ms
apply run Ef 4000 3.05 ms 791.76 μs 2.25 ms 7.27 ms
apply build Eff 5000 565.76 ns 3.19 μs 247.00 ns 96.82 μs
apply build Aff 5000 571.16 ns 3.89 μs 367.00 ns 122.49 μs
apply build Ef 5000 490.75 ns 3.90 μs 292.00 ns 122.65 μs
apply run Eff 5000 75.52 ms 24.65 ms 36.48 ms 200.52 ms
apply run Aff 5000 13.04 ms 1.12 ms 12.04 ms 19.40 ms
apply run Ef 5000 3.92 ms 794.87 μs 3.04 ms 7.80 ms

extended

bench type n mean stddev min max
>>=R build Aff 20000 58.54 μs 101.60 μs 3.42 μs 210.77 μs
>>=R build Ef 20000 42.49 μs 71.77 μs 648.00 ns 149.42 μs
>>=R run Aff 20000 54.26 ms 9.77 ms 46.26 ms 66.60 ms
>>=R run Ef 20000 24.71 ms 9.76 ms 15.62 ms 34.52 ms
>>=R build Aff 50000 14.31 μs 27.20 μs 563.00 ns 55.11 μs
>>=R build Ef 50000 20.52 μs 32.27 μs 542.00 ns 68.18 μs
>>=R run Aff 50000 119.38 ms 22.72 ms 94.43 ms 147.93 ms
>>=R run Ef 50000 95.20 ms 19.55 ms 77.47 ms 120.74 ms
>>=R build Aff 100000 15.84 μs 30.26 μs 506.00 ns 61.23 μs
>>=R build Ef 100000 26.09 μs 40.38 μs 955.00 ns 86.09 μs
>>=R run Aff 100000 207.89 ms 44.52 ms 182.30 ms 274.56 ms
>>=R run Ef 100000 169.70 ms 16.15 ms 149.40 ms 185.54 ms
>>=R build Aff 1000000 18.58 μs 35.87 μs 505.00 ns 72.39 μs
>>=R build Ef 1000000 24.89 μs 38.34 μs 620.00 ns 81.27 μs
>>=R run Aff 1000000 2.64 s 408.88 ms 2.24 s 3.19 s
>>=R run Ef 1000000 2.01 s 47.67 ms 1.95 s 2.06 s
>>=L build Aff 20000 43.62 μs 78.62 μs 560.00 ns 161.29 μs
>>=L build Ef 20000 34.85 μs 55.36 μs 516.00 ns 116.63 μs
>>=L run Aff 20000 55.00 ms 7.67 ms 45.90 ms 64.43 ms
>>=L run Ef 20000 36.97 ms 14.11 ms 17.88 ms 49.43 ms
>>=L build Aff 50000 14.06 μs 26.83 μs 547.00 ns 54.30 μs
>>=L build Ef 50000 28.13 μs 37.51 μs 814.00 ns 83.41 μs
>>=L run Aff 50000 140.71 ms 33.94 ms 112.37 ms 186.78 ms
>>=L run Ef 50000 98.82 ms 26.63 ms 77.65 ms 137.68 ms
>>=L build Aff 100000 17.62 μs 32.71 μs 1.03 μs 66.69 μs
>>=L build Ef 100000 20.40 μs 31.39 μs 519.00 ns 66.60 μs
>>=L run Aff 100000 259.10 ms 57.47 ms 226.01 ms 345.05 ms
>>=L run Ef 100000 194.13 ms 46.25 ms 162.57 ms 262.90 ms
>>=L build Aff 1000000 12.11 μs 22.95 μs 514.00 ns 46.53 μs
>>=L build Ef 1000000 25.70 μs 41.27 μs 554.00 ns 86.82 μs
>>=L run Aff 1000000 2.74 s 167.06 ms 2.59 s 2.98 s
>>=L run Ef 1000000 2.26 s 54.35 ms 2.20 s 2.31 s
map build Aff 10000 37.48 μs 67.87 μs 1.68 μs 139.25 μs
map build Ef 10000 40.36 μs 66.80 μs 591.00 ns 139.63 μs
map run Aff 10000 12.17 ms 6.61 ms 6.40 ms 21.65 ms
map run Ef 10000 2.55 ms 1.18 ms 1.65 ms 4.17 ms
map build Aff 20000 24.15 μs 39.53 μs 758.00 ns 83.19 μs
map build Ef 20000 19.43 μs 30.59 μs 560.00 ns 64.65 μs
map run Aff 20000 23.14 ms 11.62 ms 10.26 ms 38.15 ms
map run Ef 20000 5.05 ms 1.70 ms 3.18 ms 6.56 ms
map build Aff 50000 28.70 μs 49.63 μs 611.00 ns 102.82 μs
map build Ef 50000 43.64 μs 75.95 μs 532.00 ns 157.06 μs
map run Aff 50000 64.76 ms 35.34 ms 40.80 ms 117.17 ms
map run Ef 50000 21.46 ms 7.10 ms 14.11 ms 30.92 ms
map build Aff 100000 23.60 μs 37.89 μs 703.00 ns 79.76 μs
map build Ef 100000 20.55 μs 31.35 μs 604.00 ns 66.64 μs
map run Aff 100000 139.06 ms 67.94 ms 94.38 ms 239.31 ms
map run Ef 100000 56.95 ms 11.70 ms 44.71 ms 69.94 ms
map build Aff 1000000 43.82 μs 72.40 μs 1.10 μs 151.51 μs
map build Ef 1000000 99.95 μs 182.43 μs 578.00 ns 373.21 μs
map run Aff 1000000 1.40 s 826.01 ms 869.20 ms 2.61 s
map run Ef 1000000 681.45 ms 67.42 ms 614.27 ms 768.07 ms
apply build Aff 10000 55.90 μs 98.57 μs 724.00 ns 203.21 μs
apply build Ef 10000 27.77 μs 45.44 μs 609.00 ns 95.25 μs
apply run Aff 10000 45.76 ms 13.47 ms 33.63 ms 63.49 ms
apply run Ef 10000 8.08 ms 1.30 ms 7.26 ms 9.99 ms
apply build Aff 20000 25.53 μs 44.07 μs 541.00 ns 91.34 μs
apply build Ef 20000 26.08 μs 43.35 μs 407.00 ns 90.53 μs
apply run Aff 20000 107.59 ms 23.25 ms 86.21 ms 140.48 ms
apply run Ef 20000 34.28 ms 4.33 ms 29.25 ms 38.88 ms
apply build Aff 50000 76.23 μs 141.23 μs 531.00 ns 287.81 μs
apply build Ef 50000 33.94 μs 59.22 μs 445.00 ns 122.40 μs
apply run Aff 50000 252.15 ms 58.81 ms 207.85 ms 336.16 ms
apply run Ef 50000 98.93 ms 17.99 ms 83.20 ms 118.65 ms
apply build Aff 100000 31.95 μs 52.73 μs 855.00 ns 110.38 μs
apply build Ef 100000 25.37 μs 41.29 μs 400.00 ns 86.60 μs
apply run Aff 100000 494.45 ms 58.20 ms 424.30 ms 544.51 ms
apply run Ef 100000 220.36 ms 51.25 ms 177.40 ms 284.08 ms
apply build Aff 1000000 69.65 μs 122.89 μs 839.00 ns 253.57 μs
apply build Ef 1000000 33.79 μs 52.03 μs 822.00 ns 110.38 μs
apply run Aff 1000000 5.84 s 427.10 ms 5.28 s 6.23 s
apply run Ef 1000000 2.10 s 16.31 ms 2.08 s 2.12 s

@safareli
Copy link
Owner Author

@natefaubion yah did that in 2. aproach. which is better for sure. Ef is still faster then Eff and Aff in run. in terms of build time it's a bit slow but build time is nothing compared to running it.
And it's safe as before.

@paf31 what you think on this?

This version will make FFI still trivial, and making this changes on Eff will be non braking.

I guess the optimizations done on Eff now will optimize this implementation as well.

@natefaubion
Copy link

@safareli I think you should try to work it into Eff proper in a non-breaking way (which should be possible to do by only touching the FFI), and then try testing it against optimizations.

@safareli
Copy link
Owner Author

here you go 🎉 purescript-deprecated/purescript-eff#31

@safareli safareli closed this Dec 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants