Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support adjust the scheduler's tick-duration. #1366

Merged
merged 1 commit into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ import scala.util.control.NonFatal
import atomic.{ AtomicInteger, AtomicReference }
import scala.annotation.nowarn
import com.typesafe.config.{ Config, ConfigFactory }

import language.postfixOps
import org.scalatest.BeforeAndAfterEach

import org.apache.pekko
import pekko.pattern.ask
import pekko.testkit._
import pekko.util.Helpers

object SchedulerSpec {
val testConfRevolver =
Expand All @@ -40,6 +41,13 @@ object SchedulerSpec {
pekko.scheduler.ticks-per-wheel = 32
""").withFallback(PekkoSpec.testConf)

val testConfAdjustment =
ConfigFactory.parseString("""
pekko.scheduler.implementation = org.apache.pekko.actor.LightArrayRevolverScheduler
pekko.scheduler.tick-duration = 1ns
He-Pin marked this conversation as resolved.
Show resolved Hide resolved
pekko.scheduler.error-on-tick-duration-verification-failed = off
""").withFallback(PekkoSpec.testConf)

}

trait SchedulerSpec extends BeforeAndAfterEach with DefaultTimeout with ImplicitSender { this: PekkoSpec =>
Expand Down Expand Up @@ -819,3 +827,19 @@ class LightArrayRevolverSchedulerSpec extends PekkoSpec(SchedulerSpec.testConfRe
}

}

class LightArrayRevolverSchedulerAdjustConfigSpec extends PekkoSpec(SchedulerSpec.testConfAdjustment)
with SchedulerSpec {
override def collectCancellable(c: Cancellable): Cancellable = c
private val tickDuration = system.scheduler.asInstanceOf[LightArrayRevolverScheduler].TickDuration

"A LightArrayRevolverScheduler" must {
"be able to adjust the config" in {
if (Helpers.isWindows) {
tickDuration should ===(10.millis)
} else {
tickDuration should ===(1.millis)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class ConfigSpec extends PekkoSpec(ConfigFactory.defaultReference(ActorSystem.fi

getInt("pekko.scheduler.ticks-per-wheel") should ===(512)
getDuration("pekko.scheduler.tick-duration", TimeUnit.MILLISECONDS) should ===(10L)
getBoolean("pekko.scheduler.error-on-tick-duration-verification-failed") should ===(true)
getString("pekko.scheduler.implementation") should ===("org.apache.pekko.actor.LightArrayRevolverScheduler")

getBoolean("pekko.daemonic") should ===(false)
Expand Down
9 changes: 9 additions & 0 deletions actor/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
Expand Up @@ -829,8 +829,17 @@ pekko {
# Note that it might take up to 1 tick to stop the Timer, so setting the
# tick-duration to a high value will make shutting down the actor system
# take longer.
#
# Requirements:
# 1. The minimum supported tick-duration on Windows is 10ms,
# 2. The minimum supported tick-duration is 1ms
tick-duration = 10ms

# An error will be throw when the tick-duration does not meet the requirements.
# When this is set to off, the tick-duration will be adjusted to meet the requirements
# and a warning will be logged.
error-on-tick-duration-verification-failed = on

# The timer uses a circular wheel of buckets to store the timer tasks.
# This should be set such that the majority of scheduled timeouts (for high
# scheduling frequency) will be shorter than one rotation of the wheel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,39 @@ class LightArrayRevolverScheduler(config: Config, log: LoggingAdapter, threadFac
import Helpers.ConfigOps
import Helpers.Requiring

val WheelSize =
val WheelSize: Int =
config
.getInt("pekko.scheduler.ticks-per-wheel")
.requiring(ticks => (ticks & (ticks - 1)) == 0, "ticks-per-wheel must be a power of 2")
val TickDuration =
config
.getMillisDuration("pekko.scheduler.tick-duration")
.requiring(
_ >= 10.millis || !Helpers.isWindows,
"minimum supported pekko.scheduler.tick-duration on Windows is 10ms")
.requiring(_ >= 1.millis, "minimum supported pekko.scheduler.tick-duration is 1ms")
val ShutdownTimeout = config.getMillisDuration("pekko.scheduler.shutdown-timeout")

val TickDuration: FiniteDuration = {
val durationFromConfig = config.getMillisDuration("pekko.scheduler.tick-duration")
val errorOnVerificationFailed = config.getBoolean("pekko.scheduler.error-on-tick-duration-verification-failed")

if (durationFromConfig < 10.millis) {
if (Helpers.isWindows) {
if (errorOnVerificationFailed) {
throw new IllegalArgumentException(
"requirement failed: minimum supported pekko.scheduler.tick-duration on Windows is 10ms")
} else {
log.warning(
"requirement failed: minimum supported pekko.scheduler.tick-duration on Windows is 10ms, adjusted to 10ms now.")
10.millis
}
} else if (durationFromConfig < 1.millis) {
if (errorOnVerificationFailed) {
throw new IllegalArgumentException(
"requirement failed: minimum supported pekko.scheduler.tick-duration is 1ms")
} else {
log.warning(
"requirement failed: minimum supported pekko.scheduler.tick-duration is 1ms, adjusted to 1ms now.")
1.millis
}
} else durationFromConfig
} else durationFromConfig
}

val ShutdownTimeout: FiniteDuration = config.getMillisDuration("pekko.scheduler.shutdown-timeout")

import LightArrayRevolverScheduler._

Expand Down