Skip to content

Commit

Permalink
Merge pull request #325 from nfdi4plants/performanceReport
Browse files Browse the repository at this point in the history
Performance report
  • Loading branch information
HLWeil authored Mar 19, 2024
2 parents d64e708 + faaba01 commit 0fb24ee
Show file tree
Hide file tree
Showing 20 changed files with 382 additions and 182 deletions.
36 changes: 27 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
# 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 |
| :--------|-----------:|
|<a href="https://www.nuget.org/packages/ARCtrl/"><img alt="Nuget" src="https://img.shields.io/nuget/vpre/ARCtrl?logo=nuget&color=%234fb3d9"></a>|<a href="https://www.nuget.org/packages/ARCtrl/"><img alt="Nuget" src="https://img.shields.io/nuget/dt/ARCtrl?color=%234FB3D9"></a>|
|<a href="https://www.npmjs.com/package/@nfdi4plants/arctrl"><img alt="NPM" src="https://img.shields.io/npm/v/%40nfdi4plants/arctrl?logo=npm&color=%234fb3d9"></a>|<a href="https://www.npmjs.com/package/@nfdi4plants/arctrl"><img alt="NPM" src="https://img.shields.io/npm/dt/%40nfdi4plants%2Farctrl?color=%234fb3d9"></a>|

|<a href="https://pypi.org/project/ARCtrl/"><img alt="PyPI" src="https://img.shields.io/pypi/v/arctrl?logo=pypi&color=%234fb3d9"></a>|<a href="https://pypi.org/project/ARCtrl/"><img alt="PyPI" src="https://img.shields.io/pepy/dt/arctrl?color=%234fb3d9"></a>|

## Install

(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)

### .NET
#### .NET

```fsharp
#r "nuget: ARCtrl"
Expand All @@ -23,12 +20,18 @@ and __JavaScript__! ❤️
<PackageReference Include="ARCtrl" Version="1.1.0" />
```

### JavaScript
#### JavaScript

```bash
npm i @nfdi4plants/arctrl
```

#### Python

```bash
pip install arctrl
```

## Docs

Currently we provide some documentation in form of markdown files in the `/docs` folder of this repository!
Expand All @@ -37,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)
Expand All @@ -47,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

Expand All @@ -68,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 |
11 changes: 11 additions & 0 deletions build/BasicTasks.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions build/Build.fs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ let _preRelease =
[setPrereleaseTag; clean; build; runTests; packPrerelease; createPrereleaseTag; publishNugetPrerelease; publishNPMPrerelease]

ReleaseNotesTasks.updateReleaseNotes |> ignore
PerformanceTasks.perforanceReport |> ignore

[<EntryPoint>]
let main args =
Expand Down
1 change: 1 addition & 0 deletions build/Build.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<Compile Include="BasicTasks.fs" />
<Compile Include="GenerateIndexJs.fs" />
<Compile Include="GenerateIndexPy.fs" />
<Compile Include="PerformanceTasks.fs" />
<Compile Include="TestTasks.fs" />
<Compile Include="PackageTasks.fs" />
<Compile Include="ReleaseTasks.fs" />
Expand Down
43 changes: 43 additions & 0 deletions build/PerformanceTasks.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module PerformanceTasks

open BlackFox.Fake
open Fake.DotNet

open ProjectInfo
open BasicTasks
open Fake.Core

module PerformanceReport =

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" ""
// run pyxpecto in target path to execute tests in python
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" ""
// run mocha in target path to execute tests
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}\"" ""
}

let perforanceReport = BuildTask.create "PerformanceReport" [PerformanceReport.testPerformancePy; PerformanceReport.testPerformanceJs; PerformanceReport.testPerformanceDotnet] {
()
}
2 changes: 1 addition & 1 deletion docs/scripts_fsharp/ArcInvestigation.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
48 changes: 0 additions & 48 deletions tests/ISA/ISA.Json.Tests/ArcTypes.Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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" [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
<Compile Include="StudyFileTests.fs" />
<Compile Include="AssayFileTests.fs" />
<Compile Include="InvestigationFileTests.fs" />
<Compile Include="Performance.Tests.fs" />
<Compile Include="Main.fs" />
</ItemGroup>
<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion tests/ISA/ISA.Spreadsheet.Tests/Main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ let all = testSequenced <| testList "ISA.Spreadsheet" [
ArcStudyTests.main
SparseTableTests.main
IdentifierTests.main
Tests.Performance.Main
]

[<EntryPoint>]
Expand Down
45 changes: 0 additions & 45 deletions tests/ISA/ISA.Spreadsheet.Tests/Performance.Tests.fs

This file was deleted.

Loading

0 comments on commit 0fb24ee

Please sign in to comment.