Skip to content

Commit

Permalink
perf: improved by not doing unnescessary work in ValueUnit
Browse files Browse the repository at this point in the history
  • Loading branch information
Casper Bollen authored and Casper Bollen committed Oct 20, 2023
1 parent 137dcf8 commit ae6e0c7
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
```
BenchmarkDotNet v0.13.9+228a464e8be6c580ad9408e98f18813f6407fb5a, macOS Sonoma 14.0 (23A344) [Darwin 23.0.0]
Apple M2 Max, 1 CPU, 12 logical and 12 physical cores
.NET SDK 6.0.415
[Host] : .NET 6.0.23 (6.0.2323.48002), Arm64 RyuJIT AdvSIMD DEBUG
DefaultJob : .NET 6.0.23 (6.0.2323.48002), Arm64 RyuJIT AdvSIMD
```
| Method | Mean | Error | StdDev |
|------------------------ |----------:|---------:|---------:|
| BaseValue_200 | 41.12 ms | 0.661 ms | 0.618 ms |
| AllPairs_True_100 | 25.70 ms | 0.089 ms | 0.083 ms |
| AllPairs_True_200 | 129.14 ms | 0.579 ms | 0.513 ms |
| AllPairs_True_Rand_100 | 127.78 ms | 0.404 ms | 0.378 ms |
| AllPairs_False_Rand_200 | 623.85 ms | 4.947 ms | 4.627 ms |
| AllPairs_True_Rand_200 | 624.27 ms | 2.291 ms | 2.031 ms |
86 changes: 80 additions & 6 deletions benchmark/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ type BigRationalBenchmarks () =
let div = calc (/)

[<Benchmark>]
member this.AllPairsBR_100 () =
member this.AllPairs_100 () =
let x1, x2 = allPairs_100
add x1 x2 |> ignore
sub x1 x2 |> ignore
Expand All @@ -173,7 +173,7 @@ type BigRationalBenchmarks () =


[<Benchmark>]
member this.AllPairsBR_200 () =
member this.AllPairs_200 () =
let x1, x2 = allPairs_200

add x1 x2 |> ignore
Expand All @@ -183,7 +183,7 @@ type BigRationalBenchmarks () =


[<Benchmark>]
member this.AllPairsBR_Rand_100 () =
member this.AllPairs_Rand_100 () =
let x1, x2 = rand_100_a, rand_100_b

add x1 x2 |> ignore
Expand All @@ -193,7 +193,7 @@ type BigRationalBenchmarks () =


[<Benchmark>]
member this.AllPairsBR_Rand_200 () =
member this.AllPairs_Rand_200 () =
let x1, x2 = rand_200_a, rand_200_b

add x1 x2 |> ignore
Expand Down Expand Up @@ -222,6 +222,75 @@ type ValueUnitBenchmarks () =
Utils.getTwoRandomLists 200 1_000
|> fun (x1, x2) -> ValueUnit.create Units.Count.times x1, ValueUnit.create Units.Count.times x2

let calc b op x1 x2 = ValueUnit.calc b op x1 x2 //x1 |> op <| x2

let add b = calc b (+)
let sub b = calc b (-)
let mul b = calc b (*)
let div b = calc b (/)

let calcBR op x1 x2 =
Array.allPairs x1 x2
|> Array.map (fun (x1, x2) -> x1 |> op <| x2)
|> Array.distinct


[<Benchmark>]
member this.BaseValue_200 () =
let vu1, vu2 = allPairs_200
let x1 = vu1 |> ValueUnit.toBaseValue
let x2 = vu2 |> ValueUnit.toBaseValue

calcBR (+) x1 x2 |> ignore
calcBR (-) x1 x2 |> ignore
calcBR (*) x1 x2 |> ignore
calcBR (/) x1 x2 |> ignore


[<Benchmark>]
member this.AllPairs_True_100 () =
let x1, x2 = allPairs_100
add true x1 x2 |> ignore
sub true x1 x2 |> ignore
mul true x1 x2 |> ignore
div true x1 x2 |> ignore


[<Benchmark>]
member this.AllPairs_True_200 () =
let x1, x2 = allPairs_200
add true x1 x2 |> ignore
sub true x1 x2 |> ignore
mul true x1 x2 |> ignore
div true x1 x2 |> ignore


[<Benchmark>]
member this.AllPairs_True_Rand_100 () =
let x1, x2 = rand_100_a, rand_100_b
add true x1 x2 |> ignore
sub true x1 x2 |> ignore
mul true x1 x2 |> ignore
div true x1 x2 |> ignore


[<Benchmark>]
member this.AllPairs_False_Rand_200 () =
let x1, x2 = rand_200_a, rand_200_b
add false x1 x2 |> ignore
sub false x1 x2 |> ignore
mul false x1 x2 |> ignore
div false x1 x2 |> ignore


[<Benchmark>]
member this.AllPairs_True_Rand_200 () =
let x1, x2 = rand_200_a, rand_200_b
add true x1 x2 |> ignore
sub true x1 x2 |> ignore
mul true x1 x2 |> ignore
div true x1 x2 |> ignore




Expand Down Expand Up @@ -366,12 +435,17 @@ let main (args: string[]) =
| [|s|] when s = "pr" -> EquationBenchmarks().Print()

| [|s|] when s = "br" ->
printfn "Starting to run benchmarks"
printfn "Starting to run BigRational benchmarks"
let _ = BenchmarkRunner.Run<BigRationalBenchmarks>()
printfn "Finished running benchmarks"

| [|s|] when s = "vu" ->
printfn "Starting to run ValueUnit benchmarks"
let _ = BenchmarkRunner.Run<ValueUnitBenchmarks>()
printfn "Finished running benchmarks"

| [|s|] when s = "eq" ->
printfn "Starting to run benchmarks"
printfn "Starting to run Equation benchmarks"
let _ = BenchmarkRunner.Run<EquationBenchmarks>()
printfn "Finished running benchmarks"
| _ ->
Expand Down
64 changes: 39 additions & 25 deletions src/Informedica.GenUnits.Lib/ValueUnit.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2427,7 +2427,11 @@ module ValueUnit =
/// Get the value of a ValueUnit as
/// a base value.
/// For example ValueUnit(1000, mg) -> 1
let toBaseValue (ValueUnit (v, u)) = v |> Array.map (valueToBase u)
let toBaseValue vu =
let v, u = vu |> get
if u |> Multipliers.getMultiplier = 1N then v
else
v |> Array.map (valueToBase u)


/// Convert a value to v to the
Expand All @@ -2440,21 +2444,29 @@ module ValueUnit =

/// Get the value of a ValueUnit as
/// a unit value ValueUnit(1, mg) -> 1000
let toUnitValue (ValueUnit (v, u)) = v |> Array.map (valueToUnit u)
let toUnitValue vu =
let v, u = vu |> get
if u |> Multipliers.getMultiplier = 1N then v
else
v |> Array.map (valueToUnit u)


/// Replace the Value in a ValueUnit to its base.
/// For example ValueUnit(1000, mg) -> ValueUnit(1, mg)
let toBase vu =
let v, u = vu |> get
v |> Array.map (valueToBase u) |> create u
if u |> Multipliers.getMultiplier = 1N then vu
else
v |> Array.map (valueToBase u) |> create u


/// Transforms a ValueUnit to its unit.
/// For example ValueUnit(1, mg) -> ValueUnit(1000, mg)
let toUnit vu =
let v, u = vu |> get
v |> Array.map (valueToUnit u) |> create u
if u |> Multipliers.getMultiplier = 1N then vu
else
v |> Array.map (valueToUnit u) |> create u


/// Make sure that a ValueUnit has a positive value
Expand Down Expand Up @@ -2608,28 +2620,30 @@ module ValueUnit =

(false, NoUnit)
|> build ns ds
|> (fun (_, u) ->
vu
|> toBaseValue
|> create u
|> toUnitValue
|> create u
)
// rewrite case u1/u2 * u3 -> u1/u2/u3 when group u2 <> group u3
|> fun vu ->
let v, u =
|> fun (_, u1) ->
// nothing changed so just return original
if u = u1 then vu
else
vu
|> get
let u =
match u with
| CombiUnit(u1, OpPer, CombiUnit(u2, OpTimes, u3)) ->
if u2 |> Group.eqsGroup u3 then
u
else
CombiUnit(CombiUnit(u1, OpPer, u2), OpPer, u3)
| _ -> u

v |> withUnit u
|> toBaseValue
|> create u1
|> toUnitValue
|> create u1
// rewrite case u1/u2 * u3 -> u1/u2/u3 when group u2 <> group u3
|> fun vu ->
let v, u =
vu
|> get
let u =
match u with
| CombiUnit(u1, OpPer, CombiUnit(u2, OpTimes, u3)) ->
if u2 |> Group.eqsGroup u3 then
u
else
CombiUnit(CombiUnit(u1, OpPer, u2), OpPer, u3)
| _ -> u

v |> withUnit u


/// <summary>
Expand Down

0 comments on commit ae6e0c7

Please sign in to comment.