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

Some minor performance optimisations #42

Merged
merged 2 commits into from
Jul 11, 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
1 change: 1 addition & 0 deletions src/FSharpAux.Core/Colors.fs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module Colors =
| B v -> v

/// Color structure
[<Struct>]
type Color = {
/// The alpha component value of this Color structure.
A : byte
Expand Down
4 changes: 3 additions & 1 deletion src/FSharpAux.Core/Dict.fs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,16 @@
member s.ContainsKey(k) = d.ContainsKey(Some(k))
member s.TryGetValue(k,r) =
let key = Some(k)
if d.ContainsKey(key) then (r <- d.[key]; true) else false
match d.TryGetValue key with
| true, v -> r <- v; true
| false, _ -> false
member s.Remove(k : 'Key) = (raise (NotSupportedException(notMutable)) : bool)

interface ICollection<KeyValuePair<'Key, 'T>> with
member s.Add(x) = raise (NotSupportedException(notMutable));
member s.Clear() = raise (NotSupportedException(notMutable));
member s.Remove(x) = raise (NotSupportedException(notMutable));
member s.Contains(KeyValue(k,v)) = c.Contains(KeyValuePair<_,_>(Some(k),v))

Check warning on line 66 in src/FSharpAux.Core/Dict.fs

View workflow job for this annotation

GitHub Actions / build-and-test-linux

This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type ''T'.

Check warning on line 66 in src/FSharpAux.Core/Dict.fs

View workflow job for this annotation

GitHub Actions / build-and-test-windows

This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type ''T'.
member s.CopyTo(arr,i) =
let mutable n = 0
for (KeyValue(k,v)) in c do
Expand Down
14 changes: 8 additions & 6 deletions src/FSharpAux.Core/Regex.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ module Regex =
//http://stackoverflow.com/questions/5684014/f-mapping-regular-expression-matches-with-active-patterns
module Active =
/// Returns the first occurencing match of the pattern
[<return: Struct>]
let (|RegexMatchValue|_|) (regex:Regex) input =
let m = regex.Match(input)
if m.Success then Some m.Value
else None
if m.Success then ValueSome m.Value
else ValueNone



Expand Down Expand Up @@ -68,12 +69,13 @@ module Regex =
/// Returns a seq of group values matching the pattern
let parseAll regexStr line =
let rec loop (m:Match) =
seq {
match m.Success with
| true ->
yield (List.tail [ for g in m.Groups -> g.Value ])
yield! loop (m.NextMatch())
| false -> () }
seq {
yield (List.tail [ for g in m.Groups -> g.Value ])
yield! loop (m.NextMatch())
}
| false -> Seq.empty
let m = Regex.Match(line,regexStr)
loop m

Expand Down
7 changes: 4 additions & 3 deletions src/FSharpAux.Core/Seq.fs
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,10 @@ module Seq =
keyList
|> Seq.map (
fun k ->
if m.ContainsKey(k) then
aggregation m.[k]
else
match m.TryGetValue k with
| true, mk ->
aggregation mk
| false, _ ->
defaultValue
)

Expand Down
45 changes: 25 additions & 20 deletions src/FSharpAux.Core/String.fs
Original file line number Diff line number Diff line change
Expand Up @@ -79,46 +79,51 @@ module String =


// Active patterns & operators for parsing strings
let (@?) (s:string) i = if i >= s.Length then None else Some s.[i]
let (@?) (s:string) i = if i >= s.Length then ValueNone else ValueSome s.[i]

let inline satisfies predicate (charOption:option<char>) =
let inline satisfies predicate (charOption:voption<char>) =
match charOption with
| Some c when predicate c -> charOption
| _ -> None
| ValueSome c when predicate c -> charOption
| _ -> ValueNone

[<return: Struct>]
let (|EOF|_|) = function
| Some _ -> None
| _ -> Some ()
| ValueSome _ -> ValueNone
| _ -> ValueSome ()

[<return: Struct>]
let (|LetterDigit|_|) = satisfies Char.IsLetterOrDigit
[<return: Struct>]
let (|Upper|_|) = satisfies Char.IsUpper
[<return: Struct>]
let (|Lower|_|) = satisfies Char.IsLower

/// Turns a string into a nice PascalCase identifier
let niceName (s:string) =
if s = s.ToUpper() then s else
// Starting to parse a new segment
let rec restart i = seq {
let rec restart i =
match s @? i with
| EOF -> ()
| LetterDigit _ & Upper _ -> yield! upperStart i (i + 1)
| LetterDigit _ -> yield! consume i false (i + 1)
| _ -> yield! restart (i + 1) }
| 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 {
and upperStart from i =
match s @? i with
| Upper _ -> yield! consume from true (i + 1)
| Lower _ -> yield! consume from false (i + 1)
| _ -> yield! restart (i + 1) }
| Upper _ -> consume from true (i + 1)
| Lower _ -> consume from false (i + 1)
| _ -> restart (i + 1)
// Consume are letters of the same kind (either all lower or all upper)
and consume from takeUpper i = seq {
and consume from takeUpper i =
match s @? i with
| Lower _ when not takeUpper -> yield! consume from takeUpper (i + 1)
| Upper _ when takeUpper -> yield! consume from takeUpper (i + 1)
| Lower _ when not takeUpper -> consume from takeUpper (i + 1)
| Upper _ when takeUpper -> consume from takeUpper (i + 1)
| _ ->
yield from, i
yield! restart i }
seq {
yield struct (from, i)
yield! restart i }

// Split string into segments and turn them to PascalCase
seq { for i1, i2 in restart 0 do
Expand Down
10 changes: 5 additions & 5 deletions src/FSharpAux.IO/FileIO.fs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ module FileIO =
/// Detects whether the given path does not contains invalid characters.
let isValidPath (path:string) =
Path.GetInvalidPathChars()
|> Array.filter (fun char -> path.Contains(char.ToString()))
|> Array.isEmpty
|> Array.exists (fun char -> path.Contains(char.ToString()))
|> not


/// Creates a directory if it does not exist.
Expand Down Expand Up @@ -140,7 +140,7 @@ module FileIO =
let FileEnumerator (filePath) =
use reader = File.OpenText(filePath)
Seq.unfold(fun line ->
if line = null then
if isNull line then
reader.Close()
None
else
Expand Down Expand Up @@ -206,11 +206,11 @@ module FileIO =


/// Appends a text if the value is not null
let inline appendIfNotNull value s = appendIfTrue (value <> null) (sprintf "%s%A" s value)
let inline appendIfNotNull value s = appendIfTrue (not (isNull value)) (sprintf "%s%A" s value)


/// Appends a text if the value is not null
let inline appendStringIfValueIsNotNull value = appendIfTrue (value <> null)
let inline appendStringIfValueIsNotNull value = appendIfTrue (not (isNull value))


/// Appends a text if the value is not null or empty
Expand Down
5 changes: 3 additions & 2 deletions src/FSharpAux.IO/PathFileName.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ module PathFileName =
| _ -> failwith "No file or directory given."

/// Active Pattern for determining file extension.
[<return: Struct>]
let (|EndsWith|_|) (extension : string) (file : string) =
if file.EndsWith extension then Some()
else None
if file.EndsWith extension then ValueSome()
else ValueNone

/// Active Pattern for determining file name.
let (|FileInfoFullName|) (f : FileInfo) = f.FullName
Expand Down
4 changes: 2 additions & 2 deletions src/FSharpAux.IO/SchemaReader.fs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ module SchemaReader =
let header = convertHeaderLine separator header

Seq.unfold(fun line ->
if line = null then
if isNull line then
reader.Close()
None
else
Expand All @@ -276,7 +276,7 @@ module SchemaReader =
| true ->
for i = 1 to skipLinesBeforeHeader do reader.ReadLine() |> ignore
let tmpLine = reader.ReadLine()
if tmpLine = null then
if isNull tmpLine then
reader.Close()
String.Empty
else
Expand Down
8 changes: 4 additions & 4 deletions src/FSharpAux/PSeq.fs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ module PSeq =
ParallelEnumerable.ElementAt(toP(s), n)

let map2 f s1 s2 =
ParallelEnumerable.Zip(toP(s1),toP(s2), Func<_,_,_>(fun x y -> f x y))
ParallelEnumerable.Zip(toP(s1),toP(s2), Func<_,_,_>(f))

let zip s1 s2 =
ParallelEnumerable.Zip(toP(s1),toP(s2), Func<_,_,_>(fun x y -> (x,y)))
Expand Down Expand Up @@ -167,7 +167,7 @@ module PSeq =
ParallelEnumerable.Select(distinct, Func<_,_>(fun (x,px) -> x))

let sort s =
ParallelEnumerable.OrderBy(toP(s), Func<_,_>(fun x -> x), ComparisonIdentity.Structural<_>) :> pseq<'T>
ParallelEnumerable.OrderBy(toP(s), Func<_,_>(id), ComparisonIdentity.Structural<_>) :> pseq<'T>

let sortBy (f : 'T -> 'Key) s =
ParallelEnumerable.OrderBy(toP(s), Func<_,_>(f), ComparisonIdentity.Structural<_>) :> pseq<'T>
Expand Down Expand Up @@ -235,7 +235,7 @@ module PSeq =
| :? seq<float> as s -> unbox(ParallelEnumerable.Min(toP(s)))
| :? seq<float32> as s -> unbox(ParallelEnumerable.Min(toP(s)))
| :? seq<decimal> as s -> unbox(ParallelEnumerable.Min(toP(s)))
| _ -> ParallelEnumerable.Min(toP(s), Func<_,_>(fun x -> x))
| _ -> ParallelEnumerable.Min(toP(s), Func<_,_>(id))

let inline minBy (f : ^T -> ^U) (s : seq< ^T >) : ^T when ^U : comparison =
let elemsAndVals = ParallelEnumerable.Select(toP(s), Func<_,_>(fun x -> f x, x))
Expand All @@ -250,7 +250,7 @@ module PSeq =
| :? seq<float> as s -> unbox(ParallelEnumerable.Max(toP(s)))
| :? seq<float32> as s -> unbox(ParallelEnumerable.Max(toP(s)))
| :? seq<decimal> as s -> unbox(ParallelEnumerable.Max(toP(s)))
| _ -> ParallelEnumerable.Max(toP(s), Func<_,_>(fun x -> x))
| _ -> ParallelEnumerable.Max(toP(s), Func<_,_>(id))

let inline maxBy (f : ^T -> ^U) (s : seq< ^T >) : ^T =
let elemsAndVals = ParallelEnumerable.Select(toP(s), Func<_,_>(fun x -> f x, x))
Expand Down
Loading