Skip to content

Commit

Permalink
optimization: avoid NotGiven allocations (#17090)
Browse files Browse the repository at this point in the history
## Problem

I've been working on a library that uses `NotGiven` in the hot path,
which ends up producing an extra allocation on every use. I thought JIT
compilation would be able to optimize it away but that isn't the case in
some benchmarks. For example:

Benchmark:
https://github.com/fwbrasil/kyo/blob/main/kyo-bench/src/main/scala/kyo/bench/NarrowBindMapBench.scala
Flamegraph:
https://getkyo.io/dev/profile/4990c20/kyo.bench.NarrowBindMapBench.forkKyo-Throughput/flame-cpu-forward.html

## Solution

Make `NotGiven.value` a `val` instead of `def`.

## Notes

- I'm assuming the identity of a `NotGiven` object isn't relevant.
- Should I use an internal field and keep `NotGiven.value` as `def` to
avoid binary compatibility issues?
  • Loading branch information
smarter authored Mar 15, 2023
2 parents 29e229b + 421591f commit 18259db
Showing 1 changed file with 3 additions and 1 deletion.
4 changes: 3 additions & 1 deletion library/src/scala/util/NotGiven.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ trait LowPriorityNotGiven {
}
object NotGiven extends LowPriorityNotGiven {

private val cachedValue = new NotGiven[Nothing]()

/** A value of type `NotGiven` to signal a successful search for `NotGiven[C]` (i.e. a failing
* search for `C`). A reference to this value will be explicitly constructed by Dotty's
* implicit search algorithm
*/
def value: NotGiven[Nothing] = new NotGiven[Nothing]()
def value: NotGiven[Nothing] = cachedValue

/** One of two ambiguous methods used to emulate negation in Scala 2 */
given amb1[T](using ev: T): NotGiven[T] = ???
Expand Down

0 comments on commit 18259db

Please sign in to comment.