Zulip Chat Archive
Stream: lean4
Topic: maxHeartbeats in ContextInfo.runMetaM
Adam Topaz (Nov 02 2024 at 14:25):
I'm trying to run a fairly expensive computation in the MetaM monad by visiting some nodes in an infotree and using Lean.Elab.ContextInfo.runMetaM. I tried setting the maxHeartbeats to 0, but I'm still hitting deterministic timeouts. I think I must be doing something wrong in setting the maxHeartbeats option. Here is a somewhat minimal example:
import Lean
open Lean Elab Frontend
def main : IO Unit := do
searchPathRef.set compile_time_search_path%
unsafe enableInitializersExecution
let input ← IO.FS.readFile ".lake/packages/mathlib/Mathlib/Algebra/Homology/Bifunctor.lean"
let inputCtx : Lean.Parser.InputContext := Lean.Parser.mkInputContext input "<input>"
let (header, parserState, messages) ← Lean.Parser.parseHeader inputCtx
let options : Options := maxHeartbeats.set {} 0
let (env, messages) ← processHeader header options messages inputCtx
let cmdState := Command.mkState env messages options
let cmdState := { cmdState with infoState.enabled := true }
let s ← IO.processCommands inputCtx parserState cmdState <&> Frontend.State.commandState
let trees := s.infoState.trees
for tree in trees do
tree.visitM' fun ctxInfo info _ => do
let .ofTermInfo info := info | return
let ctxInfo := { ctxInfo with options := maxHeartbeats.set ctxInfo.options 0 }
ctxInfo.runMetaM info.lctx <| do
let tp := ← Meta.inferType info.expr
discard <| Meta.whnf tp
println! ← getRemainingHeartbeats
(run it in a project with mathlib
).
This doesn't hit a deterministic timeout, but it at least demonstrates that the remaining heartbeats is decreasing when I would expect it not to. What am I doing wrong?
Eric Wieser (Nov 02 2024 at 18:07):
You need to set the maxheartbeats in the core state I think; the ones in options have no effect
Eric Wieser (Nov 02 2024 at 18:08):
@loogle "withHeartbeats"
loogle (Nov 02 2024 at 18:08):
:search: Lean.withHeartbeats
Eric Wieser (Nov 02 2024 at 18:09):
(nevermind, I'm thinking of something else)
Adam Topaz (Nov 02 2024 at 18:11):
Adam Topaz (Nov 02 2024 at 18:12):
Where in the state?
Adam Topaz (Nov 02 2024 at 18:12):
Is it in docs#Lean.Core.Context maybe?
Eric Wieser (Nov 02 2024 at 18:48):
(deleted)
Eric Wieser (Nov 02 2024 at 18:49):
Adam Topaz said:
Is it in docs#Lean.Core.Context maybe?
Yes, that's what I was thinking of, thanks!
Adam Topaz (Nov 02 2024 at 18:50):
Should this be considered a bug in ContextInfo.runCoreM
?
Eric Wieser (Nov 02 2024 at 18:50):
Another possible bug here is that src#ContextInfo.runCoreM does not set initHeartbeats
, and so the hearbeat counter resets to zero each time
Eric Wieser (Nov 02 2024 at 18:52):
In fact I think this _is_ the bug, because if IO.getNumHeartbeats
is greater than your limit before you even start, then you can'd do anything in CoreM
Eric Wieser (Nov 02 2024 at 18:53):
I have a patch somewhere fixing 5-10 "didn't propagate hearbeats" issues like this, but won't be able to find it now until after my vacation
Adam Topaz (Nov 02 2024 at 19:08):
That actually explains most issues I’ve been encountering. I thought I had a memory leak somewhere at some point, but I’m now quite sure it’s the bug Eric describes above.
Adam Topaz (Nov 03 2024 at 13:20):
In case it helps anyone else, for now I'm using the following, which works for my purposes:
namespace Lean.Elab.ContextInfo
def runCoreM' (info : ContextInfo) (x : CoreM α) : IO α := do
let initHeartbeats ← IO.getNumHeartbeats
Prod.fst <$> x.toIO
{ currNamespace := info.currNamespace,
openDecls := info.openDecls,
fileName := "<InfoTree>",
fileMap := default,
initHeartbeats := initHeartbeats,
maxHeartbeats := maxHeartbeats.get info.options,
options := info.options }
{ env := info.env, ngen := info.ngen }
def runMetaM' (info : ContextInfo) (lctx : LocalContext) (x : MetaM α) : IO α := do
Prod.fst <$> info.runCoreM' (x.run { lctx := lctx } { mctx := info.mctx })
def ppGoals' (ctx : ContextInfo) (goals : List MVarId) : IO Format :=
if goals.isEmpty then
return "no goals"
else
ctx.runMetaM' {} (return Std.Format.prefixJoin "\n" (← goals.mapM (Meta.ppGoal ·)))
Damiano Testa (Nov 03 2024 at 15:33):
I think that Kyle recently made some of the monadic lift functions keep track of more of the available context. If I remember correctly, these changes have been merged into core, but may not have trickled down to mathlib yet.
Damiano Testa (Nov 03 2024 at 15:36):
Maybe lean4#5800?
Adam Topaz (Nov 03 2024 at 15:46):
The functions I’m using are all from core
Damiano Testa (Nov 03 2024 at 15:48):
Ok, besides, I don't think that the heartbeats were present in Kyle's extra context.
Eric Wieser (Jan 06 2025 at 16:40):
I think my diagnosis above must have been incorrect, as src#Lean.Core.CoreM.toIO sets initHeartbeats
after all
Last updated: May 02 2025 at 03:31 UTC