Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small memory and performance optimization: Less nested seq-wrapping on recursive functions #1511

Merged
merged 5 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading