Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@tuleism
Copy link
Contributor

@tuleism tuleism commented Aug 7, 2020

This test

testM("free from stack overflow") {
  assertM(run(Schedule.forever *> Schedule.recurs(10000000))(List.fill(1000000)(())))(
    equalTo(Chunk.range(0L, 1000000L))
  )
}

causes

java.lang.StackOverflowError
at zio.Schedule$.$anonfun$unfold$3(Schedule.scala:1041)

After the fix, it takes around 5-7 seconds to execute on my machine. Not sure if it's good to leave it in.

@tuleism
Copy link
Contributor Author

tuleism commented Aug 7, 2020

In the 1st commit, I used Chunk.range. But it's not available for dotty/2.13. I tried to change it to Chunk.fromIterable, but then got Stack Overflow from Chunk append. Issue created at #4065

@ghostdogpr
Copy link
Member

I also ran into this issue at work. The stack points at line 1041 which is unfold, but I am not sure from which operator it came from.

@ghostdogpr
Copy link
Member

It seems to crash after consuming events from Kafka for about 20 minutes (using zio-kafka cc @iravid ). I suspect it's the Schedule.forever used in ZStream#aggregateAsync which is itself used by zio-kafka.

@iravid
Copy link
Member

iravid commented Aug 12, 2020

Ouch!

@ghostdogpr I think we're only using aggregateAsync in Consumer.consumeWith, so potentially you could copy consumeWith to your project and replace the use of aggregateAsync with aggregateAsyncWithin(... Schedule.fixed(1.millis)). It's used for batching commits so that should probably be fine.

@jdegoes @adamgfraser Can you take a look at the fix?

@ghostdogpr
Copy link
Member

Ah, actually I'm not using consumeWith but subscribeAnd so it must be somewhere else. It's hard to pinpoint, I just know that it happens only on my branch introducing zio-kafka 😄 Will investigate more tomorrow if there is no fix in between.

@jdegoes
Copy link
Member

jdegoes commented Aug 12, 2020

Fix looks fine assuming it works (it would have led to infinite thunks before).

@jdegoes
Copy link
Member

jdegoes commented Aug 12, 2020

@tuleism Thank you for the contribution and the test!

@jdegoes jdegoes merged commit be2753d into zio:master Aug 12, 2020
@adamgfraser
Copy link
Contributor

One issue here is we're evaluating the by name parameter immediately. What about something like?

  def unfold[A](a: => A)(f: A => A): Schedule[Any, Any, A] = {
    def loop(a: => A): StepFunction[Any, Any, A] = {
      lazy val a0 = a
      (now, _) => ZIO.succeed(Decision.Continue(a0, now, loop(f(a0))))
    }

    Schedule((now, _) => ZIO.succeed(Decision.Continue(a, now, loop(f(a)))))
  }

This resolves the stack overflow issue and preserves the laziness of the parameter.

@adamgfraser
Copy link
Contributor

Also I think we may want to scale back the size of the test. I was able to reproduce with 10,000 elements instead of 1,000,000.

@hmemcpy
Copy link
Contributor

hmemcpy commented Aug 24, 2020

Whoa, just hit this in production! Will upgrade asap. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants