Zulip Chat Archive

Stream: maths

Topic: count_heartbeats bug?


Johan Commelin (Sep 19 2024 at 19:15):

I took the example from https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/Heavy.20rfl/near/469774488 and added count_heartbeats in to the examples.
The result is that I have several threads eating up 100% of about half of my cores. And they don't die down. Not even after a few minutes.
I'm using lean.nvim.

import Mathlib.LinearAlgebra.AffineSpace.AffineEquiv

variable (R : Type*) {V V' P P' : Type*}
variable [OrderedRing R] [AddCommGroup V] [Module R V] [AddTorsor V P]
variable [AddCommGroup V'] [Module R V'] [AddTorsor V' P']

open AffineMap

def Sbtw (x y z : P) : Prop := y  lineMap x y '' Set.Icc (0 : R) 1  y  x  y  z

variable {R}

theorem Function.Injective.sbtw_map_iff {x y z : P} {f : P →ᵃ[R] P'} (hf : Function.Injective f) :
    Sbtw R (f x) (f y) (f z)  Sbtw R x y z :=
  sorry

-- 146454 heartbeats
count_heartbeats in
lemma slow {x y z : P} (f : P ≃ᵃ[R] P') : Sbtw R (f x) (f y) (f z)  Sbtw R x y z :=
  let hf : Function.Injective f.toAffineMap := AffineEquiv.injective f
  Function.Injective.sbtw_map_iff hf

-- 762 heartbeats
count_heartbeats in
lemma fast {x y z : P} (f : P ≃ᵃ[R] P') : Sbtw R (f x) (f y) (f z)  Sbtw R x y z :=
  let hf : Function.Injective f.toAffineMap := AffineEquiv.injective f
  hf.sbtw_map_iff

Johan Commelin (Sep 19 2024 at 19:16):

Can anyone reproduce?

Johan Commelin (Sep 19 2024 at 19:16):

I was just messing around in the file a bit. Nothing special.

Heather Macbeth (Sep 19 2024 at 19:18):

I have experienced this too (in VSCode), although I don't have a precise example to reproduce it. I have switched to a workflow of commenting out count_heartbeats before editing, which seems to avoid this.

Matthew Ballard (Sep 19 2024 at 19:21):

I have had sporadic cases of this also

Kim Morrison (Sep 20 2024 at 00:00):

Were you editing the contents of the lemmas wrapped in count_heartbeats? If so, expected behaviour. :-)

Kim Morrison (Sep 20 2024 at 00:01):

That I don't know how to fix.

Mario Carneiro (Sep 20 2024 at 06:09):

Can you explain what is happening / how this is implemented?

Kim Morrison (Sep 20 2024 at 06:15):

From file#Util/CountHeartbeats

elab "count_heartbeats " "in" ppLine cmd:command : command => do
  let start  IO.getNumHeartbeats
  try
    elabCommand ( `(command| set_option maxHeartbeats 0 in $cmd))
  finally
    let finish  IO.getNumHeartbeats
    let elapsed := (finish - start) / 1000
    let max := ( Command.liftCoreM getMaxHeartbeats) / 1000
    if elapsed < max then
      logInfo m!"Used {elapsed} heartbeats, which is less than the current maximum of {max}."
    else
      let mut max' := max
      while max' < elapsed do
        max' := 2 * max'
      logInfo m!"Used {elapsed} heartbeats, which is greater than the current maximum of {max}."
      let m : TSyntax `num := quote max'
      Command.liftCoreM <| MetaM.run' do
        Lean.Meta.Tactic.TryThis.addSuggestion ( getRef)
          ( set_option hygiene false in `(command| set_option maxHeartbeats $m in $cmd))

Mario Carneiro (Sep 20 2024 at 06:31):

what's the issue?

Mario Carneiro (Sep 20 2024 at 06:32):

is it that the first call runs without a timeout and hence can't be interrupted by the elaborator cancellation signal?

Floris van Doorn (Sep 20 2024 at 08:53):

I think this is the same as https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/count_heartbeats.20CPU.20usage ?

Kim Morrison (Sep 20 2024 at 11:36):

Yes, I think people are observing that if you type in the command wrapped in count_heartbeats, 100s of non-cancellable copies of the command are spawned.


Last updated: May 02 2025 at 03:31 UTC