Open
Description
Prerequisites
- I have written a descriptive issue title
- I have verified that I am running the latest version of Fonts
- I have verified if the problem exist in both
DEBUG
andRELEASE
mode - I have searched open and closed issues to ensure it has not already been reported
Description
I tried to use SixLabors.Fonts to compute widths of many different texts to produce a nice looking Excel file with Simplexcel. It turned out to be an unusable solution because it was too slow. I tracked the slowness down to the SixLabors.Fonts.TextMeasurer.Measure
function.
I ran some benchmarks, comparing SixLabors.Fonts
to SkiaSharp
and here are the results.
BenchmarkDotNet=v0.13.1, OS=macOS Catalina 10.15.7 (19H1615) [Darwin 19.6.0]
Intel Core i9-9980HK CPU 2.40GHz, 1 CPU, 16 logical and 8 physical cores
.NET SDK=6.0.300
[Host] : .NET 6.0.5 (6.0.522.21309), X64 RyuJIT
MediumRun : .NET 6.0.5 (6.0.522.21309), X64 RyuJIT
Job=MediumRun IterationCount=15 LaunchCount=2
WarmupCount=10
Method | Text | Mean | Error | StdDev |
---|---|---|---|---|
SixLaborsFonts | Hello world | 31,270.4 ns | 621.99 ns | 871.94 ns |
SkiaSharp | Hello world | 539.0 ns | 8.13 ns | 11.92 ns |
SixLaborsFonts | The q(...)y dog [43] | 110,846.6 ns | 4,511.26 ns | 6,752.24 ns |
SkiaSharp | The q(...)y dog [43] | 1,421.4 ns | 38.72 ns | 55.54 ns |
SixLaborsFonts | a | 7,025.6 ns | 349.17 ns | 511.81 ns |
SkiaSharp | a | 353.3 ns | 11.29 ns | 16.90 ns |
I eventually used SkiaSharp instead of SixLabors.Fonts and did not investigate further why measuring text is slow.
The benchmark below could help as a starting point, should someone tackle this issue (myself included if I ever find the time).
Steps to Reproduce
Run the following project with dotnet run -c Release
MeasureTextBenchmarks.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta17" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.88.0" />
</ItemGroup>
</Project>
Program.cs
using System;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using SixLabors.Fonts;
using SkiaSharp;
BenchmarkRunner.Run<MeasureTextBenchmark>();
[MediumRunJob]
public class MeasureTextBenchmark : IDisposable
{
private readonly TextOptions _textOptions;
private readonly SKTypeface _arialTypeface;
private readonly SKFont _font;
private readonly SKPaint _paint;
public MeasureTextBenchmark()
{
const string fontFamilyName = "Arial";
const int fontSize = 16;
_textOptions = new TextOptions(SystemFonts.Get(fontFamilyName).CreateFont(fontSize, FontStyle.Regular));
_arialTypeface = SKTypeface.FromFamilyName(fontFamilyName, SKFontStyle.Normal);
_font = new SKFont(_arialTypeface, fontSize);
_paint = new SKPaint(_font);
}
public void Dispose()
{
_arialTypeface.Dispose();
_font.Dispose();
_paint.Dispose();
}
[Params("a", "Hello world", "The quick brown fox jumps over the lazy dog")]
public string Text { get; set; } = "";
[Benchmark]
public void SixLaborsFonts() => TextMeasurer.Measure(Text, _textOptions);
[Benchmark]
public void SkiaSharp() => _paint.MeasureText(Text);
}
System Configuration
- Fonts version: 1.0.0-beta17
- Other Six Labors packages and versions: none
- Environment (Operating system, version and so on): macOS 10.15.7
- .NET Framework version: .NET 6.0.5
- Additional information: N/A