Skip to content

Optimize DateTime comparison/equality - #9224

Merged
KevinRansom merged 3 commits into
dotnet:masterfrom
cartermp:ib-datetime-compare
May 27, 2020
Merged

Optimize DateTime comparison/equality#9224
KevinRansom merged 3 commits into
dotnet:masterfrom
cartermp:ib-datetime-compare

Conversation

@cartermp

@cartermpcartermp commented May 18, 2020

Copy link
Copy Markdown
Contributor

In a trace from here: https://developercommunity.visualstudio.com/content/problem/1035124/trace-of-editing-experience-with-in-memory-cross-p-1.html

I found that ComputeMaxTimeStamp was allocating a lot of DateTimes, stemming from the call to max:

image

This replaced it with a call to DateTime.Compare, which won't allocate.

After talking with @TIHan and @KevinRansom, this added some DateTime specializations to FSharp.Core so that equality, comparison, min, max, etc. all specialize to the right method rather than box the DateTime structs.

@cartermp

Copy link
Copy Markdown
ContributorAuthor

This is a small benchmark program I used to compare the two:

openSystemopenBenchmarkDotNet.AttributesopenBenchmarkDotNet.Running[<MemoryDiagnoser>]typeDateTimeBench()=letmaxTime= DateTime.MaxValue
letdata=[for x in0..100->
DateTime (int64 x)][<Benchmark(Baseline=true)>]member_.UsingMax()=let recf xs acc =match xs with|[]-> acc
| h::t -> f t (max acc h)
f data maxTime
[<Benchmark>]member_.UsingDateTimeCompare()=let recf xs acc =match xs with|[]-> acc
| h::t ->letres= DateTime.Compare(acc, h)if res >=0then
f t acc
else
f t h
f data maxTime
[<EntryPoint>]letmain argv =letsummary= BenchmarkRunner.Run<DateTimeBench>()
printfn "%A" summary
0// return an integer exit code

It yielded these results:

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.836 (1909/November2018Update/19H2)
Intel Core i7-6700K CPU 4.00GHz (Skylake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=5.0.100-preview.4.20258.7
[Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.25106, CoreFX 5.0.20.25106), X64 RyuJIT DEBUG
DefaultJob : .NET Core 5.0.0 (CoreCLR 5.0.20.25106, CoreFX 5.0.20.25106), X64 RyuJIT
MethodMeanErrorStdDevRatioGen 0Gen 1Gen 2Allocated
UsingMax2,738.80 ns21.445 ns20.059 ns1.001.1559--4848 B
UsingDateTimeCompare98.42 ns0.234 ns0.207 ns0.04----

@cartermp
cartermp requested review from TIHan and dsymeMay 18, 2020 02:32
@forki

Copy link
Copy Markdown
Contributor

wow - rewrite rule for Optimizer? ;-)

@cartermp

Copy link
Copy Markdown
ContributorAuthor

I think the more appropriate general purpose fix is to get these generic functions to stop allocating on structs that aren't specialized in FSharp.Core

@cartermpcartermp changed the title Replace 'max' with DateTime.Compare in ComputeMaxTimeStampOptimize DateTime comparison/equalityMay 19, 2020
@KevinRansom

Copy link
Copy Markdown
Contributor

@cartermp did you run the perftest with max using this fix?

@cartermp

Copy link
Copy Markdown
ContributorAuthor

The test failures are from baseline comparisons against the emitted IL in the fsharpqa suite. How does babby update?

@smoothdeveloper

Copy link
Copy Markdown
Contributor

@cartermp you should be able to use https://github.com/dotnet/fsharp/blob/master/TESTGUIDE.md#baselines after seeing the tests fail locally.

@KevinRansom

Copy link
Copy Markdown
Contributor

Updated failing baselines

@KevinRansom
KevinRansom merged commit 5bdf402 into dotnet:masterMay 27, 2020

@TIHanTIHan left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the test changes are good, but I think we don't need to update FSharp.Core. We simply need to do devirtualization on equality and comparison and just emit the equals. Here was the PR when devirting equality, #6175. We could expand it to comparison.

This sort of thing needs to be expanded to all struct types...

@TIHan

Copy link
Copy Markdown
Contributor

Seems I was a little too late as this was merged 2 minutes before submitting my review.

@cartermp

Copy link
Copy Markdown
ContributorAuthor

Now I'm confused - @TIHan@KevinRansom what we discussed was that we would place these in FSharp.Core, which is why I made this adjustment rather than keeping them in the compiler. This was because it's an easy improvement with no apparent problems, whereas #6175 and extensions to it would be too tricky and time-consuming to land right now. Or am I mistaken in my recollection of that discussion?

@KevinRansom

Copy link
Copy Markdown
Contributor

@cartermp , your recollection matches mine. I think we need a backlog item to make the change that will is thinking about. However, that requires time to design, bake and think through.
So your change is good, and I propose to leave it in.

nosami pushed a commit to xamarin/visualfsharp that referenced this pull request Feb 23, 2021
* Replace 'max' with DateTime.Compare in ComputeMaxTimeStamp
* Generalize datetime in fsharp.core
* baselines
Co-authored-by: Kevin Ransom <codecutter@hotmail.com>
Sign up for freeto 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.

5 participants

@cartermp@forki@KevinRansom@smoothdeveloper@TIHan