clock: Bug fix: High TPS didn't work well due to the timer precision

When the TPS is high (e.g., 300), the count might be unreliable
since the timer might not be precise on some machines. In this
case, calculate the factor and multiply the count by it.

Fixes #1444
This commit is contained in:
Hajime Hoshi 2020-12-20 23:40:11 +09:00
parent 53d0e1eae0
commit 59567993c2

View File

@ -29,6 +29,8 @@ var (
currentFPS float64
currentTPS float64
lastTPS int64
tpsCalcErr int64
lastUpdated int64
fpsCount = 0
tpsCount = 0
@ -64,6 +66,28 @@ func min(a, b int64) int64 {
return b
}
// calcTPSFactor calculates the TPS that is used for the timer and the factor for the count.
// If tps is under the baseTPS, use tps as newTPS. The factor is 1. The timer precision should be enough.
// If not, use baseTPS as newTPS and factor that can be more than 1.
func calcTPSFactor(tps, baseTPS int64) (newTPS int64, factor int) {
if tps <= baseTPS {
return tps, 1
}
if lastTPS != tps {
tpsCalcErr = 0
}
lastTPS = tps
factor = int(tps / baseTPS)
tpsCalcErr += tps - baseTPS*int64(factor)
factor += int(tpsCalcErr / baseTPS)
tpsCalcErr %= baseTPS
return baseTPS, factor
}
func calcCountFromTPS(tps int64, now int64) int {
if tps == 0 {
return 0
@ -80,10 +104,12 @@ func calcCountFromTPS(tps int64, now int64) int {
count := 0
syncWithSystemClock := false
// When TPS is big (e.g. 300), the time gap can be small and diff might always exceeds the gap.
// To avoid this, prepare another gap assuming TPS was 60 and use the bigger one (#1443).
tooBigGap := int64(time.Second) * 5 / min(int64(tps), 60)
if diff > tooBigGap {
// When TPS is big (e.g. 300), the timer precision is no longer reliable.
// Multiply the factor later instead (#1444).
var tpsFactor int
tps, tpsFactor = calcTPSFactor(tps, 60) // TODO: 60 should be the current display's FPS.
if diff > int64(time.Second)*5/tps {
// The previous time is too old.
// Let's force to sync the game time with the system clock.
syncWithSystemClock = true
@ -107,7 +133,7 @@ func calcCountFromTPS(tps int64, now int64) int {
lastSystemTime += int64(count) * int64(time.Second) / tps
}
return count
return count * tpsFactor
}
func updateFPSAndTPS(now int64, count int) {