Skip to content

Commit 52add53

Browse files
committed
More efficient writing of java.time.Instant values between -10000 and 10000 years using Scala.js
1 parent 3b4b6ee commit 52add53

File tree

3 files changed

+58
-35
lines changed
  • jsoniter-scala-core

3 files changed

+58
-35
lines changed

jsoniter-scala-core/js/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonWriter.scala

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,31 +1836,54 @@ final class JsonWriter private[jsoniter_scala](
18361836

18371837
private[this] def writeInstant(x: Instant): Unit = {
18381838
val epochSecond = x.getEpochSecond
1839-
val epochDay =
1840-
(if (epochSecond >= 0) epochSecond
1841-
else epochSecond - 86399) / 86400
1842-
var marchZeroDay = epochDay + 719468 // 719468 == 719528 - 60 == days 0000 to 1970 - days 1st Jan to 1st Mar
1843-
var adjust400YearCycles = 0
1844-
if (marchZeroDay < 0) {
1845-
adjust400YearCycles = ((marchZeroDay + 1) / 146097).toInt - 1
1846-
marchZeroDay -= adjust400YearCycles * 146097L
1847-
}
1848-
var year = ((marchZeroDay * 400 + 591) / 146097).toInt
1849-
var year365 = year * 365L
1850-
var century = year / 100
1851-
var marchDayOfYear = (marchZeroDay - year365).toInt - (year >> 2) + century - (century >> 2)
1852-
if (marchDayOfYear < 0) {
1853-
year365 -= 365
1854-
year -= 1
1855-
century = year / 100
1856-
marchDayOfYear = (marchZeroDay - year365).toInt - (year >> 2) + century - (century >> 2)
1839+
var year, adjust400YearCycles, marchDayOfYear, secsOfDay = 0
1840+
if (epochSecond > -316224000000L && epochSecond < 316224000000L) { // the fast path from -10000 to 10000 years
1841+
val epochDay =
1842+
((if (epochSecond >= 0) epochSecond
1843+
else epochSecond - 86399) * 1.1574074074074073E-5).toInt
1844+
var marchZeroDay = epochDay + 719468 // 719468 == 719528 - 60 == days 0000 to 1970 - days 1st Jan to 1st Mar
1845+
if (marchZeroDay < 0) {
1846+
adjust400YearCycles = ((marchZeroDay + 1) * 6.844767517471269E-6).toInt - 1
1847+
marchZeroDay -= adjust400YearCycles * 146097
1848+
}
1849+
year = ((marchZeroDay * 400 + 591) * 6.844767517471269E-6).toInt
1850+
var days = year * 365
1851+
var century = year / 100
1852+
marchDayOfYear = marchZeroDay - days - (year >> 2) + century - (century >> 2)
1853+
if (marchDayOfYear < 0) {
1854+
days -= 365
1855+
year -= 1
1856+
century = year / 100
1857+
marchDayOfYear = marchZeroDay - days - (year >> 2) + century - (century >> 2)
1858+
}
1859+
secsOfDay = (epochSecond - epochDay * 86400).toInt
1860+
} else {
1861+
val epochDay =
1862+
(if (epochSecond >= 0) epochSecond
1863+
else epochSecond - 86399) / 86400
1864+
var marchZeroDay = epochDay + 719468 // 719468 == 719528 - 60 == days 0000 to 1970 - days 1st Jan to 1st Mar
1865+
if (marchZeroDay < 0) {
1866+
adjust400YearCycles = ((marchZeroDay + 1) / 146097).toInt - 1
1867+
marchZeroDay -= adjust400YearCycles * 146097L
1868+
}
1869+
year = ((marchZeroDay * 400 + 591) / 146097).toInt
1870+
var days = year * 365L
1871+
var century = year / 100
1872+
marchDayOfYear = (marchZeroDay - days).toInt - (year >> 2) + century - (century >> 2)
1873+
if (marchDayOfYear < 0) {
1874+
days -= 365
1875+
year -= 1
1876+
century = year / 100
1877+
marchDayOfYear = (marchZeroDay - days).toInt - (year >> 2) + century - (century >> 2)
1878+
}
1879+
secsOfDay = (epochSecond - epochDay * 86400).toInt
18571880
}
18581881
val marchMonth = marchDayOfYear * 17135 + 6854 >> 19 // (marchDayOfYear * 5 + 2) / 153
18591882
val day = marchDayOfYear - (marchMonth * 1002762 - 16383 >> 15) // marchDayOfYear - (marchMonth * 306 + 5) / 10 + 1
18601883
val m = 9 - marchMonth >> 4
18611884
val month = (m & -9 | 3) + marchMonth
18621885
year += adjust400YearCycles * 400 - m
1863-
writeInstant(year, month, day, (epochSecond - epochDay * 86400).toInt, x.getNano)
1886+
writeInstant(year, month, day, secsOfDay, x.getNano)
18641887
}
18651888

18661889
private[this] def writeInstant(year: Int, month: Int, day: Int, secsOfDay: Int, nano: Int): Unit = {

jsoniter-scala-core/jvm/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonWriter.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,16 +1669,16 @@ final class JsonWriter private[jsoniter_scala](
16691669
val epochDay = Math.multiplyHigh(epochSecond, 1749024623285053783L) >> 13 // epochSecond / 86400
16701670
val marchZeroDay = epochDay + 719468 // 719468 == 719528 - 60 == days 0000 to 1970 - days 1st Jan to 1st Mar
16711671
var year = (Math.multiplyHigh(marchZeroDay * 400 + 591, 4137408090565272301L) >> 15).toInt // ((marchZeroDay * 400 + 591) / 146097).toInt
1672-
var year365 = year * 365L
1672+
var days = year * 365L
16731673
var year1374389535 = year * 1374389535L
16741674
var century = (year1374389535 >> 37).toInt
1675-
var marchDayOfYear = (marchZeroDay - year365).toInt - (year >> 2) + century - (century >> 2)
1675+
var marchDayOfYear = (marchZeroDay - days).toInt - (year >> 2) + century - (century >> 2)
16761676
if (marchDayOfYear < 0) {
1677-
year365 -= 365
1677+
days -= 365
16781678
year1374389535 -= 1374389535
16791679
year -= 1
16801680
century = (year1374389535 >> 37).toInt
1681-
marchDayOfYear = (marchZeroDay - year365).toInt - (year >> 2) + century - (century >> 2)
1681+
marchDayOfYear = (marchZeroDay - days).toInt - (year >> 2) + century - (century >> 2)
16821682
}
16831683
val marchMonth = marchDayOfYear * 17135 + 6854 >> 19 // (marchDayOfYear * 5 + 2) / 153
16841684
val day = marchDayOfYear - (marchMonth * 1002762 - 16383 >> 15) // marchDayOfYear - (marchMonth * 306 + 5) / 10 + 1
@@ -1695,16 +1695,16 @@ final class JsonWriter private[jsoniter_scala](
16951695
val adjust400YearCycles = ((marchZeroDay + 1) * 7525902 >> 40).toInt // ((marchZeroDay + 1) / 146097).toInt - 1
16961696
marchZeroDay -= adjust400YearCycles * 146097L
16971697
var year = (Math.multiplyHigh(marchZeroDay * 400 + 591, 4137408090565272301L) >> 15).toInt // ((marchZeroDay * 400 + 591) / 146097).toInt
1698-
var year365 = year * 365L
1698+
var days = year * 365L
16991699
var year1374389535 = year * 1374389535L
17001700
var century = (year1374389535 >> 37).toInt
1701-
var marchDayOfYear = (marchZeroDay - year365).toInt - (year >> 2) + century - (century >> 2)
1701+
var marchDayOfYear = (marchZeroDay - days).toInt - (year >> 2) + century - (century >> 2)
17021702
if (marchDayOfYear < 0) {
1703-
year365 -= 365
1703+
days -= 365
17041704
year1374389535 -= 1374389535
17051705
year -= 1
17061706
century = (year1374389535 >> 37).toInt
1707-
marchDayOfYear = (marchZeroDay - year365).toInt - (year >> 2) + century - (century >> 2)
1707+
marchDayOfYear = (marchZeroDay - days).toInt - (year >> 2) + century - (century >> 2)
17081708
}
17091709
val marchMonth = marchDayOfYear * 17135 + 6854 >> 19 // (marchDayOfYear * 5 + 2) / 153
17101710
val day = marchDayOfYear - (marchMonth * 1002762 - 16383 >> 15) // marchDayOfYear - (marchMonth * 306 + 5) / 10 + 1

jsoniter-scala-core/native/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/core/JsonWriter.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,16 +1669,16 @@ final class JsonWriter private[jsoniter_scala](
16691669
val epochDay = NativeMath.multiplyHigh(epochSecond, 1749024623285053783L) >> 13 // epochSecond / 86400
16701670
val marchZeroDay = epochDay + 719468 // 719468 == 719528 - 60 == days 0000 to 1970 - days 1st Jan to 1st Mar
16711671
var year = (NativeMath.multiplyHigh(marchZeroDay * 400 + 591, 4137408090565272301L) >> 15).toInt // ((marchZeroDay * 400 + 591) / 146097).toInt
1672-
var year365 = year * 365L
1672+
var days = year * 365L
16731673
var year1374389535 = year * 1374389535L
16741674
var century = (year1374389535 >> 37).toInt
1675-
var marchDayOfYear = (marchZeroDay - year365).toInt - (year >> 2) + century - (century >> 2)
1675+
var marchDayOfYear = (marchZeroDay - days).toInt - (year >> 2) + century - (century >> 2)
16761676
if (marchDayOfYear < 0) {
1677-
year365 -= 365
1677+
days -= 365
16781678
year1374389535 -= 1374389535
16791679
year -= 1
16801680
century = (year1374389535 >> 37).toInt
1681-
marchDayOfYear = (marchZeroDay - year365).toInt - (year >> 2) + century - (century >> 2)
1681+
marchDayOfYear = (marchZeroDay - days).toInt - (year >> 2) + century - (century >> 2)
16821682
}
16831683
val marchMonth = marchDayOfYear * 17135 + 6854 >> 19 // (marchDayOfYear * 5 + 2) / 153
16841684
val day = marchDayOfYear - (marchMonth * 1002762 - 16383 >> 15) // marchDayOfYear - (marchMonth * 306 + 5) / 10 + 1
@@ -1695,16 +1695,16 @@ final class JsonWriter private[jsoniter_scala](
16951695
val adjust400YearCycles = ((marchZeroDay + 1) * 7525902 >> 40).toInt // ((marchZeroDay + 1) / 146097).toInt - 1
16961696
marchZeroDay -= adjust400YearCycles * 146097L
16971697
var year = (NativeMath.multiplyHigh(marchZeroDay * 400 + 591, 4137408090565272301L) >> 15).toInt // ((marchZeroDay * 400 + 591) / 146097).toInt
1698-
var year365 = year * 365L
1698+
var days = year * 365L
16991699
var year1374389535 = year * 1374389535L
17001700
var century = (year1374389535 >> 37).toInt
1701-
var marchDayOfYear = (marchZeroDay - year365).toInt - (year >> 2) + century - (century >> 2)
1701+
var marchDayOfYear = (marchZeroDay - days).toInt - (year >> 2) + century - (century >> 2)
17021702
if (marchDayOfYear < 0) {
1703-
year365 -= 365
1703+
days -= 365
17041704
year1374389535 -= 1374389535
17051705
year -= 1
17061706
century = (year1374389535 >> 37).toInt
1707-
marchDayOfYear = (marchZeroDay - year365).toInt - (year >> 2) + century - (century >> 2)
1707+
marchDayOfYear = (marchZeroDay - days).toInt - (year >> 2) + century - (century >> 2)
17081708
}
17091709
val marchMonth = marchDayOfYear * 17135 + 6854 >> 19 // (marchDayOfYear * 5 + 2) / 153
17101710
val day = marchDayOfYear - (marchMonth * 1002762 - 16383 >> 15) // marchDayOfYear - (marchMonth * 306 + 5) / 10 + 1

0 commit comments

Comments
 (0)