Skip to content

Commit

Permalink
Merge pull request #1511 from Thorium/less-seq-wraps
Browse files Browse the repository at this point in the history
Small memory and performance optimization: Less nested seq-wrapping on recursive functions
  • Loading branch information
cartermp authored Jul 8, 2024
2 parents 0daae3a + 820aa86 commit 71c95c7
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 41 deletions.
14 changes: 7 additions & 7 deletions src/FSharp.Data.Csv.Core/CsvRuntime.fs
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,20 @@ module internal CsvReader =

/// Reads multiple lines from the input, skipping newline characters
let rec readLines lineNumber =
seq {
match reader.Read() with
| -1 -> ()
| Char '\r'
| Char '\n' -> yield! readLines lineNumber
| current ->
match reader.Read() with
| -1 -> Seq.empty
| Char '\r'
| Char '\n' -> readLines lineNumber
| current ->
seq {
yield
readLine [] (StringBuilder()) current
|> List.rev
|> Array.ofList,
lineNumber

yield! readLines (lineNumber + 1)
}
}

readLines 0

Expand Down
14 changes: 12 additions & 2 deletions src/FSharp.Data.Html.Core/HtmlParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,24 @@ open System.Collections.Generic

module private TextParser =

let toPattern f c = if f c then Some c else None
let toPattern f c = if f c then ValueSome c else ValueNone

[<return: Struct>]
let (|EndOfFile|_|) (c: char) =
let value = c |> int
if (value = -1 || value = 65535) then Some c else None

if (value = -1 || value = 65535) then
ValueSome c
else
ValueNone

[<return: Struct>]
let (|Whitespace|_|) = toPattern Char.IsWhiteSpace

[<return: Struct>]
let (|LetterDigit|_|) = toPattern Char.IsLetterOrDigit

[<return: Struct>]
let (|Letter|_|) = toPattern Char.IsLetter

// --------------------------------------------------------------------------------------
Expand Down
46 changes: 23 additions & 23 deletions src/FSharp.Data.Runtime.Utilities/NameUtils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -41,36 +41,36 @@ let nicePascalName (s: string) =
else
// Starting to parse a new segment
let rec restart i =
seq {
match tryAt s i with
| EOF -> ()
| LetterDigit _ & Upper _ -> yield! upperStart i (i + 1)
| LetterDigit _ -> yield! consume i false (i + 1)
| _ -> yield! restart (i + 1)
}
match tryAt s i with
| EOF -> Seq.empty
| LetterDigit _ & Upper _ -> upperStart i (i + 1)
| LetterDigit _ -> consume i false (i + 1)
| _ -> restart (i + 1)
// Parsed first upper case letter, continue either all lower or all upper
and upperStart from i =
seq {
match tryAt s i with
| Upper _ -> yield! consume from true (i + 1)
| Lower _ -> yield! consume from false (i + 1)
| _ ->
yield from, i
match tryAt s i with
| Upper _ -> consume from true (i + 1)
| Lower _ -> consume from false (i + 1)
| _ ->
seq {
yield struct (from, i)
yield! restart (i + 1)
}
}
// Consume are letters of the same kind (either all lower or all upper)
and consume from takeUpper i =
seq {
match tryAt s i with
| Lower _ when not takeUpper -> yield! consume from takeUpper (i + 1)
| Upper _ when takeUpper -> yield! consume from takeUpper (i + 1)
| Lower _ when takeUpper ->
yield from, (i - 1)
match takeUpper, tryAt s i with
| false, Lower _ -> consume from takeUpper (i + 1)
| true, Upper _ -> consume from takeUpper (i + 1)
| true, Lower _ ->
seq {
yield struct (from, (i - 1))
yield! restart (i - 1)
| _ ->
yield from, i
}
| _ ->
seq {
yield struct (from, i)
yield! restart i
}
}

// Split string into segments and turn them to PascalCase
seq {
Expand Down
19 changes: 10 additions & 9 deletions src/FSharp.Data.Runtime.Utilities/TextConversions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ module private Helpers =

let ParseISO8601FormattedDateTime text cultureInfo =
match DateTime.TryParse(text, cultureInfo, dateTimeStyles) with
| true, d -> d |> Some
| false, _ -> None
| true, d -> d |> ValueSome
| false, _ -> ValueNone

// --------------------------------------------------------------------------------------

Expand Down Expand Up @@ -155,8 +155,9 @@ type TextConversions private () =
else
// Parse ISO 8601 format, fixing time zone if needed
match ParseISO8601FormattedDateTime text cultureInfo with
| Some d when d.Kind = DateTimeKind.Unspecified -> new DateTime(d.Ticks, DateTimeKind.Local) |> Some
| x -> x
| ValueSome d when d.Kind = DateTimeKind.Unspecified -> new DateTime(d.Ticks, DateTimeKind.Local) |> Some
| ValueSome x -> Some x
| ValueNone -> None

static member AsDateTimeOffset cultureInfo (text: string) =
// get TimeSpan presentation from 4-digit integers like 0000 or -0600
Expand All @@ -167,8 +168,8 @@ type TextConversions private () =

let offset str =
match Int32.TryParse str with
| true, v -> getTimeSpanFromHourMin v |> Some
| false, _ -> None
| true, v -> getTimeSpanFromHourMin v |> ValueSome
| false, _ -> ValueNone

let matchesMS = msDateRegex.Value.Match(text.Trim())

Expand All @@ -178,15 +179,15 @@ type TextConversions private () =
// only if the timezone offset is specified with '-' or '+' prefix, after the millis
// e.g. 1231456+1000, 123123+0000, 123123-0500, etc.
match offset matchesMS.Groups.[2].Value with
| Some ofst ->
| ValueSome ofst ->
matchesMS.Groups.[1].Value
|> Double.Parse
|> DateTimeOffset(1970, 1, 1, 0, 0, 0, ofst).AddMilliseconds
|> Some
| None -> None
| ValueNone -> None
else
match ParseISO8601FormattedDateTime text cultureInfo with
| Some d when d.Kind <> DateTimeKind.Unspecified ->
| ValueSome d when d.Kind <> DateTimeKind.Unspecified ->
match DateTimeOffset.TryParse(text, cultureInfo, dateTimeStyles) with
| true, dto -> dto |> Some
| false, _ -> None
Expand Down

0 comments on commit 71c95c7

Please sign in to comment.