Closed t0yv0 closed 10 years ago
Merged, thanks!
I like the way it looks, but as you said there is a definite performance penalty incurred because of the intermediate pair
's, wrap
's and fragmented projection. By the way, pair
and wrap
are just surface APIs, I'm certain performance could be improved by utilizing some of the internal, unsafe, pickler constructors, though I'm not sure exactly how.
I took the time to knock together a small script that benchmarks the auto generated pickler against the record combinator as well as a straightforward implementation using wrap
:
let p'' =
Pickler.triple Pickler.string Pickler.int Pickler.string
|> Pickler.wrap
(fun (addr,age,name) -> { Address = addr ; Age = age ; Name = name })
(fun p -> p.Address, p.Age, p.Name)
The script is included in the solution and is called Benchmark.fsx
. I found that the auto-generated pickler slightly beats the wrap
implementation, while the one generated using the record combinator takes approximately 50% more time. Given the fact that the auto-generated pickler uses dynamic methods, I would suspect that there is definite room for improvement.
To answer your question on expression trees, they are strictly used in cases of reflective pickler generation, not as a deforestation agent. Check out ReflectionPicklers.fs
and FsharpPicklers.fs
and the EMIT_IL
conditional in particular. Let me know if you have further questions!
PS. A combinator for union types would be immensely useful, since there is no idiomatic way to declare union picklers in an idiomatic/non-awkward way.
I'm working on the union one. I also have some ideas on improving performance of this - will discuss later. Thanks!
Here are some experimental combinators for records. Note the example.
Probably awfully slow, since involve repeated
pair
andwrap
. Was easy to write though.I did not understand how expression trees are used, is there an ability to run a simplifier on top of a composed pickler somehow? Some algebraic laws could help reduce the intermediate
pair
+wrap
.