gpt4 book ai didi

optimization - 日期时间到字符串,在 F# 中,这可以进一步优化吗?

转载 作者:行者123 更新时间:2023-12-04 08:10:41 25 4
gpt4 key购买 nike

我有一个系统可以进行一些模拟并输出大量带有时间戳的日志信息。
我很惊讶地看到 DateTime.ToString() 在循环中非常昂贵(它真的被调用了很多),所以我尝试制作一个更快的版本来输出日期、时间和毫秒。
这可以更快地完成吗(输出需要有毫秒)?我没有尝试使用指针,因为我认为(可能是错误的)对于这么小的一段代码,固定对象的开销会更高。

module DateTimeFormatter =

let inline private valueToDigit (value: int) : char =
char (value + int '0')

let inline private write2Characters (c: char[]) offset value =
c.[offset + 0] <- valueToDigit (value / 10)
c.[offset + 1] <- valueToDigit (value % 10)

let inline private write3Characters (c: char[]) offset value =
c.[offset + 0] <- valueToDigit (value / 100)
c.[offset + 1] <- valueToDigit ((value % 100) / 10)
c.[offset + 2] <- valueToDigit (value % 10)

let format (dateTime: DateTime) =
let c = Array.zeroCreate<char> 23
write2Characters c 0 (dateTime.Year / 100)
write2Characters c 2 (dateTime.Year % 100)
c.[4] <- '-'
write2Characters c 5 dateTime.Month
c.[7] <- '-'
write2Characters c 8 dateTime.Day
c.[10] <- ' '
write2Characters c 11 dateTime.Hour
c.[13] <- ':'
write2Characters c 14 dateTime.Minute
c.[16] <- ':'
write2Characters c 17 dateTime.Second
c.[19] <- '.'
write3Characters c 20 dateTime.Millisecond

new string(c)
下面是测试代码:
let a = DateTime.UtcNow
let iterations = 10_000_000
let sw = Stopwatch()

sw.Start()
for i = 0 to iterations do
a.ToString() |> ignore
sw.Stop()
printfn $"original no ms display {sw.ElapsedMilliseconds} ms"

sw.Reset()
sw.Start()
for i = 0 to iterations do
a.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture) |> ignore
sw.Stop()
printfn $"original with ms display {sw.ElapsedMilliseconds} ms"

sw.Reset()
sw.Start()
for i = 0 to iterations do
a |> DateTimeFormatter.format |> ignore
sw.Stop()
printfn $"new with ms display {sw.ElapsedMilliseconds} ms"
和测试结果(MBP i7 2019):
original no ms display   2892 ms

original with ms display 4042 ms
new with ms display 1435 ms

最佳答案

我会改进的事情

  • 避免重新创建字符数组
  • 避免在 char 数组中重新分配分隔符 - 它们永远不会改变
  • 避免重新分配未更改的日期部分。如果您担心毫秒,我会假设年、月、日、小时、分钟甚至秒不会经常变化。
  • 避免重新计算 int '0' 的值- 它永远不会改变
  • 避免额外的函数调用
    let format =
    let mutable year = -1
    let mutable month = -1
    let mutable day = -1
    let mutable hour = -1
    let mutable minute = -1
    let mutable second = -1
    let array = "0000-00-00 00:00:00.000".ToCharArray()
    let zeroChar = int '0'

    fun (dateTime: DateTime) ->
    if dateTime.Year <> year then
    year <- dateTime.Year
    array.[0] <- char (zeroChar + year / 1000)
    array.[1] <- char (zeroChar + (year % 1000) / 100)
    array.[2] <- char (zeroChar + (year % 100) / 10)
    array.[3] <- char (zeroChar + (year % 10))

    if dateTime.Month <> month then
    month <- dateTime.Month
    array.[5] <- char (zeroChar + month / 10)
    array.[6] <- char (zeroChar + month % 10)

    if dateTime.Day <> day then
    day <- dateTime.Day
    array.[8] <- char (zeroChar + day / 10)
    array.[9] <- char (zeroChar + day % 10)

    if dateTime.Hour <> hour then
    hour <- dateTime.Hour
    array.[11] <- char (zeroChar + hour / 10)
    array.[12] <- char (zeroChar + hour % 10)

    if dateTime.Minute <> minute then
    minute <- dateTime.Minute
    array.[14] <- char (zeroChar + minute / 10)
    array.[15] <- char (zeroChar + minute % 10)

    if dateTime.Second <> second then
    second <- dateTime.Second
    array.[17] <- char (zeroChar + second / 10)
    array.[18] <- char (zeroChar + second % 10)

    let ms = dateTime.Millisecond
    array.[20] <- char (zeroChar + ms / 100)
    array.[21] <- char (zeroChar + (ms % 100) / 10)
    array.[22] <- char (zeroChar + ms % 10)

    new string(array)

  • 与您的测试用例一起运行它会显示针对您的解决方案的 x2 性能和与原始解决方案相比的 x5 性能。
    original no ms display 2354 ms
    original with ms display 3545 ms
    new with ms display 1221 ms
    newest with ms display 691 ms
    进一步优化可以避免 DateTime 属性调用并根据 Ticks 手动计算值。

    关于optimization - 日期时间到字符串,在 F# 中,这可以进一步优化吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65982780/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com