簡體   English   中英

在 F# 中找不到此日期時間測試失敗的原因

[英]Can't find why this datetime test fails, in F#

我有以下 function,這是在這里的一些人的幫助下制作的:

module DateTimeFormatter =

    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 dateTimeArray  = "xxxx-xx-xx xx:xx:xx.xxx".ToCharArray()
    let timeArray      = "xx:xx:xx.xxx".ToCharArray()
    let zeroChar       = int '0'

    // format the datetime into a date and a time with milliseconds
    let format (dateTime: DateTime) =

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

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

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

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

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

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

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

        new string(dateTimeArray)

這個想法是盡可能快地構建日期時間 + 毫秒時間戳。

但有時,並非總是如此,我得到這個 output:

2021-06-01 xx:xx:53.648

並且失敗總是在小時/分鍾上,但有時它工作正常,有時卻不行。 並且在構建字符串時我沒有看到測試有任何問題,但看起來小時和分鍾即使是第一次測試也失敗了,因為有占位符“x”。

這可能是這些超級簡單的事情之一,需要另一雙眼睛才能看到:)

它失敗了,因為模塊中的可變變量和dateTimeArray正在從不同的線程中遍歷。 這不是線程安全的代碼。

我發布了一些我現在已經刪除的評論,因為我看代碼的時間不夠長,無法理解其意圖。 意圖顯然是優化,但它失敗了。 簡化 function 實際上會提高性能。 額外的邏輯和額外的變量都沒有幫助。 下面的代碼仍然更快。

我有點懷疑線程本地存儲是否可以幫助原始代碼擊敗這段代碼,因為我認為在這個邏輯中找不到任何性能優勢。 我認為DateTime.ToString的好處在於這個簡化代碼中剩下的內容:

let dateTimeArray = "xxxx-xx-xx xx:xx:xx.xxx".ToCharArray()
let [<Literal>] zeroChar = 48 // '0'

let format (dateTime: DateTime) =

    let dateTimeArray = Array.copy dateTimeArray

    dateTimeArray.[0] <- char (zeroChar + dateTime.Year / 1000)
    dateTimeArray.[1] <- char (zeroChar + (dateTime.Year % 1000) / 100)
    dateTimeArray.[2] <- char (zeroChar + (dateTime.Year % 100) / 10)
    dateTimeArray.[3] <- char (zeroChar + (dateTime.Year % 10))

    dateTimeArray.[5] <- char (zeroChar + dateTime.Month / 10)
    dateTimeArray.[6] <- char (zeroChar + dateTime.Month % 10)

    dateTimeArray.[8] <- char (zeroChar + dateTime.Day / 10)
    dateTimeArray.[9] <- char (zeroChar + dateTime.Day % 10)

    dateTimeArray.[11] <- char (zeroChar + dateTime.Hour / 10)
    dateTimeArray.[12] <- char (zeroChar + dateTime.Hour % 10)

    dateTimeArray.[14] <- char (zeroChar + dateTime.Minute / 10)
    dateTimeArray.[15] <- char (zeroChar + dateTime.Minute % 10)

    dateTimeArray.[17] <- char (zeroChar + dateTime.Second / 10)
    dateTimeArray.[18] <- char (zeroChar + dateTime.Second % 10)

    dateTimeArray.[20] <- char (zeroChar + dateTime.Millisecond / 100)
    dateTimeArray.[21] <- char (zeroChar + (dateTime.Millisecond % 100) / 10)
    dateTimeArray.[22] <- char (zeroChar + dateTime.Millisecond % 10)

    new string(dateTimeArray)

多次讀取dateTime的屬性不會減慢 function。 一次讀取一個屬性,例如一次讀取dateTime.Year到一個本地值,然后在四個地方使用它,實際上會使 function 變慢。

看起來這將節省更多時間,並且不再需要外部dateTimeArray

let dateTimeArray: char[] =
    [|
        char (zeroChar + dateTime.Year / 1000)
        char (zeroChar + (dateTime.Year % 1000) / 100)
        char (zeroChar + (dateTime.Year % 100) / 10)
        char (zeroChar + (dateTime.Year % 10))
        '-'
        char (zeroChar + dateTime.Month / 10)
        char (zeroChar + dateTime.Month % 10)
        '-'
        char (zeroChar + dateTime.Day / 10)
        char (zeroChar + dateTime.Day % 10)
        ' '
        char (zeroChar + dateTime.Hour / 10)
        char (zeroChar + dateTime.Hour % 10)
        ':'
        char (zeroChar + dateTime.Minute / 10)
        char (zeroChar + dateTime.Minute % 10)
        ':'
        char (zeroChar + dateTime.Second / 10)
        char (zeroChar + dateTime.Second % 10)
        '.'
        char (zeroChar + dateTime.Millisecond / 100)
        char (zeroChar + (dateTime.Millisecond % 100) / 10)
        char (zeroChar + dateTime.Millisecond % 10)
    |]

我還有一個版本。 Math.DivRem的使用似乎稍微減少了一些,但是查找數組digits會增加時間,盡管它帶來了一些優雅。

let format (dateTime: DateTime) =
    let monthHigh, monthLow = Math.DivRem (dateTime.Month, 10)
    let dayHigh, dayLow = Math.DivRem (dateTime.Day, 10)
    let hourHigh, hourLow = Math.DivRem (dateTime.Hour, 10)
    let minuteHigh, minuteLow = Math.DivRem (dateTime.Minute, 10)
    let secondHigh, secondLow = Math.DivRem (dateTime.Second, 10)
    let digit = [| '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9' |]
    [|
        digit.[dateTime.Year / 1000]
        digit.[(dateTime.Year % 1000) / 100]
        digit.[(dateTime.Year % 100) / 10]
        digit.[dateTime.Year % 10]
        '-'
        digit.[monthHigh]
        digit.[monthLow]
        '-'
        digit.[dayHigh]
        digit.[dayLow]
        ' '
        digit.[hourHigh]
        digit.[hourLow]
        ':'
        digit.[minuteHigh]
        digit.[minuteLow]
        ':'
        digit.[secondHigh]
        digit.[secondLow]
        '.'
        digit.[dateTime.Millisecond / 100]
        digit.[(dateTime.Millisecond % 100) / 10]
        digit.[dateTime.Millisecond % 10]
    |] |> (fun a -> new String(a))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM