From 41fef587314b4c4c1ca2fd4a73e9b0d2fa45985e Mon Sep 17 00:00:00 2001 From: HLWeil Date: Tue, 12 Mar 2024 17:58:22 +0100 Subject: [PATCH 1/7] first draft of performanceReport target --- build/TestTasks.fs | 29 +++ tests/ISA/ISA.Json.Tests/ArcTypes.Tests.fs | 48 ----- .../ISA.Spreadsheet.Tests.fsproj | 1 - tests/ISA/ISA.Spreadsheet.Tests/Main.fs | 1 - .../Performance.Tests.fs | 45 ---- tests/ISA/ISA.Tests/ArcTable.Tests.fs | 79 +------ tests/TestingUtils/PerformanceReport.fs | 204 ++++++++++++++++++ tests/TestingUtils/TestingUtils.fsproj | 2 + 8 files changed, 238 insertions(+), 171 deletions(-) delete mode 100644 tests/ISA/ISA.Spreadsheet.Tests/Performance.Tests.fs create mode 100644 tests/TestingUtils/PerformanceReport.fs diff --git a/build/TestTasks.fs b/build/TestTasks.fs index 8ebc7921..516f86f8 100644 --- a/build/TestTasks.fs +++ b/build/TestTasks.fs @@ -61,6 +61,35 @@ module RunTests = |> Seq.iter dotnetRun } + +module PerformanceReport = + + let cpu = + Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM\\CentralProcessor\\0", "ProcessorNameString", null) :?> string + + let testPerformancePy = BuildTask.create "testPerformancePy" [clean; build] { + let path = "tests/TestingUtils" + //transpile py files from fsharp code + run dotnet $"fable {path} -o {path}/py --lang python" "" + // run pyxpecto in target path to execute tests in python + run python $"{path}/py/performance_report.py {cpu}" "" + } + let testPerformanceJs = BuildTask.create "testPerformanceJS" [clean; build] { + let path = "tests/TestingUtils" + // transpile js files from fsharp code + run dotnet $"fable {path} -o {path}/js" "" + // run mocha in target path to execute tests + run npx $"mocha {path}/js {cpu}" "" + } + let testPerformanceDotnet = BuildTask.create "testPerformanceDotnet" [clean; build] { + let path = "tests/TestingUtils" + run dotnet $"run --project {path} {cpu}" "" + } + +let perforanceReport = BuildTask.create "PerformanceReport" [PerformanceReport.testPerformancePy; PerformanceReport.testPerformanceJs; PerformanceReport.testPerformanceDotnet] { + () +} + let runTests = BuildTask.create "RunTests" [clean; build; RunTests.runTestsJs; RunTests.runTestsJsNative; RunTests.runTestsPy; RunTests.runTestsDotnet] { () } \ No newline at end of file diff --git a/tests/ISA/ISA.Json.Tests/ArcTypes.Tests.fs b/tests/ISA/ISA.Json.Tests/ArcTypes.Tests.fs index 8c9d1dfc..8ac184f0 100644 --- a/tests/ISA/ISA.Json.Tests/ArcTypes.Tests.fs +++ b/tests/ISA/ISA.Json.Tests/ArcTypes.Tests.fs @@ -179,16 +179,6 @@ let tests_ArcTable = testList "ArcTable" [ let decoded = ArcTable.fromCompressedJsonString encoded Expect.equal decoded filled "empty table is wrong after compressed encoding and decoding" // Set to pTest in Fable, as compressed parsing is around 10times slower than uncompressed parsing. This is weird, since in dotnet it is around 10times faster - #if FABLE_COMPILER - ptestCase "Performance" <| fun _ -> - #else - testCase "Performance" <| fun _ -> - #endif - let t = TestObjects.Spreadsheet.Study.LargeFile.table - Expect.isFasterThan (t.ToCompressedJsonString >> ignore) (t.ToJsonString >> ignore) "toCompressedJsonString is slower than to uncompressed" - let json = t.ToJsonString() - let compressed = Expect.wantFaster (t.ToCompressedJsonString) 1000 "toCompressedJsonString should be faster" - Expect.isTrue (compressed.Length*5 < json.Length) $"compressed should be more than 10 times smaller than uncompressed, but was only {float json.Length / float compressed.Length}x smaller" testCase "rangeColumnSize" <| fun _ -> // testTable column should be saved as range column, this should make it smaller than the IO column even though it has more cells let testTable = ArcTable.init("Test") @@ -258,44 +248,6 @@ let tests_ArcAssay = testList "ArcAssay" [ let decoded = ArcAssay.fromCompressedJsonString encoded Expect.equal decoded filled "empty table is wrong after compressed encoding and decoding" ] - testList "performance" [ - testCase "SingleLongTable_JsonAssay" <| fun _ -> - let a = ArcAssay.init("MyAssay") - let t = a.InitTable("MyTable") - t.AddColumn(CompositeHeader.Input IOType.Source) - t.AddColumn(CompositeHeader.Parameter (OntologyAnnotation.fromString("MyParameter1"))) - t.AddColumn(CompositeHeader.Parameter (OntologyAnnotation.fromString("MyParameter2"))) - t.AddColumn(CompositeHeader.Parameter (OntologyAnnotation.fromString("MyParameter3"))) - t.AddColumn(CompositeHeader.Characteristic (OntologyAnnotation.fromString("MyCharacteristic"))) - t.AddColumn(CompositeHeader.Output IOType.Sample) - let rowCount = 10000 - for i = 0 to rowCount - 1 do - let cells = - [| - CompositeCell.FreeText $"Source{i}" - CompositeCell.FreeText $"Parameter1_value" - CompositeCell.FreeText $"Parameter2_value" - CompositeCell.FreeText $"Parameter3_value{i - i % 10}" - CompositeCell.FreeText $"Characteristic_value" - CompositeCell.FreeText $"Sample{i}" - |] - for j = 0 to cells.Length - 1 do - t.Values.[(j,i)] <- cells.[j] - let f() = ArcAssay.toJsonString a - #if FABLE_COMPILER_JAVASCRIPT - let expectedMs = 5000 - #endif - #if FABLE_COMPILER_PYTHON - let expectedMs = 100000 - #endif - #if !FABLE_COMPILER - let expectedMs = 2500 - #endif - // 1200ms in Dotnet on i7-13800H - // 3412ms in Javascript on i7-13800H - // 24562ms in Javascript on i7-13800H - Expect.wantFaster f expectedMs "toJsonString should be faster" |> ignore - ] ] let tests_ArcStudy = testList "ArcStudy" [ diff --git a/tests/ISA/ISA.Spreadsheet.Tests/ISA.Spreadsheet.Tests.fsproj b/tests/ISA/ISA.Spreadsheet.Tests/ISA.Spreadsheet.Tests.fsproj index 8728b2bf..6ee34c7a 100644 --- a/tests/ISA/ISA.Spreadsheet.Tests/ISA.Spreadsheet.Tests.fsproj +++ b/tests/ISA/ISA.Spreadsheet.Tests/ISA.Spreadsheet.Tests.fsproj @@ -17,7 +17,6 @@ - diff --git a/tests/ISA/ISA.Spreadsheet.Tests/Main.fs b/tests/ISA/ISA.Spreadsheet.Tests/Main.fs index 77b328f5..3c8d206b 100644 --- a/tests/ISA/ISA.Spreadsheet.Tests/Main.fs +++ b/tests/ISA/ISA.Spreadsheet.Tests/Main.fs @@ -12,7 +12,6 @@ let all = testSequenced <| testList "ISA.Spreadsheet" [ ArcStudyTests.main SparseTableTests.main IdentifierTests.main - Tests.Performance.Main ] [] diff --git a/tests/ISA/ISA.Spreadsheet.Tests/Performance.Tests.fs b/tests/ISA/ISA.Spreadsheet.Tests/Performance.Tests.fs deleted file mode 100644 index e344213f..00000000 --- a/tests/ISA/ISA.Spreadsheet.Tests/Performance.Tests.fs +++ /dev/null @@ -1,45 +0,0 @@ -module Tests.Performance - -open ARCtrl.ISA -open FsSpreadsheet -open TestingUtils -open ARCtrl.ISA.Spreadsheet - -let private tests_Study = testList "Study" [ - testCase "LargeWorkbook" <| fun _ -> - let fswb = TestObjects.Spreadsheet.Study.LargeFile.Workbook - let convertToArcFile(fswb:FsWorkbook) = - let timer_start = System.DateTime.Now - let s,_ = ArcStudy.fromFsWorkbook fswb - let timer_end = System.DateTime.Now - let runtime = (timer_end - timer_start).Milliseconds - #if FABLE_COMPILER_PYTHON - let expectedMs = 1500 - #else - let expectedMs = 300 // this is too high and should be reduced - #endif - Expect.equal s.TableCount 1 "Table count" - Expect.isTrue (runtime <= expectedMs) $"Expected conversion to be finished in under {expectedMs}, but it took {runtime}" - convertToArcFile fswb -] - -let private tests_Investigation = testList "Investigation" [ - testCase "WriteManyStudies" <| fun _ -> - let inv = ArcInvestigation.init("MyInvestigation") - for i = 0 to 1500 do - let s = ArcStudy.init($"Study{i}") - inv.AddRegisteredStudy(s) - let testF = fun () -> ArcInvestigation.toFsWorkbook inv - #if FABLE_COMPILER_PYTHON - let expectedMs = 50000 - #else - let expectedMs = 1000 - #endif - let wb = Expect.wantFaster testF expectedMs "Parsing investigation to Workbook is too slow" - Expect.equal (wb.GetWorksheets().Count) 1 "Worksheet count" -] - -let Main = testList "Performance" [ - tests_Study - tests_Investigation -] \ No newline at end of file diff --git a/tests/ISA/ISA.Tests/ArcTable.Tests.fs b/tests/ISA/ISA.Tests/ArcTable.Tests.fs index d7a40565..cca40753 100644 --- a/tests/ISA/ISA.Tests/ArcTable.Tests.fs +++ b/tests/ISA/ISA.Tests/ArcTable.Tests.fs @@ -108,18 +108,6 @@ let private tests_GetHashCode = testList "GetHashCode" [ let notActual = create_testTable() Expect.notEqual actual notActual "equal" Expect.notEqual (actual.GetHashCode()) (notActual.GetHashCode()) "Hash" - testCase "Performance" <| fun _ -> - let testTable = ArcTable.init("Test") - let values = Array.init 10000 (fun i -> CompositeCell.createFreeText (string i)) - testTable.AddColumn(CompositeHeader.FreeText "Header", values) - let f1 () = testTable.GetHashCode() - #if FABLE_COMPILER_PYTHON - let expectedMs = 500 - #else - let expectedMs = 50 - #endif - // On i7-13800H, 2ms in Dotnet and 18ms in javascript - Expect.wantFaster f1 expectedMs "GetHashCode is too slow" |> ignore ] let private tests_validate = @@ -483,29 +471,6 @@ let private tests_UpdateCell = let eval() = table.UpdateCellAt(0,0,cell) Expect.throws eval "" ) - - // Commented this test out, as the behaviour is different in dotnet and js, but both implementations are very close together performance-wise - - //testCase "performance" (fun () -> - // // Test, that for most cases (because of performance), setter should be used - // let f1 = fun () -> - // let table = ArcTable.init("Table") - // for i = 0 to 10 do - // table.Headers.Insert(i,CompositeHeader.FreeText $"Header_{i}") - // for j = 0 to 5000 do - // ArcTableAux.Unchecked.setCellAt(i,j,CompositeCell.createFreeText $"Cell_{i}_{j}") table.Values - // let f2 = fun () -> - // let table = ArcTable.init("Table") - // for i = 0 to 10 do - // table.Headers.Insert(i,CompositeHeader.FreeText $"Header_{i}") - // for j = 0 to 5000 do - // ArcTableAux.Unchecked.addCellAt(i,j,CompositeCell.createFreeText $"Cell_{i}_{j}") table.Values - // Expect.isFasterThan f1 f2 "SetCell Implementation should be faster than reference" - - - - //) - ] let private tests_UpdateColumn = @@ -2023,19 +1988,6 @@ let private tests_AddRows = else Expect.equal table.Values.[columnIndex, rowIndex] newTable.Values.[columnIndex, rowIndex-newColumnCount] $"Cell {columnIndex},{rowIndex}" ) - testCase "performance" (fun () -> - let table = ArcTable("MyTable",ResizeArray [CompositeHeader.Input IOType.Sample;CompositeHeader.FreeText "Freetext1" ; CompositeHeader.FreeText "Freetext2"; CompositeHeader.Output IOType.Sample], System.Collections.Generic.Dictionary()) - let rows = - Array.init 10000 (fun i -> - [|CompositeCell.FreeText $"Source_{i}"; CompositeCell.FreeText $"FT1_{i}"; CompositeCell.FreeText $"FT2_{i}"; CompositeCell.FreeText $"Sample_{i}"; |]) - let testF = fun () -> table.AddRows(rows) - #if FABLE_COMPILER_PYTHON - let expectedMs = 1000 - #else - let expectedMs = 100 - #endif - Expect.wantFaster testF expectedMs $"AddRows is too slow." |> ignore - ) ] let private tests_UpdateRefWithSheet = @@ -2316,34 +2268,9 @@ let private tests_equality = testList "equality" [ ] -let private tests_fillMissing = testList "fillMissing" [ - testCase "performance" <| fun _ -> - - let headers = ResizeArray [CompositeHeader.Input IOType.Sample;CompositeHeader.FreeText "Freetext1" ; CompositeHeader.FreeText "Freetext2"; CompositeHeader.Output IOType.Sample] - let values = System.Collections.Generic.Dictionary() - for i = 0 to 20000 do - if i%2 = 0 then - ArcTableAux.Unchecked.setCellAt(0,i,(CompositeCell.FreeText $"Source_{i}")) values - ArcTableAux.Unchecked.setCellAt(1,i,(CompositeCell.FreeText $"FT1_{i}")) values - ArcTableAux.Unchecked.setCellAt(2,i,(CompositeCell.FreeText $"FT2_{i}")) values - ArcTableAux.Unchecked.setCellAt(3,i,(CompositeCell.FreeText $"FT3_{i}")) values - ArcTableAux.Unchecked.setCellAt(6,i,(CompositeCell.FreeText $"Sample_{i}")) values - else - ArcTableAux.Unchecked.setCellAt(0,i,(CompositeCell.FreeText $"Source_{i}")) values - ArcTableAux.Unchecked.setCellAt(3,i,(CompositeCell.FreeText $"FT3_{i}")) values - ArcTableAux.Unchecked.setCellAt(4,i,(CompositeCell.FreeText $"FT4_{i}")) values - ArcTableAux.Unchecked.setCellAt(5,i,(CompositeCell.FreeText $"FT5_{i}")) values - ArcTableAux.Unchecked.setCellAt(6,i,(CompositeCell.FreeText $"Sample_{i}")) values - let testF = fun () -> ArcTableAux.Unchecked.fillMissingCells headers values - #if FABLE_COMPILER_PYTHON - let expectedMs = 10000 - #else - let expectedMs = 220 - #endif - //4800ms in python on i7-13800H - Expect.wantFaster testF expectedMs "fillMissing is too slow." |> ignore // 130ms in javascript, dotnet faster than 100ms - ] +//let private tests_fillMissing = testList "fillMissing" [ +// ] let main = testList "ArcTable" [ @@ -2368,5 +2295,5 @@ let main = tests_IterColumns tests_GetHashCode tests_equality - tests_fillMissing + //tests_fillMissing ] \ No newline at end of file diff --git a/tests/TestingUtils/PerformanceReport.fs b/tests/TestingUtils/PerformanceReport.fs new file mode 100644 index 00000000..140a4be4 --- /dev/null +++ b/tests/TestingUtils/PerformanceReport.fs @@ -0,0 +1,204 @@ +module PerformanceReport + +open ARCtrl.ISA +open ARCtrl.ISA.Json +open ARCtrl.ISA.Spreadsheet + +type PerformanceTest = + { + Name : string + Description : string + Test : unit -> unit + Time : int option + } + + member this.Run() = + printfn "Running test: %s" this.Name + let timer_start = System.DateTime.Now + this.Test() + let timer_end = System.DateTime.Now + let runtime = (timer_end - timer_start).Milliseconds + {this with Time = Some runtime} + + static member create name description test = {Name = name; Description = description; Test = test; Time = None} + +type PerformanceReport = + { + CPU : string + Lang : string + Tests : PerformanceTest list + } + + static member create cpu lang tests = {CPU = cpu; Lang = lang; Tests = tests} + + member this.RunTests() = + {this with Tests = this.Tests |> List.map (fun t -> t.Run())} + + member this.ToMarkdown() = + let header = $"| Name | Description | CPU | Lang Time (ms) |" + let separator = $"| --- | --- | --- | --- |" + let tests = this.Tests |> List.map (fun t -> $"| {t.Name} | {t.Description} | {this.CPU} | {t.Time.Value} |") + String.concat "\n" [header; separator; tests |> String.concat "\n"] + + +let table_GetHashCode = + let testTable = ArcTable.init("Test") + let values = Array.init 10000 (fun i -> CompositeCell.createFreeText (string i)) + testTable.AddColumn(CompositeHeader.FreeText "Header", values) + PerformanceTest.create + "Table_GetHashCode" + "From a table with 1 column and 10000 rows, retrieve the Hash Code" + (fun _ -> + testTable.GetHashCode() + |> ignore + ) + + +// // Commented this test out, as the behaviour is different in dotnet and js, but both implementations are very close together performance-wise +// //testCase "performance" (fun () -> +// // // Test, that for most cases (because of performance), setter should be used +// // let f1 = fun () -> +// // let table = ArcTable.init("Table") +// // for i = 0 to 10 do +// // table.Headers.Insert(i,CompositeHeader.FreeText $"Header_{i}") +// // for j = 0 to 5000 do +// // ArcTableAux.Unchecked.setCellAt(i,j,CompositeCell.createFreeText $"Cell_{i}_{j}") table.Values +// // let f2 = fun () -> +// // let table = ArcTable.init("Table") +// // for i = 0 to 10 do +// // table.Headers.Insert(i,CompositeHeader.FreeText $"Header_{i}") +// // for j = 0 to 5000 do +// // ArcTableAux.Unchecked.addCellAt(i,j,CompositeCell.createFreeText $"Cell_{i}_{j}") table.Values +// // Expect.isFasterThan f1 f2 "SetCell Implementation should be faster than reference" + + +let table_AddRows = + + let table = ArcTable("MyTable",ResizeArray [CompositeHeader.Input IOType.Sample;CompositeHeader.FreeText "Freetext1" ; CompositeHeader.FreeText "Freetext2"; CompositeHeader.Output IOType.Sample], System.Collections.Generic.Dictionary()) + let rows = + Array.init 10000 (fun i -> + [|CompositeCell.FreeText $"Source_{i}"; CompositeCell.FreeText $"FT1_{i}"; CompositeCell.FreeText $"FT2_{i}"; CompositeCell.FreeText $"Sample_{i}"; |]) + PerformanceTest.create + "Table_AddRows" + "Add 10000 rows to a table with 4 columns." + (fun _ -> + table.AddRows(rows) + |> ignore + ) + +let table_fillMissingCells = + let headers = ResizeArray [CompositeHeader.Input IOType.Sample;CompositeHeader.FreeText "Freetext1" ; CompositeHeader.FreeText "Freetext2"; CompositeHeader.Output IOType.Sample] + let values = System.Collections.Generic.Dictionary() + for i = 0 to 20000 do + if i%2 = 0 then + ArcTableAux.Unchecked.setCellAt(0,i,(CompositeCell.FreeText $"Source_{i}")) values + ArcTableAux.Unchecked.setCellAt(1,i,(CompositeCell.FreeText $"FT1_{i}")) values + ArcTableAux.Unchecked.setCellAt(2,i,(CompositeCell.FreeText $"FT2_{i}")) values + ArcTableAux.Unchecked.setCellAt(3,i,(CompositeCell.FreeText $"FT3_{i}")) values + ArcTableAux.Unchecked.setCellAt(6,i,(CompositeCell.FreeText $"Sample_{i}")) values + else + ArcTableAux.Unchecked.setCellAt(0,i,(CompositeCell.FreeText $"Source_{i}")) values + ArcTableAux.Unchecked.setCellAt(3,i,(CompositeCell.FreeText $"FT3_{i}")) values + ArcTableAux.Unchecked.setCellAt(4,i,(CompositeCell.FreeText $"FT4_{i}")) values + ArcTableAux.Unchecked.setCellAt(5,i,(CompositeCell.FreeText $"FT5_{i}")) values + ArcTableAux.Unchecked.setCellAt(6,i,(CompositeCell.FreeText $"Sample_{i}")) values + PerformanceTest.create + "Table_fillMissingCells" + "For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values." + (fun () -> ArcTableAux.Unchecked.fillMissingCells headers values |> ignore) + +let table_toJson = + let t = TestObjects.Spreadsheet.Study.LargeFile.table + PerformanceTest.create + "Table_ToJson" + "" + (fun _ -> t.ToJsonString() |> ignore) + +let table_toCompressedJson = + let t = TestObjects.Spreadsheet.Study.LargeFile.table + PerformanceTest.create + "Table_ToCompressedJson" + "" + (fun _ -> t.ToCompressedJsonString() |> ignore) + + +let assay_toJson = + let a = ArcAssay.init("MyAssay") + let t = a.InitTable("MyTable") + t.AddColumn(CompositeHeader.Input IOType.Source) + t.AddColumn(CompositeHeader.Parameter (OntologyAnnotation.fromString("MyParameter1"))) + t.AddColumn(CompositeHeader.Parameter (OntologyAnnotation.fromString("MyParameter"))) + t.AddColumn(CompositeHeader.Parameter (OntologyAnnotation.fromString("MyParameter"))) + t.AddColumn(CompositeHeader.Characteristic (OntologyAnnotation.fromString("MyCharacteristic"))) + t.AddColumn(CompositeHeader.Output IOType.Sample) + let rowCount = 10000 + for i = 0 to rowCount - 1 do + let cells = + [| + CompositeCell.FreeText $"Source{i}" + CompositeCell.FreeText $"Parameter1_value" + CompositeCell.FreeText $"Parameter2_value" + CompositeCell.FreeText $"Parameter3_value{i - i % 10}" + CompositeCell.FreeText $"Characteristic_value" + CompositeCell.FreeText $"Sample{i}" + |] + for j = 0 to cells.Length - 1 do + t.Values.[(j,i)] <- cells.[j] + PerformanceTest.create + "Assay_toJson" + "Parse an assay with one table with 10000 rows and 6 columns to json" + (fun _ -> ArcAssay.toJsonString a |> ignore) + +let study_fromWorkbook = + let fswb = TestObjects.Spreadsheet.Study.LargeFile.Workbook + PerformanceTest.create + "Study_FromWorkbook" + "Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy" + (fun _ -> ArcStudy.fromFsWorkbook fswb |> ignore) + +let investigation_toWorkbook_ManyStudies = + let inv = ArcInvestigation.init("MyInvestigation") + for i = 0 to 1500 do + let s = ArcStudy.init($"Study{i}") + inv.AddRegisteredStudy(s) + PerformanceTest.create + "Investigation_ToWorkbook_ManyStudies" + "Parse an investigation with 1500 studies to a workbook" + (fun _ -> ArcInvestigation.toFsWorkbook inv |> ignore) + + +let allPerformanceTests = + [ + table_GetHashCode + table_AddRows + table_fillMissingCells + table_toJson + table_toCompressedJson + assay_toJson + study_fromWorkbook + investigation_toWorkbook_ManyStudies + ] + + +let createMarkdownPerformanceReport lang cpu = + let report = PerformanceReport.create cpu lang allPerformanceTests + report.RunTests().ToMarkdown() + +let lang = + #if FABLE_COMPILER_JAVASCRIPT + "JavaScript" + #endif + #if FABLE_COMPILER_PYTHON + "Python" + #endif + #if !FABLE_COMPILER + "F#" + #endif + + +[] +let main argv = + let cpu = argv.[1] + let report = createMarkdownPerformanceReport lang cpu + printfn "%s" report + 0 diff --git a/tests/TestingUtils/TestingUtils.fsproj b/tests/TestingUtils/TestingUtils.fsproj index 8c6d504a..983b65da 100644 --- a/tests/TestingUtils/TestingUtils.fsproj +++ b/tests/TestingUtils/TestingUtils.fsproj @@ -2,6 +2,7 @@ net6.0 + Exe true @@ -22,6 +23,7 @@ + From 27aac66eea741cf2554198d063e217d333366068 Mon Sep 17 00:00:00 2001 From: HLWeil Date: Fri, 15 Mar 2024 15:46:42 +0100 Subject: [PATCH 2/7] move performance report build targets and create first reports --- build/Build.fs | 2 - build/Build.fsproj | 1 + build/PerformanceTasks.fs | 36 +++++++++++ build/TestTasks.fs | 29 --------- docs/scripts_fsharp/ArcInvestigation.fsx | 2 +- tests/TestingUtils/Library.fs | 7 +++ tests/TestingUtils/PerformanceReport.fs | 62 +++++++++++++++---- .../2024_3_15_PerformanceReport_Combined.md | 12 ++++ .../2024_3_15_PerformanceReport_FSharp.md | 10 +++ .../2024_3_15_PerformanceReport_JavaScript.md | 10 +++ .../2024_3_15_PerformanceReport_Python.md | 10 +++ tests/TestingUtils/TestingUtils.fsproj | 1 + 12 files changed, 137 insertions(+), 45 deletions(-) create mode 100644 build/PerformanceTasks.fs create mode 100644 tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Combined.md create mode 100644 tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md create mode 100644 tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md create mode 100644 tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Python.md diff --git a/build/Build.fs b/build/Build.fs index bf3cc6d5..88f51d63 100644 --- a/build/Build.fs +++ b/build/Build.fs @@ -29,8 +29,6 @@ let _preRelease = "PreRelease" [setPrereleaseTag; clean; build; runTests; packPrerelease; createPrereleaseTag; publishNugetPrerelease; publishNPMPrerelease] -ReleaseNotesTasks.updateReleaseNotes |> ignore - [] let main args = runOrDefault build args diff --git a/build/Build.fsproj b/build/Build.fsproj index ecbd44dd..7c5011fd 100644 --- a/build/Build.fsproj +++ b/build/Build.fsproj @@ -13,6 +13,7 @@ + diff --git a/build/PerformanceTasks.fs b/build/PerformanceTasks.fs new file mode 100644 index 00000000..1faae83f --- /dev/null +++ b/build/PerformanceTasks.fs @@ -0,0 +1,36 @@ +module PerformanceTasks + +open BlackFox.Fake +open Fake.DotNet + +open ProjectInfo +open BasicTasks +open Fake.Core + +module PerformanceReport = + + let cpu = + Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM\\CentralProcessor\\0", "ProcessorNameString", null) :?> string + + let testPerformancePy = BuildTask.create "testPerformancePy" [clean; build] { + let path = "tests/TestingUtils" + //transpile py files from fsharp code + run dotnet $"fable {path} -o {path}/py --lang python" "" + // run pyxpecto in target path to execute tests in python + run python $"{path}/py/performance_report.py \"{cpu}\"" "" + } + let testPerformanceJs = BuildTask.create "testPerformanceJS" [clean; build] { + let path = "tests/TestingUtils" + // transpile js files from fsharp code + run dotnet $"fable {path} -o {path}/js" "" + // run mocha in target path to execute tests + run npx $"mocha {path}/js \"{cpu}\"" "" + } + let testPerformanceDotnet = BuildTask.create "testPerformanceDotnet" [clean; build] { + let path = "tests/TestingUtils" + run dotnet $"run --project {path} \"{cpu}\"" "" + } + +let perforanceReport = BuildTask.create "PerformanceReport" [PerformanceReport.testPerformancePy; PerformanceReport.testPerformanceJs; PerformanceReport.testPerformanceDotnet] { + () +} \ No newline at end of file diff --git a/build/TestTasks.fs b/build/TestTasks.fs index 516f86f8..8ebc7921 100644 --- a/build/TestTasks.fs +++ b/build/TestTasks.fs @@ -61,35 +61,6 @@ module RunTests = |> Seq.iter dotnetRun } - -module PerformanceReport = - - let cpu = - Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM\\CentralProcessor\\0", "ProcessorNameString", null) :?> string - - let testPerformancePy = BuildTask.create "testPerformancePy" [clean; build] { - let path = "tests/TestingUtils" - //transpile py files from fsharp code - run dotnet $"fable {path} -o {path}/py --lang python" "" - // run pyxpecto in target path to execute tests in python - run python $"{path}/py/performance_report.py {cpu}" "" - } - let testPerformanceJs = BuildTask.create "testPerformanceJS" [clean; build] { - let path = "tests/TestingUtils" - // transpile js files from fsharp code - run dotnet $"fable {path} -o {path}/js" "" - // run mocha in target path to execute tests - run npx $"mocha {path}/js {cpu}" "" - } - let testPerformanceDotnet = BuildTask.create "testPerformanceDotnet" [clean; build] { - let path = "tests/TestingUtils" - run dotnet $"run --project {path} {cpu}" "" - } - -let perforanceReport = BuildTask.create "PerformanceReport" [PerformanceReport.testPerformancePy; PerformanceReport.testPerformanceJs; PerformanceReport.testPerformanceDotnet] { - () -} - let runTests = BuildTask.create "RunTests" [clean; build; RunTests.runTestsJs; RunTests.runTestsJsNative; RunTests.runTestsPy; RunTests.runTestsDotnet] { () } \ No newline at end of file diff --git a/docs/scripts_fsharp/ArcInvestigation.fsx b/docs/scripts_fsharp/ArcInvestigation.fsx index 9d39b58e..ea3d0d71 100644 --- a/docs/scripts_fsharp/ArcInvestigation.fsx +++ b/docs/scripts_fsharp/ArcInvestigation.fsx @@ -20,7 +20,7 @@ open FsSpreadsheet.Net let fswb = ArcInvestigation.toFsWorkbook investigation_comments -fswb.ToFile("test2.isa.investigation.xlsx") +fswb.ToXlsxFile("test2.isa.investigation.xlsx") // ## Json - Write diff --git a/tests/TestingUtils/Library.fs b/tests/TestingUtils/Library.fs index 3240f2d8..80b76242 100644 --- a/tests/TestingUtils/Library.fs +++ b/tests/TestingUtils/Library.fs @@ -59,6 +59,13 @@ type Stopwatch() = | Some start, Some stop -> stop - start | _, _ -> failwith "Error. Unable to call `Elapsed` without calling `Start` and `Stop` before." + static member measure f = + let stopwatch = Stopwatch() + stopwatch.Start() + let res = f() + stopwatch.Stop() + stopwatch.Elapsed.TotalMilliseconds + /// Fable compatible Expecto/Mocha/Pyxpecto unification module Expect = open Utils diff --git a/tests/TestingUtils/PerformanceReport.fs b/tests/TestingUtils/PerformanceReport.fs index 140a4be4..45569d7a 100644 --- a/tests/TestingUtils/PerformanceReport.fs +++ b/tests/TestingUtils/PerformanceReport.fs @@ -3,6 +3,29 @@ open ARCtrl.ISA open ARCtrl.ISA.Json open ARCtrl.ISA.Spreadsheet +open Fable.Core + +#if FABLE_COMPILER_JAVASCRIPT +open Node.Api +#endif + +#if FABLE_COMPILER_PYTHON +open Fable.Python.Builtins +#endif + +let writeFile (path : string) (content : string) = + #if FABLE_COMPILER_JAVASCRIPT + fs.writeFileSync(path,content) + #endif + #if FABLE_COMPILER_PYTHON + let file = builtins.``open``(path, OpenTextMode.Write) + file.write(content) |> ignore + #endif + #if !FABLE_COMPILER + System.IO.File.WriteAllText(path,content) + #endif + + //fs.writeFile(path,content) type PerformanceTest = { @@ -13,12 +36,10 @@ type PerformanceTest = } member this.Run() = - printfn "Running test: %s" this.Name - let timer_start = System.DateTime.Now - this.Test() - let timer_end = System.DateTime.Now - let runtime = (timer_end - timer_start).Milliseconds - {this with Time = Some runtime} + printfn "%A: Running test: %s" System.DateTime.Now this.Name + let time = TestingUtils.Stopwatch.measure(this.Test) |> int + printfn "\tC%A: Completeted in %ims" System.DateTime.Now time + {this with Time = Some time} static member create name description test = {Name = name; Description = description; Test = test; Time = None} @@ -35,7 +56,7 @@ type PerformanceReport = {this with Tests = this.Tests |> List.map (fun t -> t.Run())} member this.ToMarkdown() = - let header = $"| Name | Description | CPU | Lang Time (ms) |" + let header = $"| Name | Description | CPU | {this.Lang} Time (ms) |" let separator = $"| --- | --- | --- | --- |" let tests = this.Tests |> List.map (fun t -> $"| {t.Name} | {t.Description} | {this.CPU} | {t.Time.Value} |") String.concat "\n" [header; separator; tests |> String.concat "\n"] @@ -111,16 +132,15 @@ let table_toJson = let t = TestObjects.Spreadsheet.Study.LargeFile.table PerformanceTest.create "Table_ToJson" - "" + "Serialize a table with 5 columns and 10000 rows to json." (fun _ -> t.ToJsonString() |> ignore) let table_toCompressedJson = let t = TestObjects.Spreadsheet.Study.LargeFile.table PerformanceTest.create "Table_ToCompressedJson" - "" - (fun _ -> t.ToCompressedJsonString() |> ignore) - + "Serialize a table with 5 columns and 10000 rows to compressed json." + (fun _ -> t.ToCompressedJsonString() |> ignore) let assay_toJson = let a = ArcAssay.init("MyAssay") @@ -192,13 +212,29 @@ let lang = "Python" #endif #if !FABLE_COMPILER - "F#" + "FSharp" + #endif + + +let argumentNumber = + #if FABLE_COMPILER_JAVASCRIPT + 1 + #else + 0 #endif [] let main argv = - let cpu = argv.[1] + printfn "Arguments:" + for arg in argv do + printfn "\t%s" arg + let cpu = argv.[argumentNumber] let report = createMarkdownPerformanceReport lang cpu + let timeString = + let dt = System.DateTime.Today + $"{dt.Year}_{dt.Month}_{dt.Day}" + let outFile = $"tests/TestingUtils/PerformanceReport/{timeString}_PerformanceReport_{lang}.md" + writeFile outFile report printfn "%s" report 0 diff --git a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Combined.md b/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Combined.md new file mode 100644 index 00000000..8e1daab1 --- /dev/null +++ b/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Combined.md @@ -0,0 +1,12 @@ +Measured on 13th Gen Intel(R) Core(TM) i7-13800H + +| Name | Description | FSharp Time (ms) | JavaScript Time (ms) | Python Time (ms) | +| --- | --- | --- | --- | --- | +| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 5 | 21 | 226 | +| Table_AddRows | Add 10000 rows to a table with 4 columns. | 15 | 22 | 289 | +| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 49 | 108 | 4813 | +| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 1099 | 481 | 6833 | +| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 261 | 2266 | 717334 | +| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 915 | 2459 | 28799 | +| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 97 | 87 | 1249 | +| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 621 | 379 | 9974 | \ No newline at end of file diff --git a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md b/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md new file mode 100644 index 00000000..c23cff5e --- /dev/null +++ b/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md @@ -0,0 +1,10 @@ +| Name | Description | CPU | FSharp Time (ms) | +| --- | --- | --- | --- | +| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 13th Gen Intel(R) Core(TM) i7-13800H | 5 | +| Table_AddRows | Add 10000 rows to a table with 4 columns. | 13th Gen Intel(R) Core(TM) i7-13800H | 15 | +| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 13th Gen Intel(R) Core(TM) i7-13800H | 49 | +| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 13th Gen Intel(R) Core(TM) i7-13800H | 1099 | +| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 13th Gen Intel(R) Core(TM) i7-13800H | 261 | +| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 13th Gen Intel(R) Core(TM) i7-13800H | 915 | +| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 13th Gen Intel(R) Core(TM) i7-13800H | 97 | +| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 13th Gen Intel(R) Core(TM) i7-13800H | 621 | \ No newline at end of file diff --git a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md b/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md new file mode 100644 index 00000000..07424d7f --- /dev/null +++ b/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md @@ -0,0 +1,10 @@ +| Name | Description | CPU | JavaScript Time (ms) | +| --- | --- | --- | --- | +| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 13th Gen Intel(R) Core(TM) i7-13800H | 21 | +| Table_AddRows | Add 10000 rows to a table with 4 columns. | 13th Gen Intel(R) Core(TM) i7-13800H | 22 | +| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 13th Gen Intel(R) Core(TM) i7-13800H | 108 | +| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 13th Gen Intel(R) Core(TM) i7-13800H | 481 | +| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 13th Gen Intel(R) Core(TM) i7-13800H | 2266 | +| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 13th Gen Intel(R) Core(TM) i7-13800H | 2459 | +| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 13th Gen Intel(R) Core(TM) i7-13800H | 87 | +| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 13th Gen Intel(R) Core(TM) i7-13800H | 379 | \ No newline at end of file diff --git a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Python.md b/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Python.md new file mode 100644 index 00000000..b2a6abda --- /dev/null +++ b/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Python.md @@ -0,0 +1,10 @@ +| Name | Description | CPU | Python Time (ms) | +| --- | --- | --- | --- | +| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 13th Gen Intel(R) Core(TM) i7-13800H | 226 | +| Table_AddRows | Add 10000 rows to a table with 4 columns. | 13th Gen Intel(R) Core(TM) i7-13800H | 289 | +| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 13th Gen Intel(R) Core(TM) i7-13800H | 4813 | +| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 13th Gen Intel(R) Core(TM) i7-13800H | 6833 | +| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 13th Gen Intel(R) Core(TM) i7-13800H | 717334 | +| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 13th Gen Intel(R) Core(TM) i7-13800H | 28799 | +| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 13th Gen Intel(R) Core(TM) i7-13800H | 1249 | +| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 13th Gen Intel(R) Core(TM) i7-13800H | 9974 | \ No newline at end of file diff --git a/tests/TestingUtils/TestingUtils.fsproj b/tests/TestingUtils/TestingUtils.fsproj index 983b65da..44756787 100644 --- a/tests/TestingUtils/TestingUtils.fsproj +++ b/tests/TestingUtils/TestingUtils.fsproj @@ -26,6 +26,7 @@ + From 9e796856e9b374bc13154457b74639e7a3cf2953 Mon Sep 17 00:00:00 2001 From: HLWeil Date: Fri, 15 Mar 2024 17:33:04 +0100 Subject: [PATCH 3/7] move performance report into speedtest project --- build/BasicTasks.fs | 11 +++++++++++ build/Build.fs | 3 +++ build/PerformanceTasks.fs | 10 +++++----- .../PerformanceReport.fs | 18 ++---------------- .../2024_3_15_PerformanceReport_Combined.md | 0 .../2024_3_15_PerformanceReport_FSharp.md | 12 ++++++------ .../2024_3_15_PerformanceReport_JavaScript.md | 16 ++++++++-------- .../2024_3_15_PerformanceReport_Python.md | 16 ++++++++-------- tests/Speedtest/Program.fs | 12 +++++++++++- tests/Speedtest/Speedtest.fsproj | 5 +++++ tests/TestingUtils/TestingUtils.fsproj | 1 - 11 files changed, 59 insertions(+), 45 deletions(-) rename tests/{TestingUtils => Speedtest}/PerformanceReport.fs (96%) rename tests/{TestingUtils => Speedtest}/PerformanceReport/2024_3_15_PerformanceReport_Combined.md (100%) rename tests/{TestingUtils => Speedtest}/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md (80%) rename tests/{TestingUtils => Speedtest}/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md (76%) rename tests/{TestingUtils => Speedtest}/PerformanceReport/2024_3_15_PerformanceReport_Python.md (80%) diff --git a/build/BasicTasks.fs b/build/BasicTasks.fs index d24953d6..449e4f9f 100644 --- a/build/BasicTasks.fs +++ b/build/BasicTasks.fs @@ -83,6 +83,17 @@ module Helper = let dotnet = createProcess "dotnet" + let node = + let nodePath = + match ProcessUtils.tryFindFileOnPath "node" with + | Some path -> path + | None -> + "node was not found in path. Please install it and make sure it's available from your path. " + + "See https://safe-stack.github.io/docs/quickstart/#install-pre-requisites for more info" + |> failwith + + createProcess nodePath + let npx = let npmPath = match ProcessUtils.tryFindFileOnPath "npx" with diff --git a/build/Build.fs b/build/Build.fs index 88f51d63..0ffa83f7 100644 --- a/build/Build.fs +++ b/build/Build.fs @@ -29,6 +29,9 @@ let _preRelease = "PreRelease" [setPrereleaseTag; clean; build; runTests; packPrerelease; createPrereleaseTag; publishNugetPrerelease; publishNPMPrerelease] +ReleaseNotesTasks.updateReleaseNotes |> ignore +PerformanceTasks.perforanceReport |> ignore + [] let main args = runOrDefault build args diff --git a/build/PerformanceTasks.fs b/build/PerformanceTasks.fs index 1faae83f..49457e6f 100644 --- a/build/PerformanceTasks.fs +++ b/build/PerformanceTasks.fs @@ -13,21 +13,21 @@ module PerformanceReport = Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM\\CentralProcessor\\0", "ProcessorNameString", null) :?> string let testPerformancePy = BuildTask.create "testPerformancePy" [clean; build] { - let path = "tests/TestingUtils" + let path = "tests/Speedtest" //transpile py files from fsharp code run dotnet $"fable {path} -o {path}/py --lang python" "" // run pyxpecto in target path to execute tests in python - run python $"{path}/py/performance_report.py \"{cpu}\"" "" + run python $"{path}/py/program.py \"{cpu}\"" "" } let testPerformanceJs = BuildTask.create "testPerformanceJS" [clean; build] { - let path = "tests/TestingUtils" + let path = "tests/Speedtest" // transpile js files from fsharp code run dotnet $"fable {path} -o {path}/js" "" // run mocha in target path to execute tests - run npx $"mocha {path}/js \"{cpu}\"" "" + run node $"{path}/js/program.js \"{cpu}\"" "" } let testPerformanceDotnet = BuildTask.create "testPerformanceDotnet" [clean; build] { - let path = "tests/TestingUtils" + let path = "tests/Speedtest" run dotnet $"run --project {path} \"{cpu}\"" "" } diff --git a/tests/TestingUtils/PerformanceReport.fs b/tests/Speedtest/PerformanceReport.fs similarity index 96% rename from tests/TestingUtils/PerformanceReport.fs rename to tests/Speedtest/PerformanceReport.fs index 45569d7a..a4e05985 100644 --- a/tests/TestingUtils/PerformanceReport.fs +++ b/tests/Speedtest/PerformanceReport.fs @@ -215,26 +215,12 @@ let lang = "FSharp" #endif - -let argumentNumber = - #if FABLE_COMPILER_JAVASCRIPT - 1 - #else - 0 - #endif - - -[] -let main argv = - printfn "Arguments:" - for arg in argv do - printfn "\t%s" arg - let cpu = argv.[argumentNumber] +let runReport cpu = let report = createMarkdownPerformanceReport lang cpu let timeString = let dt = System.DateTime.Today $"{dt.Year}_{dt.Month}_{dt.Day}" - let outFile = $"tests/TestingUtils/PerformanceReport/{timeString}_PerformanceReport_{lang}.md" + let outFile = $"tests/Speedtest/PerformanceReport/{timeString}_PerformanceReport_{lang}.md" writeFile outFile report printfn "%s" report 0 diff --git a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Combined.md b/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_Combined.md similarity index 100% rename from tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Combined.md rename to tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_Combined.md diff --git a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md b/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md similarity index 80% rename from tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md rename to tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md index c23cff5e..ff21c915 100644 --- a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md +++ b/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md @@ -2,9 +2,9 @@ | --- | --- | --- | --- | | Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 13th Gen Intel(R) Core(TM) i7-13800H | 5 | | Table_AddRows | Add 10000 rows to a table with 4 columns. | 13th Gen Intel(R) Core(TM) i7-13800H | 15 | -| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 13th Gen Intel(R) Core(TM) i7-13800H | 49 | -| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 13th Gen Intel(R) Core(TM) i7-13800H | 1099 | -| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 13th Gen Intel(R) Core(TM) i7-13800H | 261 | -| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 13th Gen Intel(R) Core(TM) i7-13800H | 915 | -| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 13th Gen Intel(R) Core(TM) i7-13800H | 97 | -| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 13th Gen Intel(R) Core(TM) i7-13800H | 621 | \ No newline at end of file +| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 13th Gen Intel(R) Core(TM) i7-13800H | 47 | +| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 13th Gen Intel(R) Core(TM) i7-13800H | 1298 | +| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 13th Gen Intel(R) Core(TM) i7-13800H | 289 | +| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 13th Gen Intel(R) Core(TM) i7-13800H | 927 | +| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 13th Gen Intel(R) Core(TM) i7-13800H | 129 | +| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 13th Gen Intel(R) Core(TM) i7-13800H | 556 | \ No newline at end of file diff --git a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md b/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md similarity index 76% rename from tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md rename to tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md index 07424d7f..d58be2db 100644 --- a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md +++ b/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md @@ -1,10 +1,10 @@ | Name | Description | CPU | JavaScript Time (ms) | | --- | --- | --- | --- | -| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 13th Gen Intel(R) Core(TM) i7-13800H | 21 | -| Table_AddRows | Add 10000 rows to a table with 4 columns. | 13th Gen Intel(R) Core(TM) i7-13800H | 22 | -| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 13th Gen Intel(R) Core(TM) i7-13800H | 108 | -| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 13th Gen Intel(R) Core(TM) i7-13800H | 481 | -| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 13th Gen Intel(R) Core(TM) i7-13800H | 2266 | -| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 13th Gen Intel(R) Core(TM) i7-13800H | 2459 | -| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 13th Gen Intel(R) Core(TM) i7-13800H | 87 | -| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 13th Gen Intel(R) Core(TM) i7-13800H | 379 | \ No newline at end of file +| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 13th Gen Intel(R) Core(TM) i7-13800H | 11 | +| Table_AddRows | Add 10000 rows to a table with 4 columns. | 13th Gen Intel(R) Core(TM) i7-13800H | 23 | +| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 13th Gen Intel(R) Core(TM) i7-13800H | 111 | +| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 13th Gen Intel(R) Core(TM) i7-13800H | 521 | +| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 13th Gen Intel(R) Core(TM) i7-13800H | 2368 | +| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 13th Gen Intel(R) Core(TM) i7-13800H | 1673 | +| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 13th Gen Intel(R) Core(TM) i7-13800H | 92 | +| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 13th Gen Intel(R) Core(TM) i7-13800H | 428 | \ No newline at end of file diff --git a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Python.md b/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_Python.md similarity index 80% rename from tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Python.md rename to tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_Python.md index b2a6abda..61bf76b1 100644 --- a/tests/TestingUtils/PerformanceReport/2024_3_15_PerformanceReport_Python.md +++ b/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_Python.md @@ -1,10 +1,10 @@ | Name | Description | CPU | Python Time (ms) | | --- | --- | --- | --- | -| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 13th Gen Intel(R) Core(TM) i7-13800H | 226 | -| Table_AddRows | Add 10000 rows to a table with 4 columns. | 13th Gen Intel(R) Core(TM) i7-13800H | 289 | -| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 13th Gen Intel(R) Core(TM) i7-13800H | 4813 | -| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 13th Gen Intel(R) Core(TM) i7-13800H | 6833 | -| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 13th Gen Intel(R) Core(TM) i7-13800H | 717334 | -| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 13th Gen Intel(R) Core(TM) i7-13800H | 28799 | -| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 13th Gen Intel(R) Core(TM) i7-13800H | 1249 | -| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 13th Gen Intel(R) Core(TM) i7-13800H | 9974 | \ No newline at end of file +| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 13th Gen Intel(R) Core(TM) i7-13800H | 200 | +| Table_AddRows | Add 10000 rows to a table with 4 columns. | 13th Gen Intel(R) Core(TM) i7-13800H | 322 | +| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 13th Gen Intel(R) Core(TM) i7-13800H | 4973 | +| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 13th Gen Intel(R) Core(TM) i7-13800H | 7866 | +| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 13th Gen Intel(R) Core(TM) i7-13800H | 792683 | +| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 13th Gen Intel(R) Core(TM) i7-13800H | 28535 | +| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 13th Gen Intel(R) Core(TM) i7-13800H | 1755 | +| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 13th Gen Intel(R) Core(TM) i7-13800H | 6138 | \ No newline at end of file diff --git a/tests/Speedtest/Program.fs b/tests/Speedtest/Program.fs index bbff80cc..78acca4b 100644 --- a/tests/Speedtest/Program.fs +++ b/tests/Speedtest/Program.fs @@ -29,6 +29,7 @@ let main argv = FillMissing.newF t3 FillMissing.newSeqF t4 1 + #if !FABLE_COMPILER elif Array.contains "--bigJson" argv then let createAssay() = let a = ArcAssay.init("MyAssay") @@ -66,5 +67,14 @@ let main argv = |> toJson |> toFS 1 + #endif else - 0 + printfn "ARE YOU DOING STUFF?" + //let argumentNumber = + // #if FABLE_COMPILER_JAVASCRIPT + // 1 + // #else + // 0 + // #endif + let cpu = argv.[0] + PerformanceReport.runReport cpu \ No newline at end of file diff --git a/tests/Speedtest/Speedtest.fsproj b/tests/Speedtest/Speedtest.fsproj index e81ed5a4..a9c82aef 100644 --- a/tests/Speedtest/Speedtest.fsproj +++ b/tests/Speedtest/Speedtest.fsproj @@ -10,12 +10,17 @@ + + + + + diff --git a/tests/TestingUtils/TestingUtils.fsproj b/tests/TestingUtils/TestingUtils.fsproj index 44756787..cefb049d 100644 --- a/tests/TestingUtils/TestingUtils.fsproj +++ b/tests/TestingUtils/TestingUtils.fsproj @@ -23,7 +23,6 @@ - From f05561709a0a8d1da752d54d5a997db225a3384e Mon Sep 17 00:00:00 2001 From: HLWeil Date: Mon, 18 Mar 2024 14:06:00 +0100 Subject: [PATCH 4/7] remove erroneous exe output type from testingutils --- tests/TestingUtils/TestingUtils.fsproj | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/TestingUtils/TestingUtils.fsproj b/tests/TestingUtils/TestingUtils.fsproj index cefb049d..e5ee8fb3 100644 --- a/tests/TestingUtils/TestingUtils.fsproj +++ b/tests/TestingUtils/TestingUtils.fsproj @@ -2,7 +2,6 @@ net6.0 - Exe true From 9c32a3df12f9439217090ad1568d8479ae5170d0 Mon Sep 17 00:00:00 2001 From: HLWeil Date: Mon, 18 Mar 2024 15:05:57 +0100 Subject: [PATCH 5/7] update readme with performance report and python links --- README.md | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 37adbe4d..95412a37 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,29 @@ # ARCtrl -> **ARCtrl** the easy way to read, manipulate and write ARCs in __.NET__ -and __JavaScript__! ❤️ +> **ARCtrl** the easy way to read, manipulate and write ARCs in __.NET__, __JavaScript__ and __Python__! ❤️ | Version | Downloads | | :--------|-----------:| |Nuget|Nuget| |NPM|NPM| +|PyPI|PyPI| +## Performance -## Install +Measured on 13th Gen Intel(R) Core(TM) i7-13800H + +| Name | Description | FSharp Time (ms) | JavaScript Time (ms) | Python Time (ms) | +| --- | --- | --- | --- | --- | +| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 5 | 21 | 226 | +| Table_AddRows | Add 10000 rows to a table with 4 columns. | 15 | 22 | 289 | +| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 49 | 108 | 4813 | +| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 1099 | 481 | 6833 | +| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 261 | 2266 | 717334 | +| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 915 | 2459 | 28799 | +| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 97 | 87 | 1249 | +| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 621 | 379 | 9974 | -(currently only prereleases available, check the [nuget page](https://www.nuget.org/packages/ARCtrl) or [npm page](https://www.npmjs.com/package/@nfdi4plants/arctrl) respectively) +## Install ### .NET @@ -29,6 +41,12 @@ and __JavaScript__! ❤️ npm i @nfdi4plants/arctrl ``` +### Python + +```bash +pip install python +``` + ## Docs Currently we provide some documentation in form of markdown files in the `/docs` folder of this repository! From 2c74476bad430d8e4865744b8149a707737d3c1e Mon Sep 17 00:00:00 2001 From: HLWeil Date: Mon, 18 Mar 2024 15:50:45 +0100 Subject: [PATCH 6/7] fix build chain for linux --- build/PerformanceTasks.fs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/build/PerformanceTasks.fs b/build/PerformanceTasks.fs index 49457e6f..2685ae1f 100644 --- a/build/PerformanceTasks.fs +++ b/build/PerformanceTasks.fs @@ -9,10 +9,15 @@ open Fake.Core module PerformanceReport = - let cpu = - Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM\\CentralProcessor\\0", "ProcessorNameString", null) :?> string + let mutable cpu = "" + + let promptCpu() = + if cpu = "" then + printfn "Please enter your cpu name" + cpu <- System.Console.ReadLine() let testPerformancePy = BuildTask.create "testPerformancePy" [clean; build] { + promptCpu() let path = "tests/Speedtest" //transpile py files from fsharp code run dotnet $"fable {path} -o {path}/py --lang python" "" @@ -20,6 +25,7 @@ module PerformanceReport = run python $"{path}/py/program.py \"{cpu}\"" "" } let testPerformanceJs = BuildTask.create "testPerformanceJS" [clean; build] { + promptCpu() let path = "tests/Speedtest" // transpile js files from fsharp code run dotnet $"fable {path} -o {path}/js" "" @@ -27,6 +33,7 @@ module PerformanceReport = run node $"{path}/js/program.js \"{cpu}\"" "" } let testPerformanceDotnet = BuildTask.create "testPerformanceDotnet" [clean; build] { + promptCpu() let path = "tests/Speedtest" run dotnet $"run --project {path} \"{cpu}\"" "" } From faaba01fb783797cbb459e541577cbe35636a883 Mon Sep 17 00:00:00 2001 From: HLWeil Date: Tue, 19 Mar 2024 10:00:10 +0100 Subject: [PATCH 7/7] several minor adjustments according to change request --- README.md | 44 +++++++++---------- tests/Speedtest/PerformanceReport.fs | 5 +-- ...bined.md => PerformanceReport_Combined.md} | 2 + ..._FSharp.md => PerformanceReport_FSharp.md} | 0 ...ipt.md => PerformanceReport_JavaScript.md} | 0 ..._Python.md => PerformanceReport_Python.md} | 0 tests/Speedtest/Program.fs | 1 - tests/Speedtest/Speedtest.fsproj | 5 +++ 8 files changed, 30 insertions(+), 27 deletions(-) rename tests/Speedtest/PerformanceReport/{2024_3_15_PerformanceReport_Combined.md => PerformanceReport_Combined.md} (98%) rename tests/Speedtest/PerformanceReport/{2024_3_15_PerformanceReport_FSharp.md => PerformanceReport_FSharp.md} (100%) rename tests/Speedtest/PerformanceReport/{2024_3_15_PerformanceReport_JavaScript.md => PerformanceReport_JavaScript.md} (100%) rename tests/Speedtest/PerformanceReport/{2024_3_15_PerformanceReport_Python.md => PerformanceReport_Python.md} (100%) diff --git a/README.md b/README.md index 95412a37..6e776ec0 100644 --- a/README.md +++ b/README.md @@ -6,26 +6,11 @@ | :--------|-----------:| |Nuget|Nuget| |NPM|NPM| -|PyPI|PyPI| - -## Performance - -Measured on 13th Gen Intel(R) Core(TM) i7-13800H - -| Name | Description | FSharp Time (ms) | JavaScript Time (ms) | Python Time (ms) | -| --- | --- | --- | --- | --- | -| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 5 | 21 | 226 | -| Table_AddRows | Add 10000 rows to a table with 4 columns. | 15 | 22 | 289 | -| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 49 | 108 | 4813 | -| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 1099 | 481 | 6833 | -| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 261 | 2266 | 717334 | -| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 915 | 2459 | 28799 | -| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 97 | 87 | 1249 | -| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 621 | 379 | 9974 | +|PyPI|PyPI| ## Install -### .NET +#### .NET ```fsharp #r "nuget: ARCtrl" @@ -35,16 +20,16 @@ Measured on 13th Gen Intel(R) Core(TM) i7-13800H ``` -### JavaScript +#### JavaScript ```bash npm i @nfdi4plants/arctrl ``` -### Python +#### Python ```bash -pip install python +pip install arctrl ``` ## Docs @@ -55,7 +40,7 @@ Currently we provide some documentation in form of markdown files in the `/docs` ## Development -### Requirements +#### Requirements - [nodejs and npm](https://nodejs.org/en/download) - verify with `node --version` (Tested with v18.16.1) @@ -65,7 +50,7 @@ Currently we provide some documentation in form of markdown files in the `/docs` - [Python](https://www.python.org/downloads/) - verify with `py --version` (Tested with 3.12.2, known to work only for >=3.11) -### Local Setup +#### Local Setup 1. Setup dotnet tools @@ -86,3 +71,18 @@ Currently we provide some documentation in form of markdown files in the `/docs` 3. `.\.venv\Scripts\python.exe -m poetry install --no-root` Verify correct setup with `./build.cmd runtests` ✨ + +## Performance + +Measured on 13th Gen Intel(R) Core(TM) i7-13800H + +| Name | Description | FSharp Time (ms) | JavaScript Time (ms) | Python Time (ms) | +| --- | --- | --- | --- | --- | +| Table_GetHashCode | From a table with 1 column and 10000 rows, retrieve the Hash Code | 5 | 21 | 226 | +| Table_AddRows | Add 10000 rows to a table with 4 columns. | 15 | 22 | 289 | +| Table_fillMissingCells | For a table 6 columns and 20000 rows, where each row has one missing value, fill those values with default values. | 49 | 108 | 4813 | +| Table_ToJson | Serialize a table with 5 columns and 10000 rows to json. | 1099 | 481 | 6833 | +| Table_ToCompressedJson | Serialize a table with 5 columns and 10000 rows to compressed json. | 261 | 2266 | 717334 | +| Assay_toJson | Parse an assay with one table with 10000 rows and 6 columns to json | 915 | 2459 | 28799 | +| Study_FromWorkbook | Parse a workbook with one study with 10000 rows and 6 columns to an ArcStudy | 97 | 87 | 1249 | +| Investigation_ToWorkbook_ManyStudies | Parse an investigation with 1500 studies to a workbook | 621 | 379 | 9974 | diff --git a/tests/Speedtest/PerformanceReport.fs b/tests/Speedtest/PerformanceReport.fs index a4e05985..cf71e576 100644 --- a/tests/Speedtest/PerformanceReport.fs +++ b/tests/Speedtest/PerformanceReport.fs @@ -217,10 +217,7 @@ let lang = let runReport cpu = let report = createMarkdownPerformanceReport lang cpu - let timeString = - let dt = System.DateTime.Today - $"{dt.Year}_{dt.Month}_{dt.Day}" - let outFile = $"tests/Speedtest/PerformanceReport/{timeString}_PerformanceReport_{lang}.md" + let outFile = $"tests/Speedtest/PerformanceReport/PerformanceReport_{lang}.md" writeFile outFile report printfn "%s" report 0 diff --git a/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_Combined.md b/tests/Speedtest/PerformanceReport/PerformanceReport_Combined.md similarity index 98% rename from tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_Combined.md rename to tests/Speedtest/PerformanceReport/PerformanceReport_Combined.md index 8e1daab1..1b9a6684 100644 --- a/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_Combined.md +++ b/tests/Speedtest/PerformanceReport/PerformanceReport_Combined.md @@ -1,3 +1,5 @@ +## 2024_15_03 + Measured on 13th Gen Intel(R) Core(TM) i7-13800H | Name | Description | FSharp Time (ms) | JavaScript Time (ms) | Python Time (ms) | diff --git a/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md b/tests/Speedtest/PerformanceReport/PerformanceReport_FSharp.md similarity index 100% rename from tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_FSharp.md rename to tests/Speedtest/PerformanceReport/PerformanceReport_FSharp.md diff --git a/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md b/tests/Speedtest/PerformanceReport/PerformanceReport_JavaScript.md similarity index 100% rename from tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_JavaScript.md rename to tests/Speedtest/PerformanceReport/PerformanceReport_JavaScript.md diff --git a/tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_Python.md b/tests/Speedtest/PerformanceReport/PerformanceReport_Python.md similarity index 100% rename from tests/Speedtest/PerformanceReport/2024_3_15_PerformanceReport_Python.md rename to tests/Speedtest/PerformanceReport/PerformanceReport_Python.md diff --git a/tests/Speedtest/Program.fs b/tests/Speedtest/Program.fs index 78acca4b..0d55aec0 100644 --- a/tests/Speedtest/Program.fs +++ b/tests/Speedtest/Program.fs @@ -69,7 +69,6 @@ let main argv = 1 #endif else - printfn "ARE YOU DOING STUFF?" //let argumentNumber = // #if FABLE_COMPILER_JAVASCRIPT // 1 diff --git a/tests/Speedtest/Speedtest.fsproj b/tests/Speedtest/Speedtest.fsproj index a9c82aef..16d21c1a 100644 --- a/tests/Speedtest/Speedtest.fsproj +++ b/tests/Speedtest/Speedtest.fsproj @@ -6,6 +6,9 @@ + + + @@ -14,6 +17,8 @@ + +