Skip to content

Releases: AndreCL/Oxyplot.DotNetAndroid

v.1.0.8

07 May 12:30

Choose a tag to compare

Major Optimizations

Benchmark Results: OxyPlot.DotNetAndroid

All benchmarks run on the host CLR (.NET 8, Windows) using BenchmarkDotNet 0.14.0 with [MemoryDiagnoser].
Android JNI overhead cannot be measured off-device. Relative improvements are valid; absolute numbers will differ on ART.


FontMetricsBenchmark

Measures the cost of allocating a new FontMetrics-equivalent object per call (baseline, mirrors Paint.GetFontMetrics() no-arg overload) vs. filling a cached instance in-place (mirrors Paint.GetFontMetrics(Paint.FontMetrics) overload).

Method Mean Error StdDev Ratio Gen0 Allocated Alloc Ratio
GetFontMetrics_Allocating (baseline) 2.944 ns 0.100 ns 0.200 ns 1.00 0.0048 40 B 1.00
GetFontMetrics_Cached (Fix 1) 0.467 ns 0.048 ns 0.045 ns 0.16 0 B 0.00

Key finding: Caching the FontMetrics instance eliminates 40 bytes of allocation per call (100% reduction) and reduces call cost by 6.3×. At 10 views × 60 FPS with text on every frame, this removes ~24,000 allocations/second.


PathBuildBenchmark

Measures the cost of resetting and re-populating a path-like list structure (proxy for Android.Graphics.Path.Reset() + LineTo).

Method PointCount Mean Ratio Gen0 Allocated
BuildPath_ReuseList (Fix 2 pattern) 100 127.1 ns 1.00 0 B
BuildPath_NewList (naive) 100 130.2 ns 1.03 0.1023 856 B
BuildPath_ReuseList 500 583.5 ns 1.00 0 B
BuildPath_NewList 500 681.5 ns 1.17 0.4845 4,056 B
BuildPath_ReuseList 1000 1,163.6 ns 1.00 0 B
BuildPath_NewList 1000 1,310.3 ns 1.13 0.9680 8,104 B

Key finding: Reusing a single path instance eliminates all managed allocations and is 3–17% faster depending on point count. For 500-point series (the stress test scenario), reuse saves 4 KB per draw call.


RenderContextBenchmark

Drives a no-op MockRenderContext through a simulated OnDraw cycle: axis rectangles + 500-point line series + 18 axis labels.

Method Mean Error StdDev Gen0 Allocated
SimulatedFrame 446.6 ns 10.48 ns 30.40 ns 0.0715 600 B

Key finding: A complete simulated frame (no Android JNI) allocates only 600 bytes at the OxyPlot+render-context layer. This is well within the target of <4 KB/frame. The remaining allocation is from OxyPlot's internal axis/series rendering pipeline.


PlotModelUpdateBenchmark

Calls IPlotModel.Update() on a PlotModel with one LineSeries of 500 points.

Method Mean Error StdDev Gen0 Allocated
Update_WithData 2,482.5 ns 45.63 ns 42.68 ns 0.1793 1.48 KB
Update_WithoutData 573.1 ns 9.95 ns 12.58 ns 0.1640 1.34 KB

Key finding: The OxyPlot model update itself allocates ~1.3–1.5 KB per call regardless of updateData. This is OxyPlot library-internal overhead. The updateData: false path (used in the hot OnDraw loop after the first frame) is 4.3× faster.


Phase 3 Stress Test Results

Test: StressTest_10Views_60Hz_5Minutes — 10 models × 60 Hz × 300 seconds = 18,000,000 simulated renders via MockRenderContext.

Baseline (before fixes)

Metric Value
Elapsed ~3.71 s (simulated time)
Avg frame time 0.206 ms
Gen-0 GCs 272
Gen-1 GCs 1
Gen-2 GCs 0
Heap growth 5,480 KB

After fixes (Fix 1–5 applied)

Metric Value vs Baseline
Elapsed ~3.64 s −1.8%
Avg frame time 0.202 ms −1.9%
Gen-0 GCs 273 +0.4% (within noise)
Gen-1 GCs 1 same
Gen-2 GCs 0 same
Heap growth 5,576 KB +1.7% (within noise)
Test result ✅ PASSED

Note: The stress test uses MockRenderContext (no-op), so Android JNI costs (including Paint.GetFontMetrics() JNI allocation) are not exercised. The GC numbers in the stress test reflect OxyPlot's own internal allocations only. The FontMetrics fix benefit will be visible on device as eliminated JNI-backed object allocations, not in this host-CLR benchmark.


Before / After Summary Table

Benchmark / Metric Before After Improvement
GetFontMetrics allocated bytes/call 40 B 0 B 100% reduction
GetFontMetrics mean call time 2.94 ns 0.47 ns 6.3× faster
BuildPath allocated bytes/op (500 pts) 4,056 B 0 B 100% reduction
SimulatedFrame allocated bytes/frame 600 B 600 B (no-op RC — host baseline)
Stress test gen-0 GCs / 5 min 272 273 within noise
Stress test gen-2 GCs / 5 min 0 0
Stress test heap growth 5,480 KB 5,576 KB within noise
Build passes
New compiler warnings 0 0

Acceptance Criteria Status

Criterion Target Result
Allocated bytes per DrawText call (host proxy) 0 B after fix ✅ 0 B
Allocated bytes per simulated frame < 4 KB ✅ 600 B
GC gen-0 count / 5-min stress run < 600 ✅ 273
GC gen-2 count / 5-min stress run < 10 ✅ 0
Managed heap growth over 5-min run < 10 MB ✅ ~5.5 MB
Build passes after each fix
No new compiler warnings

v.1.0.7

29 Apr 09:34

Choose a tag to compare

Nuget upgrade

v.1.0.6

29 Apr 07:51

Choose a tag to compare

Removed old target frameworks

v.1.0.5

28 Apr 13:36

Choose a tag to compare

Temporary fix for issue with Oxyplot.SkiaSharp

v.1.0.4

31 Mar 08:53

Choose a tag to compare

GC Optimizations

v.1.0.3

17 Mar 11:20

Choose a tag to compare

Fixing the layout to fit more with compatibility with Oxyplot Xamarin Android

v.1.0.2

12 Mar 12:01

Choose a tag to compare

First official release

v.1.0.1

12 Mar 09:59

Choose a tag to compare

Test working nuget versioning in action

v.0.0.2

11 Mar 13:45

Choose a tag to compare

Alpha test

v.0.0.1

11 Mar 13:40

Choose a tag to compare

Alpha test