enso/docs/runtime/demand-analysis.md

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

72 lines
2.7 KiB
Markdown
Raw Normal View History

---
layout: developer-doc
title: Demand Analysis
category: runtime
tags: [runtime, demand-analysis, execution]
order: 2
---
2020-04-17 14:12:28 +03:00
# Demand Analysis
2020-07-21 15:59:40 +03:00
2020-04-17 14:12:28 +03:00
Demand analysis is the process of deciding when to compute the value of a
suspended computation in a language which supports suspended computation.
<!-- MarkdownTOC levels="2,3" autolink="true" -->
- [Determining When To Force](#determining-when-to-force)
- [Avoiding Pathological Force-Thunk Chains](#avoiding-pathological-force-thunk-chains)
- [The Demand Analysis Algorithm](#the-demand-analysis-algorithm)
<!-- /MarkdownTOC -->
## Determining When To Force
2020-07-21 15:59:40 +03:00
2020-04-17 14:12:28 +03:00
As Enso supports dynamic dispatch for methods, we cannot always (even in the
2020-07-21 15:59:40 +03:00
presence of a typechecker), statically determine whether or not the function
2020-04-17 14:12:28 +03:00
that will eventually be called at any given call site. This means that we have
2020-07-21 15:59:40 +03:00
to come up with a more efficient way to handle suspended arguments.
2020-04-17 14:12:28 +03:00
This is done by making the _function application_ responsible for determining
when a value passed to it should be evaluated. It works as follows:
1. _All_ function arguments are passed suspended.
2. The function application is provided with knowledge of its argument
declarations.
3. As a result, the _application_ is responsible for deciding which arguments
should be evaluated up front, and which should be deferred.
4. In conjunction with this, the suspended arguments to the application need to
be explicitly forced at their use sites in the function body.
## Avoiding Pathological Force-Thunk Chains
2020-07-21 15:59:40 +03:00
2020-04-17 14:12:28 +03:00
The above approach does, when done naively, result in a severe performance
pathology when passing suspended arguments into functions also expecting
suspended arguments. Without intervention, the suspended argument gets wrapped
in a chain of thunks that has a significant performance cost to resolve, when
necessary.
In order to avoid this issue, we do the following:
1. Where a suspended argument is passed into a function, we pass it _without_
explicitly forcing it.
2. All other uses of that argument are forced.
## The Demand Analysis Algorithm
2020-07-21 15:59:40 +03:00
2020-04-17 14:12:28 +03:00
The algorithm for performing demand analysis on Enso code is as follows.
```
for (node <- ir):
if (node is a usage):
if (node is not used in a function application):
node = force(node)
```
This, however, is not entirely sufficient to support codegen. At the time of
generating truffle code, we want to know whether a given usage in an argument to
a function application needs to be wrapped in a suspension or left alone (as is
the case for a suspended term passed to a function).
To this end, we instead explicitly mark the arguments to the application with
whether or not they should be suspended during codegen.