-
Notifications
You must be signed in to change notification settings - Fork 323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Convert Array_Like_Helpers.map
to a builtin to reduce stack size
#11363
Conversation
The experiment in Stack_Size_Spec.enso generates code for nested
Which means that, e.g., a
I am not sure yet what to do with that experiment. We should probably integrate it somehow later as a regression test. |
990ee6a introduces a regression test diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso
index 4ce7c5bdb4..27c9bed438 100644
--- a/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso
+++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Data/Vector.enso
@@ -700,7 +700,7 @@ type Vector a
[1, 2, 3] . map +1
map : (Any -> Any) -> Problem_Behavior | No_Wrap -> Vector Any
map self function on_problems:(Problem_Behavior | No_Wrap)=..Report_Error =
- Array_Like_Helpers.map self function on_problems
+ @Tail_Call Array_Like_Helpers.map self function on_problems
## ICON union
Applies a function to each element of the vector, returning the `Vector`
diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso
index aaf2442940..416be3d4a5 100644
--- a/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso
+++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Internal/Array_Like_Helpers.enso
@@ -229,7 +229,7 @@ transpose vec_of_vecs =
Vector.from_polyglot_array proxy
map vector function on_problems =
- vector_from_function vector.length (i-> function (vector.at i)) on_problems
+ @Tail_Call vector_from_function vector.length (i-> function (vector.at i)) on_problems
map_with_index vector function on_problems =
vector_from_function vector.length (i-> function i (vector.at i)) on_problems
the number of stack frames is 22, with the disadvantage that the |
...e/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/VectorFromFunctionNode.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few code comments inlined.
At the end, I have decided not to add the @Tail_Call annotations there for now. I think that the reduction of 35 Java stack frames per Vector.map method call is sufficient improvement.
I don't think I agree with such decision. I am more concerned about performance and avoiding StackoverflowError
than the shape of the stack. Moreover ...
the number of stack frames is 22, with the disadvantage that the Vector.map call is not visible in Runtime.get_stack_trace.
...if we want to see something that resembles Vector.map
in the stack, then rename Array_Like_Helpers
to Vector_Impl
and vector_from_function
to map
and we'll get a reasonable stack names while keeping the stack size down to 22
.
...e/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/VectorFromFunctionNode.java
Outdated
Show resolved
Hide resolved
...e/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/VectorFromFunctionNode.java
Outdated
Show resolved
Hide resolved
@Cached BranchProfile errorEncounteredProfile) { | ||
var ctx = EnsoContext.get(this); | ||
var onProblems = processOnProblemsArg(onProblemsAtom, typesLib); | ||
var len = Math.toIntExact(length); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will happen on ArithmeticException
? It shouldn't crash the interpreter.
...e/runtime/src/main/java/org/enso/interpreter/runtime/data/vector/VectorFromFunctionNode.java
Show resolved
Hide resolved
import org.enso.interpreter.dsl.BuiltinType; | ||
import org.enso.interpreter.node.expression.builtin.Builtin; | ||
|
||
@BuiltinType(name = "Standard.Base.Data.Vector.No_Wrap") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Off-topic, but I'd like to know the answer: What is name
attribute optional? It is specified on some of the builtins, but not on all. Shouldn't it be specified all the time? I am asking because of
the proposed Standard.Prelude
should include all the builtins and their methods, but we want to have their names exactly the same as in Standard.Base
- can we generate such a Prelude.enso
from these annotations?
|
Another benchmarks scheduled at:
|
Caching onProblems argument apparently helped: |
I'd like to point out that #11365 is going to change the way we do if_bench_6_in vec =
vec.fold 0 acc-> curr->
curr.f1.not.if_then_else acc <|
curr.f2.not.if_then_else acc <|
curr.f3.not.if_then_else acc <|
curr.f4.not.if_then_else acc <|
curr.f5.not.if_then_else acc <|
curr.f6.not.if_then_else acc <|
acc + 1 The ifBench6In benchmark is doing exactly that! It invokes the If slowdown in ifBench6In benchmark is the only blocker, then I suggest to ignore it. |
Another locally verified regression of diff --git a/engine/runtime-benchmarks/src/main/java/org/enso/interpreter/bench/benchmarks/semantic/TypePatternBenchmarks.java b/engine/runtime-benchmarks/src/main/java/org/enso/interpreter/bench/benchmarks/semantic/TypePatternBenchmarks.java
index 9343bd153..97a742657 100644
--- a/engine/runtime-benchmarks/src/main/java/org/enso/interpreter/bench/benchmarks/semantic/TypePatternBenchmarks.java
+++ b/engine/runtime-benchmarks/src/main/java/org/enso/interpreter/bench/benchmarks/semantic/TypePatternBenchmarks.java
@@ -66,7 +66,7 @@ public class TypePatternBenchmarks {
Function<String, Value> getMethod = (name) -> module.invokeMember(Module.EVAL_EXPRESSION, name);
- var length = 100;
+ var length = 100_000;
this.vec = getMethod.apply("gen_vec").execute(length, 1.1);
switch (SrcUtil.findName(params)) {
case "matchOverAny" -> this.patternMatch = getMethod.apply("match_any"); On develop: 0.213 ± 0.020 |
Regressions resolved. Turns out I was caching the |
# Conflicts: # distribution/lib/Standard/Base/0.0.0-dev/src/Network/HTTP.enso
Wait for the tests to be green and then, let's schedule another round of benchmarks |
Benchmark may run even without tests to be fully green. Trying to run the benchmarks right now might speed things up. |
Benchmarks scheduled:
|
All (stable) benchmarks are either the same, or better, let's integrate. |
…11363) The ultimate goal is to reduce the method calls necessary for `Vector.map`. # Important Notes - I managed to reduce the number of Java stack frames needed for each `Vector.map` call from **150** to **22** (See #11363 (comment)) - Introduced `Stack_Size_Spec` regression test that will ensure that Java stack frames needed for `Vector.map` method call does not exceed **40**.
Fixes #11329
Pull Request Description
The ultimate goal is to reduce the method calls necessary for
Vector.map
.Important Notes
Vector.map
call from 150 to 22 (See ConvertArray_Like_Helpers.map
to a builtin to reduce stack size #11363 (comment))Stack_Size_Spec
regression test that will ensure that Java stack frames needed forVector.map
method call does not exceed 40.Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:
Scala,
Java,