Skip to content

Commit

Permalink
FSharp.Core: Map: optimize tree layout (#10188)
Browse files Browse the repository at this point in the history
* FSharp.Core: Map: optimize tree layout

Following discussion and POC code from #5360 (comment)

Changes are very straightforward and do not touch public API:

* Performance improves by a huge margin
* Code size is smaller or same
* Memory is same
* No low level tricks, just simple code (see `asNode` comments for potential micro-optimizations, which are not visible after all; these comments are to be deleted)

Benchmarks code is here: https://github.com/buybackoff/fsharp-benchmarks

|      Method |    Job | BuildConfiguration |     Size |              Mean |            Error |           StdDev | Rank |      Gen 0 |    Gen 1 |   Gen 2 |   Allocated | Code Size |
|------------ |------- |------------------- |--------- |------------------:|-----------------:|-----------------:|-----:|-----------:|---------:|--------:|------------:|----------:|
|     getItem |  After |         LocalBuild |      100 |          36.21 ns |         0.199 ns |         0.167 ns |    1 |          - |        - |       - |           - |     126 B |
|     getItem | Before |            Default |      100 |          62.51 ns |         0.143 ns |         0.127 ns |    2 |          - |        - |       - |           - |     126 B |
|     getItem |  After |         LocalBuild |    10000 |          76.57 ns |         0.140 ns |         0.124 ns |    3 |          - |        - |       - |           - |     126 B |
|     getItem | Before |            Default |    10000 |         120.02 ns |         0.182 ns |         0.170 ns |    4 |          - |        - |       - |           - |     126 B |
|     getItem |  After |         LocalBuild | 10000000 |         129.45 ns |         0.126 ns |         0.118 ns |    5 |          - |        - |       - |           - |     126 B |
|     getItem | Before |            Default | 10000000 |         209.35 ns |         0.496 ns |         0.464 ns |    6 |          - |        - |       - |           - |     126 B |
|             |        |                    |          |                   |                  |                  |      |            |          |         |             |           |
| containsKey |  After |         LocalBuild |      100 |          35.63 ns |         0.201 ns |         0.188 ns |    1 |          - |        - |       - |           - |     177 B |
| containsKey | Before |            Default |      100 |          64.01 ns |         0.351 ns |         0.328 ns |    2 |          - |        - |       - |           - |     276 B |
| containsKey |  After |         LocalBuild |    10000 |          65.63 ns |         0.150 ns |         0.125 ns |    3 |          - |        - |       - |           - |     177 B |
| containsKey | Before |            Default |    10000 |         123.82 ns |         0.149 ns |         0.139 ns |    5 |          - |        - |       - |           - |     276 B |
| containsKey |  After |         LocalBuild | 10000000 |          95.05 ns |         0.082 ns |         0.072 ns |    4 |          - |        - |       - |           - |     177 B |
| containsKey | Before |            Default | 10000000 |         204.39 ns |         0.338 ns |         0.282 ns |    6 |          - |        - |       - |           - |     276 B |
|             |        |                    |          |                   |                  |                  |      |            |          |         |             |           |
|   itemCount |  After |         LocalBuild |      100 |         231.39 ns |         0.406 ns |         0.360 ns |    1 |          - |        - |       - |           - |      96 B |
|   itemCount | Before |            Default |      100 |         539.74 ns |         1.923 ns |         1.798 ns |    2 |          - |        - |       - |           - |     151 B |
|   itemCount |  After |         LocalBuild |    10000 |      33,160.50 ns |       194.709 ns |       182.131 ns |    3 |          - |        - |       - |           - |      96 B |
|   itemCount | Before |            Default |    10000 |      63,074.34 ns |       138.682 ns |       129.724 ns |    4 |          - |        - |       - |           - |     151 B |
|   itemCount |  After |         LocalBuild | 10000000 |  62,332,911.90 ns |   252,973.481 ns |   224,254.402 ns |    5 |          - |        - |       - |       148 B |      96 B |
|   itemCount | Before |            Default | 10000000 |  94,745,625.56 ns |   205,640.690 ns |   192,356.429 ns |    6 |          - |        - |       - |           - |     151 B |
|             |        |                    |          |                   |                  |                  |      |            |          |         |             |           |
| iterForeach |  After |         LocalBuild |      100 |       3,355.75 ns |         9.540 ns |         7.448 ns |    1 |     0.9727 |        - |       - |      6120 B |     291 B |
| iterForeach | Before |            Default |      100 |       3,866.56 ns |        10.148 ns |         8.996 ns |    2 |     0.9689 |        - |       - |      6120 B |     291 B |
| iterForeach |  After |         LocalBuild |    10000 |     348,359.43 ns |     1,148.753 ns |       959.260 ns |    3 |    95.2148 |        - |       - |    600120 B |     291 B |
| iterForeach | Before |            Default |    10000 |     398,419.61 ns |       513.959 ns |       480.758 ns |    4 |    95.2148 |        - |       - |    600120 B |     291 B |
| iterForeach |  After |         LocalBuild | 10000000 | 391,889,200.00 ns | 1,604,306.946 ns | 1,500,669.712 ns |    5 | 95000.0000 |        - |       - | 600000120 B |     321 B |
| iterForeach | Before |            Default | 10000000 | 445,099,028.57 ns | 1,380,498.715 ns | 1,223,776.153 ns |    6 | 95000.0000 |        - |       - | 600000120 B |     321 B |
|             |        |                    |          |                   |                  |                  |      |            |          |         |             |           |
|     addItem |  After |         LocalBuild |      100 |         181.25 ns |         0.961 ns |         0.899 ns |    1 |     0.0586 |   0.0003 |       - |       369 B |     621 B |
|     addItem | Before |            Default |      100 |         311.85 ns |         0.601 ns |         0.562 ns |    2 |     0.0586 |        - |       - |       369 B |     697 B |
|     addItem |  After |         LocalBuild |    10000 |      40,893.49 ns |       174.683 ns |       163.398 ns |    3 |    11.0156 |   3.2813 |       - |     69324 B |     621 B |
|     addItem | Before |            Default |    10000 |      71,746.33 ns |       130.309 ns |       121.891 ns |    4 |    11.0156 |   3.3594 |       - |     69324 B |     697 B |
|     addItem |  After |         LocalBuild | 10000000 |  87,178,251.47 ns |   250,148.324 ns |   233,988.898 ns |    5 | 18680.0000 | 960.0000 | 10.0000 | 117146915 B |     621 B |
|     addItem | Before |            Default | 10000000 | 146,799,424.80 ns |   286,531.195 ns |   268,021.458 ns |    6 | 18680.0000 | 960.0000 | 10.0000 | 117146915 B |     697 B |
|             |        |                    |          |                   |                  |                  |      |            |          |         |             |           |
|  removeItem |  After |         LocalBuild |      100 |          13.64 ns |         0.112 ns |         0.105 ns |    1 |     0.0064 |        - |       - |        40 B |     469 B |
|  removeItem | Before |            Default |      100 |          16.38 ns |         0.071 ns |         0.067 ns |    2 |     0.0064 |        - |       - |        40 B |     519 B |
|  removeItem |  After |         LocalBuild |    10000 |       1,329.24 ns |         9.087 ns |         8.056 ns |    3 |     0.6372 |        - |       - |      4000 B |     469 B |
|  removeItem | Before |            Default |    10000 |       1,607.21 ns |         5.566 ns |         5.206 ns |    4 |     0.6372 |        - |       - |      4000 B |     519 B |
|  removeItem |  After |         LocalBuild | 10000000 |   1,232,230.00 ns |     6,303.414 ns |     5,896.218 ns |    5 |   630.0000 |        - |       - |   4000000 B |     469 B |
|  removeItem | Before |            Default | 10000000 |   1,801,088.33 ns |     8,945.674 ns |     8,367.789 ns |    6 |   630.0000 |        - |       - |   4000000 B |     519 B |

* Simplify node ctors

* FSharp.Core: Map: delete notes in asNode

* FSharp.Core: Map: fix typo in spliceOutSuccessor

* FSharp.Core: Map: remove unused open
  • Loading branch information
buybackoff committed Sep 26, 2020
1 parent 81d1d91 commit 77687e3
Show file tree
Hide file tree
Showing 2 changed files with 289 additions and 267 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -138,3 +138,5 @@ msbuild.binlog
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*

.idea

0 comments on commit 77687e3

Please sign in to comment.