Skip to content

Commit 03bcbc7

Browse files
committed
- BenchmarkDotNet 0.10.12 -> 0.12.1
- leave support for long Stream indexes in RandomAccessStream (and take the mild read hit) - add RASBenchmark class
1 parent f95f556 commit 03bcbc7

File tree

5 files changed

+247
-13
lines changed

5 files changed

+247
-13
lines changed

MetadataExtractor.Benchmarks/MetadataExtractor.Benchmarks.csproj

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
</ItemGroup>
1111

1212
<ItemGroup>
13-
<PackageReference Include="BenchmarkDotNet" Version="0.10.12" />
14-
<PackageReference Include="BenchmarkDotNet.Core" Version="0.10.12" />
13+
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
1514
</ItemGroup>
1615

1716
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright (c) Drew Noakes and contributors. All Rights Reserved. Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
2+
3+
using System;
4+
using System.IO;
5+
6+
namespace MetadataExtractor.Benchmarks
7+
{
8+
internal class NonSeekableStream : Stream
9+
{
10+
Stream m_stream;
11+
internal NonSeekableStream(Stream baseStream)
12+
{
13+
m_stream = baseStream;
14+
}
15+
16+
public override bool CanRead => m_stream.CanRead;
17+
18+
public override bool CanSeek => false;
19+
20+
public override bool CanWrite => m_stream.CanWrite;
21+
22+
public override long Length => throw new NotSupportedException();
23+
24+
public override long Position { get => m_stream.Position; set => throw new NotSupportedException(); }
25+
26+
public override void Flush()
27+
{
28+
m_stream.Flush();
29+
}
30+
31+
public override int Read(byte[] buffer, int offset, int count)
32+
{
33+
return m_stream.Read(buffer, offset, count);
34+
}
35+
36+
public override long Seek(long offset, SeekOrigin origin)
37+
{
38+
throw new NotImplementedException();
39+
}
40+
41+
public override void SetLength(long value)
42+
{
43+
throw new NotSupportedException();
44+
}
45+
46+
public override void Write(byte[] buffer, int offset, int count)
47+
{
48+
m_stream.Write(buffer, offset, count);
49+
}
50+
}
51+
}

MetadataExtractor.Benchmarks/Program.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ namespace MetadataExtractor.Benchmarks
1717
{
1818
internal static class Program
1919
{
20-
private static void Main() => BenchmarkRunner.Run<JpegBenchmark>();
20+
//private static void Main() => BenchmarkRunner.Run<JpegBenchmark>();
21+
private static void Main() => BenchmarkRunner.Run<RASBenchmark>();
2122
}
2223

2324
/*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
using System;
2+
using System.IO;
3+
4+
using BenchmarkDotNet.Attributes;
5+
6+
using MetadataExtractor.IO;
7+
8+
namespace MetadataExtractor.Benchmarks
9+
{
10+
[MemoryDiagnoser]
11+
public class RASBenchmark
12+
{
13+
private readonly MemoryStream _stream;
14+
15+
private readonly ReaderInfo _reader;
16+
public RASBenchmark()
17+
{
18+
_stream = new MemoryStream();
19+
20+
// This is the largest JPEG file in this repository
21+
using var fs = File.OpenRead("../../../../MetadataExtractor.Tests/Data/nikonMakernoteType2b.jpg");
22+
fs.CopyTo(_stream);
23+
24+
_reader = new RandomAccessStream(_stream).CreateReader();
25+
}
26+
27+
[Benchmark(Baseline = true)]
28+
public void RASListBenchmark()
29+
{
30+
_stream.Position = 0;
31+
32+
//var reader = new RandomAccessStream(_stream).CreateReader();
33+
RunReader(_reader);
34+
}
35+
36+
37+
/*
38+
[Benchmark]]
39+
public void RASDictionaryBenchmark()
40+
{
41+
_stream.Position = 0;
42+
43+
var reader = new RandomAccessStreamDictionary(_stream).CreateReader();
44+
RunReader(reader);
45+
}
46+
47+
[Benchmark]
48+
public void RASDictionaryNonseekableBenchmark()
49+
{
50+
_stream.Position = 0;
51+
52+
var reader = new RandomAccessStreamDictionary(new NonSeekableStream(_stream)).CreateReader();
53+
RunReader(reader);
54+
}
55+
56+
[Benchmark]
57+
public void RASListNonseekableBenchmark()
58+
{
59+
_stream.Position = 0;
60+
61+
var reader = new RandomAccessStream(new NonSeekableStream(_stream)).CreateReader();
62+
RunReader(reader);
63+
}
64+
*/
65+
66+
67+
[Benchmark]
68+
public void IndexedCapturingReaderBenchmark()
69+
{
70+
_stream.Position = 0;
71+
72+
var reader = new IndexedCapturingReader(_stream, 4096);
73+
RunIndexedReader(reader);
74+
}
75+
76+
[Benchmark]
77+
public void IndexedSeekingReaderBenchmark()
78+
{
79+
_stream.Position = 0;
80+
81+
var reader = new IndexedSeekingReader(_stream);
82+
RunIndexedReader(reader);
83+
}
84+
85+
private void RunReader(ReaderInfo reader)
86+
{
87+
int offset = 4 * 1024 + 10; // skip over at least one buffer, just because
88+
89+
// Nothing mathematical intended here other than jumping around in the file
90+
for (int i = 0; i < 10; i++)
91+
{
92+
var calcoffset2 = GetLongOffset(i, offset, 2);
93+
var calcoffset3 = GetLongOffset(i, offset, 3);
94+
95+
96+
reader.GetInt16(calcoffset2);
97+
reader.GetInt16(calcoffset3);
98+
99+
reader.GetInt24(calcoffset2);
100+
reader.GetInt24(calcoffset3);
101+
102+
reader.GetInt32(calcoffset2);
103+
reader.GetInt32(calcoffset3);
104+
105+
reader.GetBytes(calcoffset2, 128);
106+
reader.GetBytes(calcoffset3, 128);
107+
108+
reader.GetInt64(calcoffset2);
109+
reader.GetInt64(calcoffset3);
110+
111+
for (int j = 0; j < 1000; j++)
112+
{
113+
reader.GetByte(calcoffset2 + j);
114+
reader.GetByte(calcoffset3 + j);
115+
}
116+
117+
reader.GetUInt16(calcoffset2);
118+
reader.GetUInt16(calcoffset3);
119+
120+
reader.GetUInt32(calcoffset2);
121+
reader.GetUInt32(calcoffset3);
122+
123+
124+
//reader.GetUInt64(calcoffset2);
125+
//reader.GetUInt64(calcoffset3);
126+
}
127+
}
128+
129+
private void RunIndexedReader(IndexedReader reader)
130+
{
131+
int offset = 4 * 1024 + 10; // skip over at least one buffer, just because
132+
133+
// Nothing mathematical intended here other than jumping around in the file
134+
for (int i = 0; i < 10; i++)
135+
{
136+
var calcoffset2 = GetIntOffset(i, offset, 2);
137+
var calcoffset3 = GetIntOffset(i, offset, 3);
138+
139+
140+
reader.GetInt16(calcoffset2);
141+
reader.GetInt16(calcoffset3);
142+
143+
reader.GetInt24(calcoffset2);
144+
reader.GetInt24(calcoffset3);
145+
146+
reader.GetInt32(calcoffset2);
147+
reader.GetInt32(calcoffset3);
148+
149+
reader.GetBytes(calcoffset2, 128);
150+
reader.GetBytes(calcoffset3, 128);
151+
152+
reader.GetInt64(calcoffset2);
153+
reader.GetInt64(calcoffset3);
154+
155+
for (int j = 0; j < 1000; j++)
156+
{
157+
reader.GetByte(calcoffset2 + j);
158+
reader.GetByte(calcoffset3 + j);
159+
}
160+
161+
reader.GetUInt16(calcoffset2);
162+
reader.GetUInt16(calcoffset3);
163+
164+
reader.GetUInt32(calcoffset2);
165+
reader.GetUInt32(calcoffset3);
166+
167+
168+
//reader.GetUInt64(calcoffset2);
169+
//reader.GetUInt64(calcoffset3);
170+
}
171+
}
172+
173+
private static long GetLongOffset(int i, long offset, int power)
174+
{
175+
return (long)(i * offset + Math.Pow(power, i));
176+
}
177+
178+
private static int GetIntOffset(int i, long offset, int power)
179+
{
180+
return (int)(i * offset + Math.Pow(power, i));
181+
}
182+
}
183+
}

MetadataExtractor/IO/RandomAccessStream.cs

+10-10
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,13 @@ private byte GetByteNoValidation(long index)
175175
return p_chunks[0][index];
176176

177177
// micro-optimization for benchmarks
178-
var intIndex = (int)index;
178+
//var intIndex = (int)index;
179179

180-
var chunkIndex = intIndex / p_chunkLength;
181-
var innerIndex = intIndex % p_chunkLength;
180+
//var chunkIndex = intIndex / p_chunkLength;
181+
//var innerIndex = intIndex % p_chunkLength;
182182

183-
//var chunkIndex = (int)(index / p_chunkLength);
184-
//var innerIndex = (int)(index % p_chunkLength);
183+
var chunkIndex = (int)(index / p_chunkLength);
184+
var innerIndex = (int)(index % p_chunkLength);
185185

186186
if (p_chunks.Count - 1 >= chunkIndex)
187187
return p_chunks[chunkIndex][innerIndex];
@@ -474,13 +474,13 @@ private int BytesAvailable(long index, int bytesRequested)
474474
return 0;
475475

476476
// micro-optimization for benchmarks
477-
var intIndex = (int)index;
477+
//var intIndex = (int)index;
478478

479479
// zero-based
480-
int chunkstart = intIndex / p_chunkLength;
481-
int chunkend = ((intIndex + bytesRequested) / p_chunkLength) + 1;
482-
//int chunkstart = (int)(index / p_chunkLength);
483-
//int chunkend = chunkstart + (bytesRequested / p_chunkLength) + 1;
480+
//int chunkstart = intIndex / p_chunkLength;
481+
//int chunkend = ((intIndex + bytesRequested) / p_chunkLength) + 1;
482+
int chunkstart = (int)(index / p_chunkLength);
483+
int chunkend = chunkstart + (bytesRequested / p_chunkLength) + 1;
484484

485485
if (p_chunks.Count - 1 < chunkstart || p_chunks[chunkstart] == null)
486486
{

0 commit comments

Comments
 (0)