Performance implications of template-level let bindings

Mod note: As of SDK 1.5.0 Scenarios have been superseded by the more powerful Daml Script. We now recommend using that for all purposes. For more information, and to learn how to use Script please check out @Andreas’ post on our blog.

I like if the compiler raises an error for unused things. In the example below exerciser is used, but the compiler thinks it is not and therefore raises an error.

One way to go about this is to inline it or extract the logic into separate function.

As far as I can tell the two are functionally equivalent. However, I was wondering though if there are any runtime differences, e.g.: performance?

import DA.Assert
import DA.Text (isInfixOf)

template Example
  with
    owner : Party
    observers : [Party]
  where
    signatory owner
    observer observers

    controller (find (hasName "Bob") observers) can
      nonconsuming Something : Int
        do pure 1

    let exerciser = find (hasName "Bob") observers
    controller exerciser can
      nonconsuming SomethingElse : Int
        do pure 2

hasName : Text -> Party -> Bool
hasName name party = name `isInfixOf` partyToText party

testExample : Scenario ()
testExample = scenario do
  owner <- getParty "Alice"
  bob1 <- getParty "Uncle Bob"
  bob2 <- getParty "Bob Martin"
  observers <- forA ["Charlie", "Dalma"] getParty

  example <- owner `submit` create (Example owner (bob1 :: bob2 :: observers))

  x <- bob1 `submit` exercise example Something

  1 === x

  x <- bob1 `submit` exercise example SomethingElse

  2 === x

  submitMustFail bob2 (fetch example)
2 Likes

@Tamas_Kalcza When I try this in scenario I get

Scenario execution failed:
  Invalid party name:  # Bob #
1 Like

So true, thanks. I fixed my example.

1 Like

Hey Tamas! I don’t have an answer for you but wanted to clarify a bit what you’re asking. There appear to be two questions here:

  1. Why you can’t reference variables in a controller clause (the title of the OP Dynamic controllers on choices seems to also suggest this).
  2. Performance implications of inlining vs functions.

Can you clarify a bit whether you’re particularly interested in the controller clause or just performance of inlining vs functions in general?

1 Like

I agree the title is slightly misleading, not very exact. I’m open for suggestions. :slight_smile:

Using variables in controller clause is fine and works. As far as I know this is a known bug that if I harden the DAML build it complains about such a thing being not used while it actually is.

So at this point I’m more interested in the performance (or other) implications of the two approaches.

1 Like

First, a bit of context on the warning: This is coming from -Wunused-binds which is not enabled by default. We are planning to fix the false positive here at some point but didn’t have the time so far. I recommend looking at Making the most out of DAML Compiler warnings for a list of warnings that are useful and don’t cause false positives.

As for performance implications of inlining this, there is no difference here. Template-level let’s are desugared to a let in each choice, signature expression, …. You might be wondering why we don’t just compute it once instead. The reason for this is that there is no place where we could store the result once a contract is created. If a choice is being executed you only have access to the template and the choice argument but we don’t want want to modify either of those.
Of course, if you use it multiple times within the same choice, you probably want to compute it once at the beginning of the choice which is what the template-level let binding will do.

3 Likes

Thanks for the explanation and for the compiler warning link.

1 Like