Skip to content

Commit

Permalink
Performance improvements for Comparators (#5687)
Browse files Browse the repository at this point in the history
Critical performance improvements after #4067

# Important Notes
- Replace if-then-else expressions in `Any.==` with case expressions.
- Fix caching in `EqualsNode`.
- This includes fixing specializations, along with fallback guard.
  • Loading branch information
Akirathan committed Feb 21, 2023
1 parent 6dddc53 commit 58c7ca5
Show file tree
Hide file tree
Showing 10 changed files with 462 additions and 162 deletions.
22 changes: 13 additions & 9 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Any.enso
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,20 @@ type Any
# host or polyglot values, so we just compare them with the default comparator.
eq_self = Panic.catch No_Such_Conversion (Comparable.from self) _-> Default_Unordered_Comparator
eq_that = Panic.catch No_Such_Conversion (Comparable.from that) _-> Default_Unordered_Comparator
if Meta.is_same_object eq_self Incomparable then False else
similar_type = Meta.is_same_object eq_self eq_that
if similar_type.not then False else
case eq_self.is_ordered of
case Meta.is_same_object eq_self Incomparable of
True -> False
False ->
similar_type = Meta.is_same_object eq_self eq_that
case similar_type of
False -> False
True ->
# Comparable.equals_builtin is a hack how to directly access EqualsNode from the
# engine, so that we don't end up in an infinite recursion here (which would happen
# if we would compare with `eq_self == eq_that`).
Comparable.equals_builtin (eq_self.compare self that) Ordering.Equal
False -> eq_self.equals self that
case eq_self.is_ordered of
True ->
# Comparable.equals_builtin is a hack how to directly access EqualsNode from the
# engine, so that we don't end up in an infinite recursion here (which would happen
# if we would compare with `eq_self == eq_that`).
Comparable.equals_builtin (eq_self.compare self that) Ordering.Equal
False -> eq_self.equals self that

## ALIAS Inequality

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import project.Data.Ordering.Ordering
import project.Data.Ordering.Comparable
import project.Data.Ordering.Incomparable
import project.Data.Ordering.Default_Ordered_Comparator
import project.Data.Text.Text
import project.Data.Locale.Locale
Expand Down Expand Up @@ -940,7 +941,10 @@ type Integer

parse_builtin text radix = @Builtin_Method "Integer.parse"

Comparable.from (_:Number) = Default_Ordered_Comparator
Comparable.from (that:Number) =
case that.is_nan of
True -> Incomparable
False -> Default_Ordered_Comparator

## UNSTABLE

Expand Down
13 changes: 10 additions & 3 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Ordering.enso
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import project.Error.Unimplemented.Unimplemented
import project.Nothing
import project.Meta
import project.Meta.Atom
import project.Panic.Panic
from project.Data.Boolean import all

## Provides custom ordering, equality check and hash code for types that need it.
Expand Down Expand Up @@ -165,9 +166,15 @@ type Default_Ordered_Comparator
## Handles only primitive types, not atoms or vectors.
compare : Any -> Any -> Ordering
compare x y =
if Comparable.less_than_builtin x y then Ordering.Less else
if Comparable.equals_builtin x y then Ordering.Equal else
if Comparable.less_than_builtin y x then Ordering.Greater
case Comparable.less_than_builtin x y of
True -> Ordering.Less
False ->
case Comparable.equals_builtin x y of
True -> Ordering.Equal
False ->
case Comparable.less_than_builtin y x of
True -> Ordering.Greater
False -> Panic.throw "Unreachable"

hash : Number -> Integer
hash x = Comparable.hash_builtin x
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ get key = @Builtin_Method "State.get"
- key: The key with which to associate the new state.
- new_state: The new state to store.

Returns an uninitialized state error if the user tries to read from an
Returns an uninitialized state error if the user tries to put into an
uninitialized slot.

> Example
Expand Down
Loading

0 comments on commit 58c7ca5

Please sign in to comment.