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

Add List.chooseV, Seq.tryPickV, etc. for ValueOption #6781

Closed
wants to merge 12 commits into from
Closed

Add List.chooseV, Seq.tryPickV, etc. for ValueOption #6781

wants to merge 12 commits into from

Conversation

cmeeren
Copy link
Contributor

@cmeeren cmeeren commented May 20, 2019

See fsharp/fslang-suggestions#739

I have simply copied the existing Option-based implementations and tried to adapt them trivially to ValueOption. Note that I was unable to build the solution (before I started working), so I have made these edits without an IDE.

I need help with adding ValueOption equivalents of

  • Microsoft.FSharp.Primitives.Basics.List.choose
  • Microsoft.FSharp.Primitives.Basics.List.unfold

because I don't know where to find them. Other than that, I don't know of anything else that needs to be done here (as long as it compiles).

Note that I have absolutely no need to have my name on these changes; I have only created this PR in the hope that it might speed up the completion of fsharp/fslang-suggestions#739. I'm completely fine with this PR being thrown away in favor of another implementation.

@cartermp
Copy link
Contributor

@cmeeren If possible, can you change this PR to a draft? That way it's clear that the PR is for experimentation and information about what this feature could mean.

Once you're comfortable with a trial implementation, it would be great to spin up a few BenchmarkDotNet experiments that attempt to simulate common tasks. A subfolder containing a solution could be placed here: https://github.com/dotnet/fsharp/tree/master/tests/fsharp/perf

This would help really suss out the impact from a CPU time and memory perspective of having these kinds of functions.

@cmeeren
Copy link
Contributor Author

cmeeren commented May 21, 2019

If possible, can you change this PR to a draft?

I don't know what this means. Edit: I just found out about GitHub's draft PR stuff, but it seems it's not possible to change from non-draft to draft.

Once you're comfortable with a trial implementation, it would be great to spin up a few BenchmarkDotNet experiments that attempt to simulate common tasks.

I have never used BenchmarkDotNet and am quite busy with real-life events the next months, so I can't promise anything (I probably won't be able to delve into it). For the record though, what specifically do you want the tests to measure? Should they compare the option and voption alternatives?

Also, do you know where I can find Microsoft.FSharp.Primitives.Basics.List.choose and Microsoft.FSharp.Primitives.Basics.List.unfold?

@cmeeren
Copy link
Contributor Author

cmeeren commented May 28, 2019

@cartermp Are you able to provide some clarification on the questions in my last comment?

@cartermp
Copy link
Contributor

cartermp commented Jun 4, 2019

@cmeeren Sorry for not getting back to you yet.

Re: draft PR - this is fine. It's unfortunate that GitHub doesn't allow this.

As for benchmarking, it's quite easy. I have an example here that demonstrates how you can measure CPU and memory usage for distinct things: https://github.com/cartermp/trees

The idea is that you'd compare the built-in FSharp.Core methods today with your own variants written in a separate file/namepsace/module/etc. It would be good to have a few different benchmark classes:

  • These functions on small lists (<100)
  • These functions on medium lists (<1000)
  • These functions on large lists (>1000)
  • These functions with larger data types being held in the lists

That should give a pretty good view over the impact of using ValueOption for things.

@cmeeren
Copy link
Contributor Author

cmeeren commented Jun 4, 2019

Thanks! I still need to know where I can find Microsoft.FSharp.Primitives.Basics.List.choose and Microsoft.FSharp.Primitives.Basics.List.unfold, though (currently it doesn't compile).

@cartermp
Copy link
Contributor

cartermp commented Jun 4, 2019

Choose is here: https://github.com/dotnet/fsharp/blob/master/src/fsharp/FSharp.Core/local.fs#L187

Unfold is here: https://github.com/dotnet/fsharp/blob/master/src/fsharp/FSharp.Core/local.fs#L781

Note that they ultimately rely on inline IL: https://github.com/dotnet/fsharp/blob/master/src/fsharp/FSharp.Core/local.fs#L96

So you'll have to do the benchmarks with a built FSharp.Core, otherwise your code will be at a disadvantage 🙂

@cmeeren
Copy link
Contributor Author

cmeeren commented Jun 13, 2019

Note that they ultimately rely on inline IL: https://github.com/dotnet/fsharp/blob/master/src/fsharp/FSharp.Core/local.fs#L96

So you'll have to do the benchmarks with a built FSharp.Core, otherwise your code will be at a disadvantage

@cartermp I'm working on perf tests, but having problems referencing the built FSharp.Core. I've added it in the project file:

<ItemGroup>
  <Reference Include="FSharp.Core">
    <HintPath>..\..\..\..\..\artifacts\bin\FSharp.Core\Release\netstandard1.6\FSharp.Core.dll</HintPath>
  </Reference>
</ItemGroup>

However, I don't have access to the new functions, even though they appear in the corresponding FSharp.Core.xml file.

image

Do you have any tips?

@cartermp
Copy link
Contributor

You can look at @dsyme's PR here: #6811

A project file example is here: https://github.com/dotnet/fsharp/pull/6811/files#diff-49b750428326bdfe4736d158ea9d2f78R17

@cmeeren
Copy link
Contributor Author

cmeeren commented Jun 14, 2019

A project file example is here: https://github.com/dotnet/fsharp/pull/6811/files#diff-49b750428326bdfe4736d158ea9d2f78R17

Apologies for my confusion, but that's a project reference, and you said I have to

do the benchmarks with a built FSharp.Core

Perhaps I misunderstood that remark? I figured it meant that I had to reference a pre-compiled DLL. Though, come to think of it, what's the difference - the project is compiled anyway, of course. So what did you mean?

@cartermp
Copy link
Contributor

Sorry, what I meant was just an updated FSharp.Core. Project reference is likely the best way to do that.

@cmeeren
Copy link
Contributor Author

cmeeren commented Jun 15, 2019

I've added performance tests now. Is it what you were after? Again, I've never used BenchmarkDotNet before, so please tell me if I should change anything.

@dsyme
Copy link
Contributor

dsyme commented Jul 1, 2019

I've added performance tests now. Is it what you were after? Again, I've never used BenchmarkDotNet before, so please tell me if I should change anything.

Can you paste the perf results here? Thanks

@cmeeren
Copy link
Contributor Author

cmeeren commented Jul 1, 2019

Here are the benchmark results:

choose

(Some/ValueSome returned for all items)

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17763.557 (1809/October2018Update/Redstone5)
Intel Core i5-4690K CPU 3.50GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=3.0.100-preview5-011568
  [Host]     : .NET Core 3.0.0-preview5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64bit RyuJIT DEBUG
  DefaultJob : .NET Core 3.0.0-preview5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64bit RyuJIT


|      Method |      N |   Type |            Mean |          Error |         StdDev | Ratio |    Gen 0 |    Gen 1 | Gen 2 | Allocated |
|------------ |------- |------- |----------------:|---------------:|---------------:|------:|---------:|---------:|------:|----------:|
|      Option |     10 |    int |        93.30 ns |      0.5223 ns |      0.4885 ns |  1.00 |   0.1861 |        - |     - |     584 B |
| ValueOption |     10 |    int |       105.27 ns |      0.1590 ns |      0.1487 ns |  1.13 |   0.1097 |        - |     - |     344 B |
|             |        |        |                 |                |                |       |          |          |       |           |
|      Option |     10 | record |       153.68 ns |      1.0971 ns |      1.0262 ns |  1.00 |   0.1860 |        - |     - |     584 B |
| ValueOption |     10 | record |       124.45 ns |      0.2014 ns |      0.1572 ns |  0.81 |   0.1097 |        - |     - |     344 B |
|             |        |        |                 |                |                |       |          |          |       |           |
|      Option |   1000 |    int |     9,111.92 ns |     11.8979 ns |     10.5471 ns |  1.00 |  17.8528 |        - |     - |   56024 B |
| ValueOption |   1000 |    int |    10,306.70 ns |     34.8596 ns |     30.9022 ns |  1.13 |  10.2081 |        - |     - |   32024 B |
|             |        |        |                 |                |                |       |          |          |       |           |
|      Option |   1000 | record |    14,170.86 ns |    138.4902 ns |    129.5438 ns |  1.00 |  17.8528 |        - |     - |   56024 B |
| ValueOption |   1000 | record |    11,136.60 ns |     71.5383 ns |     66.9169 ns |  0.79 |  10.2081 |        - |     - |   32024 B |
|             |        |        |                 |                |                |       |          |          |       |           |
|      Option | 100000 |    int | 5,457,377.63 ns | 61,807.4797 ns | 57,814.7549 ns |  1.00 | 914.0625 | 453.1250 |     - | 5600024 B |
| ValueOption | 100000 |    int | 2,318,102.29 ns | 14,083.2867 ns | 13,173.5151 ns |  0.42 | 527.3438 | 253.9063 |     - | 3200024 B |
|             |        |        |                 |                |                |       |          |          |       |           |
|      Option | 100000 | record | 7,846,356.25 ns | 82,262.9530 ns | 76,948.8173 ns |  1.00 | 914.0625 | 453.1250 |     - | 5600024 B |
| ValueOption | 100000 | record | 4,339,809.82 ns | 11,625.5308 ns | 10,305.7302 ns |  0.55 | 523.4375 | 250.0000 |     - | 3200024 B |

tryPick

(None/ValueNone returned for all items)

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17763.557 (1809/October2018Update/Redstone5)
Intel Core i5-4690K CPU 3.50GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=3.0.100-preview5-011568
  [Host]     : .NET Core 3.0.0-preview5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64bit RyuJIT DEBUG
  DefaultJob : .NET Core 3.0.0-preview5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64bit RyuJIT


|      Method |      N |   Type |            Mean |          Error |         StdDev | Ratio |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------ |------- |------- |----------------:|---------------:|---------------:|------:|-------:|------:|------:|----------:|
|      Option |     10 |    int |        18.46 ns |      0.0374 ns |      0.0331 ns |  1.00 | 0.0076 |     - |     - |      24 B |
| ValueOption |     10 |    int |        22.47 ns |      0.0839 ns |      0.0785 ns |  1.22 | 0.0076 |     - |     - |      24 B |
|             |        |        |                 |                |                |       |        |       |       |           |
|      Option |     10 | record |        20.30 ns |      0.0362 ns |      0.0321 ns |  1.00 | 0.0076 |     - |     - |      24 B |
| ValueOption |     10 | record |        24.53 ns |      0.0886 ns |      0.0829 ns |  1.21 | 0.0076 |     - |     - |      24 B |
|             |        |        |                 |                |                |       |        |       |       |           |
|      Option |   1000 |    int |     1,329.67 ns |      3.7526 ns |      3.5102 ns |  1.00 | 0.0076 |     - |     - |      24 B |
| ValueOption |   1000 |    int |     1,552.61 ns |      4.0393 ns |      3.7783 ns |  1.17 | 0.0076 |     - |     - |      24 B |
|             |        |        |                 |                |                |       |        |       |       |           |
|      Option |   1000 | record |     2,885.07 ns |      6.6972 ns |      5.2287 ns |  1.00 | 0.0076 |     - |     - |      24 B |
| ValueOption |   1000 | record |     3,239.33 ns |     23.6545 ns |     22.1264 ns |  1.12 | 0.0076 |     - |     - |      24 B |
|             |        |        |                 |                |                |       |        |       |       |           |
|      Option | 100000 |    int |   133,114.27 ns |    175.1564 ns |    163.8414 ns |  1.00 |      - |     - |     - |      24 B |
| ValueOption | 100000 |    int |   156,501.69 ns |    788.5052 ns |    658.4376 ns |  1.18 |      - |     - |     - |      24 B |
|             |        |        |                 |                |                |       |        |       |       |           |
|      Option | 100000 | record | 2,198,305.01 ns | 22,732.6208 ns | 21,264.1076 ns |  1.00 |      - |     - |     - |      24 B |
| ValueOption | 100000 | record | 2,206,098.84 ns |  5,867.8472 ns |  5,488.7879 ns |  1.00 |      - |     - |     - |      24 B |

I'm confused by the tryPickV results.

@dsyme
Copy link
Contributor

dsyme commented Jul 2, 2019

I'm confused by the tryPickV results.

Likewise! The chooseV case is pretty compelling however

  • Could you also extend the benchmarks to include arrays, where I'd imagine the performance gain would be highest?

  • Could you add unfoldV to the benchmarks please?

thanks!

@thinkbeforecoding
Copy link
Contributor

@dsyme any reason choose is faster than chooseV for an int ? Is there a specific optimization in the rest of the compiler ?

@dsyme
Copy link
Contributor

dsyme commented Jul 2, 2019

@dsyme any reason choose is faster than chooseV for an int ? Is there a specific optimization in the rest of the compiler ?

No. It could be a number of things - alignments, registers 22.47 ns is very short, perhaps run the operation many more times in a loop rather than relying on the benchmarking to do that.

@cartermp
Copy link
Contributor

cartermp commented Jul 2, 2019

@dsyme I wouldn't expect much of a change there, as BenchmarkDotNet is running it enough times such that it's statistically sufficient. Putting in a loop won't be testing the invocation of the function, but a loop that invokes the function.

@cartermp
Copy link
Contributor

cartermp commented Jul 2, 2019

One source of variance is that failing to give your benchmarking process priority on your system can lead to something else getting a higher priority and affecting the benchmark. But since someone's machine isn't necessarily going to assign a similar priority to their own processes, it's arguably not bad to do this. They're close enough in execution time such that users aren't likely to notice either. It's the lack of allocations in the bigger ones where this comes into play.

@cmeeren
Copy link
Contributor Author

cmeeren commented Jul 3, 2019

Here are all results so far:

results.zip

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.17763.557 (1809/October2018Update/Redstone5)
Intel Core i5-4690K CPU 3.50GHz (Haswell), 1 CPU, 4 logical and 4 physical cores
.NET Core SDK=3.0.100-preview5-011568
  [Host]     : .NET Core 3.0.0-preview5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64bit RyuJIT DEBUG
  DefaultJob : .NET Core 3.0.0-preview5-27626-15 (CoreCLR 4.6.27622.75, CoreFX 4.700.19.22408), 64bit RyuJIT

List.choose

Method N Type Mean Error StdDev Ratio Gen 0 Gen 1 Gen 2 Allocated
Option 10 int 94.42ns 0.1014ns 0.0899ns 1.00 0.1861 - - 584B
ValueOption 10 int 106.80ns 0.6133ns 0.5737ns 1.13 0.1097 - - 344B
Option 10 record 156.01ns 0.2104ns 0.1757ns 1.00 0.1860 - - 584B
ValueOption 10 record 131.28ns 0.6983ns 0.6190ns 0.84 0.1097 - - 344B
Option 1000 int 9,182.43ns 20.5495ns 17.1597ns 1.00 17.8528 - - 56024B
ValueOption 1000 int 10,437.64ns 62.0687ns 58.0591ns 1.14 10.2081 - - 32024B
Option 1000 record 14,540.01ns 142.0912ns 132.9122ns 1.00 17.8528 - - 56024B
ValueOption 1000 record 11,293.24ns 38.7614ns 32.3675ns 0.78 10.2081 - - 32024B
Option 100000 int 5,471,929.48ns 27,408.3314ns 25,637.7702ns 1.00 914.0625 453.1250 - 5600024B
ValueOption 100000 int 2,313,274.69ns 4,397.8885ns 3,898.6136ns 0.42 527.3438 257.8125 - 3200024B
Option 100000 record 7,771,535.64ns 57,188.7703ns 47,755.2133ns 1.00 914.0625 453.1250 - 5600024B
ValueOption 100000 record 4,310,785.89ns 12,708.3983ns 11,887.4437ns 0.55 523.4375 250.0000 - 3200024B

List.tryPick

Method N Type Mean Error StdDev Ratio Gen 0 Gen 1 Gen 2 Allocated
Option 10 int 19.09ns 0.0332ns 0.0311ns 1.00 0.0076 - - 24B
ValueOption 10 int 20.50ns 0.0454ns 0.0403ns 1.07 0.0076 - - 24B
Option 10 record 20.35ns 0.0960ns 0.0898ns 1.00 0.0076 - - 24B
ValueOption 10 record 24.65ns 0.0395ns 0.0330ns 1.21 0.0076 - - 24B
Option 1000 int 1,325.98ns 0.2503ns 0.2342ns 1.00 0.0076 - - 24B
ValueOption 1000 int 1,331.45ns 0.1962ns 0.1532ns 1.00 0.0076 - - 24B
Option 1000 record 2,764.38ns 1.8204ns 1.6138ns 1.00 0.0076 - - 24B
ValueOption 1000 record 2,835.19ns 9.8126ns 7.6610ns 1.03 0.0076 - - 24B
Option 100000 int 132,580.58ns 144.3995ns 128.0064ns 1.00 - - - 24B
ValueOption 100000 int 132,973.41ns 778.8675ns 690.4458ns 1.00 - - - 24B
Option 100000 record 2,216,955.89ns 14,799.4768ns 13,119.3507ns 1.00 - - - 24B
ValueOption 100000 record 2,248,968.39ns 16,673.2208ns 15,596.1411ns 1.01 - - - 24B

List.unfoldV

Method N Type Mean Error StdDev Ratio Gen 0 Gen 1 Gen 2 Allocated
Option 10 int 168.1ns 0.3696ns 0.3457ns 1.00 0.2880 - - 904B
ValueOption 10 int 130.2ns 0.8314ns 0.7777ns 0.77 0.2038 - - 640B
Option 10 record 960.9ns 0.6222ns 0.5196ns 1.00 0.8965 - - 2816B
ValueOption 10 record 925.5ns 3.6742ns 3.4369ns 0.96 0.8135 - - 2552B
Option 1000 int 14,569.5ns 198.3009ns 185.4908ns 1.00 25.5280 - - 80104B
ValueOption 1000 int 10,799.1ns 14.3689ns 13.4407ns 0.74 17.8680 - - 56080B
Option 1000 record 123,831.8ns 969.5654ns 809.6310ns 1.00 94.2383 8.4229 - 311696B
ValueOption 1000 record 119,949.1ns 283.9864ns 265.6411ns 0.97 82.2754 10.1318 - 287672B
Option 100000 int 8,290,024.1ns 28,192.7096ns 26,371.4781ns 1.00 1328.1250 640.6250 140.6250 8000104B
ValueOption 100000 int 5,288,396.8ns 32,413.0518ns 30,319.1887ns 0.64 906.2500 453.1250 - 5600080B
Option 100000 record 83,182,436.7ns 314,770.5518ns 294,436.5694ns 1.00 5500.0000 2166.6667 833.3333 31199721B
ValueOption 100000 record 69,257,819.2ns 312,446.7299ns 292,262.8650ns 0.83 5000.0000 1875.0000 750.0000 28799694B

Array.choose

Method N Type Mean Error StdDev Ratio Gen 0 Gen 1 Gen 2 Allocated
Option 10 int 91.53ns 0.1451ns 0.1133ns 1.00 0.1351 - - 424B
ValueOption 10 int 108.10ns 0.5147ns 0.4815ns 1.18 0.0587 - - 184B
Option 10 record 133.37ns 0.2445ns 0.2167ns 1.00 0.1581 - - 496B
ValueOption 10 record 98.35ns 0.0876ns 0.0777ns 0.74 0.0815 - - 256B
Option 1000 int 4,840.96ns 22.3488ns 18.6623ns 1.00 10.2310 - - 32104B
ValueOption 1000 int 7,405.87ns 35.0736ns 32.8078ns 1.53 2.5787 - - 8104B
Option 1000 record 8,812.95ns 54.8451ns 51.3021ns 1.00 12.7563 - - 40096B
ValueOption 1000 record 5,977.79ns 38.8219ns 36.3141ns 0.68 5.1270 - - 16096B
Option 100000 int 1,043,248.68ns 631.5124ns 527.3415ns 1.00 812.5000 48.8281 48.8281 3200104B
ValueOption 100000 int 796,531.26ns 3,272.3305ns 3,060.9400ns 0.76 33.2031 33.2031 33.2031 800362B
Option 100000 record 3,669,541.90ns 9,405.0687ns 8,797.5071ns 1.00 855.4688 93.7500 93.7500 4000096B
ValueOption 100000 record 1,807,609.38ns 4,121.0920ns 3,217.4776ns 0.49 62.5000 62.5000 62.5000 1600585B

Array.tryPick

Method N Type Mean Error StdDev Ratio RatioSD Gen 0 Gen 1 Gen 2 Allocated
Option 10 int 20.04ns 0.0265ns 0.0207ns 1.00 0.00 0.0076 - - 24B
ValueOption 10 int 24.63ns 0.1168ns 0.1035ns 1.23 0.01 0.0076 - - 24B
Option 10 record 22.13ns 0.0491ns 0.0410ns 1.00 0.00 0.0076 - - 24B
ValueOption 10 record 26.02ns 0.1238ns 0.1158ns 1.18 0.01 0.0076 - - 24B
Option 1000 int 1,341.31ns 0.8370ns 0.6535ns 1.00 0.00 0.0076 - - 24B
ValueOption 1000 int 1,604.37ns 21.5298ns 20.1390ns 1.20 0.02 0.0076 - - 24B
Option 1000 record 1,345.73ns 3.8779ns 3.6274ns 1.00 0.00 0.0076 - - 24B
ValueOption 1000 record 1,564.84ns 9.8862ns 8.2555ns 1.16 0.01 0.0076 - - 24B
Option 100000 int 130,971.21ns 16.6883ns 14.7937ns 1.00 0.00 - - - 24B
ValueOption 100000 int 154,674.60ns 857.4426ns 802.0523ns 1.18 0.01 - - - 24B
Option 100000 record 130,992.27ns 26.0676ns 23.1083ns 1.00 0.00 - - - 24B
ValueOption 100000 record 154,725.87ns 603.2300ns 503.7243ns 1.18 0.00 - - - 24B

Array.unfoldV

Method N Type Mean Error StdDev Median Ratio Gen 0 Gen 1 Gen 2 Allocated
Option 10 int 193.6ns 1.2658ns 1.1840ns 192.7ns 1.00 0.2677 - - 840B
ValueOption 10 int 159.4ns 0.2155ns 0.1682ns 159.4ns 0.82 0.1836 - - 576B
Option 10 record 1,035.7ns 2.1101ns 1.6474ns 1,036.4ns 1.00 0.9251 - - 2904B
ValueOption 10 record 995.8ns 1.2365ns 0.9654ns 995.7ns 0.96 0.8411 - - 2640B
Option 1000 int 11,266.9ns 14.1358ns 12.5310ns 11,261.3ns 1.00 19.2871 - - 60528B
ValueOption 1000 int 7,951.1ns 37.8169ns 35.3740ns 7,966.2ns 0.71 11.6272 - - 36504B
Option 1000 record 111,051.4ns 180.9723ns 151.1201ns 110,995.8ns 1.00 91.3086 7.5684 - 304296B
ValueOption 1000 record 121,403.0ns 546.0792ns 510.8028ns 121,615.5ns 1.09 86.3037 3.4180 - 280272B
Option 100000 int 1,447,572.3ns 3,687.5333ns 3,449.3209ns 1,446,928.7ns 1.00 1599.6094 597.6563 398.4375 6249080B
ValueOption 100000 int 1,080,474.8ns 3,697.1373ns 3,277.4159ns 1,081,297.5ns 0.75 849.6094 447.2656 398.4375 3849056B
Option 100000 record 51,535,995.0ns 172,388.6166ns 152,818.0185ns 51,511,740.0ns 1.00 5000.0000 2100.0000 900.0000 30897251B
ValueOption 100000 record 64,791,745.8ns 62,347.7679ns 48,677.0361ns 64,806,100.0ns 1.26 4625.0000 2000.0000 750.0000 28497230B

@realvictorprm
Copy link
Contributor

Why are there still allocations for the ValueSome implementation 🤔 ?

@KevinRansom
Copy link
Member

KevinRansom commented May 16, 2020

These changes look good to me, since they are new APIs to fsharp.core we need to add the
ExperimentalAttribute.

SurfaceArea tests fail.

@dsyme , @cartermp, are we good with adding these Apis.

@KevinRansom KevinRansom reopened this May 16, 2020
@cartermp cartermp marked this pull request as draft May 16, 2020 19:28
@cartermp
Copy link
Contributor

I've converted this into a draft (feature is available now!)

I think I'm fine with the APIs getting added but @dsyme should have a say and this would need to also undergo an RFC

@KevinRansom
Copy link
Member

@cartermp, we should try to move this forward, so we can get some preview time in for it before F# 5.0

@KevinRansom
Copy link
Member

Tests Fixed, and Experimental added.

@KevinRansom
Copy link
Member

/cc @dsyme , @cartermp

Please review this, I think it is ready to merge.

@KevinRansom KevinRansom requested review from cartermp and dsyme May 28, 2020 09:37
Copy link
Member

@KevinRansom KevinRansom left a comment

Choose a reason for hiding this comment

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

These look good to me.

@KevinRansom KevinRansom marked this pull request as ready for review May 28, 2020 09:38
Copy link
Contributor

@cartermp cartermp left a comment

Choose a reason for hiding this comment

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

Putting in a block since fsharp/fslang-suggestions#739 is not an approved change - @dsyme will need to have a say here

@abelbraaksma
Copy link
Contributor

abelbraaksma commented Jul 23, 2020

I'm confused by the tryPickV results.

I had a brief look at why tryPickV is measurably slower here. Since the test basically always returns None or ValueNone for the chooser function, this comes down to the way a match over option vs voption gets compiled.

  • voption, like other struct DUs always calls get_Tag() and compares its result to 0.
  • option, as is well known, compiles into a fast null-test.

As a consequence, even after JIT inlining and optimization, the voption being tested against ValueNone is considerably slower. This could potentially be fixed by optimizing this into a brfalse IL test, since the whole underlying struct is only ever zero when it's also ValueNone. I've created #9767 for that.

I tested some other ways of coding tryPickV but none had a significant advantage. All of them did too many copies and re-assignments (like: the chooser gets re-assigned to a new var inside the resulting while loop), but I didn't check if they were properly folded by the JIT.

Note that the normal overhead of option being a ref type and voption not is irrelevant, as when chooser returns Some or ValueSome, the function returns. Hence only the difference in how [Value]None is treated is relevant, which is slower for voption.

@brettfo brettfo changed the base branch from master to main August 19, 2020 20:04
@KevinRansom
Copy link
Member

@cmeeren
I'm afraid we are trying to prune the inactive but open PR's once again. Please reopen this PR when you have time to pursue and RFC and continue the development.

Thanks

Kevin

@cmeeren
Copy link
Contributor Author

cmeeren commented Jan 22, 2021

I don't see what more I can do; this seems to be approved by everyone except that @dsyme needs to have a look at it (or at least approve fsharp/fslang-suggestions#739).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants