diff --git a/.gitignore b/.gitignore index c20b14d2..a02a88d7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ ################################################################################ obj/ /.vs/OpenMcdf/v14 -/bin/Debug +bin/ /TestResults /sources/Test/OpenMcdf.Test/bin/Debug /sources/Test/OpenMcdf.PerfTest/obj/Debug @@ -27,7 +27,7 @@ obj/ /Memory Test/bin/Debug /bin/Release/StructuredStorageXplorer /bin/Release/OpenMcdf.Extensions -/bin/Release +/bin/Release/ /sources/Html Help/Help /.vs # User-specific files diff --git a/OpenMcdf.sln b/OpenMcdf.sln index 12e58e8b..ab4ab2ab 100644 --- a/OpenMcdf.sln +++ b/OpenMcdf.sln @@ -52,6 +52,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenMcdf.PerfTest", "source EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenMcdf.Test", "sources\Test\OpenMcdf.Test\OpenMcdf.Test.csproj", "{FD339266-8842-40B4-9230-F8E84FC42AC2}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenMcdf.Benchmark", "sources\Test\OpenMcdf.Benchmark\OpenMcdf.Benchmark.csproj", "{B3645D34-1E22-4BCC-8956-A8A56FA9F114}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -86,6 +88,10 @@ Global {FD339266-8842-40B4-9230-F8E84FC42AC2}.Debug|Any CPU.Build.0 = Debug|Any CPU {FD339266-8842-40B4-9230-F8E84FC42AC2}.Release|Any CPU.ActiveCfg = Release|Any CPU {FD339266-8842-40B4-9230-F8E84FC42AC2}.Release|Any CPU.Build.0 = Release|Any CPU + {B3645D34-1E22-4BCC-8956-A8A56FA9F114}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B3645D34-1E22-4BCC-8956-A8A56FA9F114}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B3645D34-1E22-4BCC-8956-A8A56FA9F114}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B3645D34-1E22-4BCC-8956-A8A56FA9F114}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -96,6 +102,7 @@ Global {E2BAD82D-3040-462B-BAA2-6E608A9054F4} = {73814657-FC73-4066-AABD-86062F2A132E} {7077508F-B313-4DF6-8855-4764911BE161} = {73814657-FC73-4066-AABD-86062F2A132E} {FD339266-8842-40B4-9230-F8E84FC42AC2} = {73814657-FC73-4066-AABD-86062F2A132E} + {B3645D34-1E22-4BCC-8956-A8A56FA9F114} = {73814657-FC73-4066-AABD-86062F2A132E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DEAA45F3-54F5-4F50-8402-9D89EB95A04C} diff --git a/OpenMcdf.sln.DotSettings b/OpenMcdf.sln.DotSettings new file mode 100644 index 00000000..43677b3c --- /dev/null +++ b/OpenMcdf.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/sources/Test/OpenMcdf.Benchmark/InMemory.cs b/sources/Test/OpenMcdf.Benchmark/InMemory.cs new file mode 100644 index 00000000..128b5ac0 --- /dev/null +++ b/sources/Test/OpenMcdf.Benchmark/InMemory.cs @@ -0,0 +1,100 @@ +using System; +using System.IO; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Order; + +namespace OpenMcdf.Benchmark +{ + [CoreJob] + [CsvExporter] + [HtmlExporter] + [MarkdownExporter] + //[DryCoreJob] // I always forget this attribute, so please leave it commented out + [MemoryDiagnoser] + [Orderer(SummaryOrderPolicy.FastestToSlowest)] + public class InMemory : IDisposable + { + private const int Kb = 1024; + private const int Mb = Kb * Kb; + private const string storageName = "MyStorage"; + private const string streamName = "MyStream"; + + private byte[] _readBuffer; + + private Stream _stream; + + [Params(Kb / 2, Kb, 4 * Kb, 128 * Kb, 256 * Kb, 512 * Kb, Kb * Kb)] + public int BufferSize { get; set; } + + [Params(Mb /*, 8 * Mb, 64 * Mb, 128 * Mb*/)] + public int TotalStreamSize { get; set; } + + public void Dispose() + { + _stream?.Dispose(); + } + + [GlobalSetup] + public void GlobalSetup() + { + _stream = new MemoryStream(); + _readBuffer = new byte[BufferSize]; + CreateFile(1); + } + + [GlobalCleanup] + public void GlobalCleanup() + { + _stream.Dispose(); + _stream = null; + _readBuffer = null; + } + + + [Benchmark] + public void Test() + { + // + _stream.Seek(0L, SeekOrigin.Begin); + // + var compoundFile = new CompoundFile(_stream); + var cfStream = compoundFile.RootStorage + .GetStorage(storageName) + .GetStream(streamName + 0); + var streamSize = cfStream.Size; + var position = 0L; + while (true) + { + if (position >= streamSize) break; + var read = cfStream + .Read(_readBuffer, position, _readBuffer.Length); + position += read; + if (read <= 0) break; + } + + //compoundFile.Close(); + } + + private void CreateFile(int streamCount) + { + var iterationCount = TotalStreamSize / BufferSize; + + var buffer = new byte[BufferSize]; + Array.Fill(buffer, byte.MaxValue); + const CFSConfiguration flags = CFSConfiguration.Default | CFSConfiguration.LeaveOpen; + using (var compoundFile = new CompoundFile(CFSVersion.Ver_4, flags)) + { + var st = compoundFile.RootStorage.AddStorage(storageName); + for (var streamId = 0; streamId < streamCount; ++streamId) + { + var sm = st.AddStream(streamName + streamId); + + for (var iteration = 0; iteration < iterationCount; ++iteration) sm.Append(buffer); + } + + compoundFile.Save(_stream); + compoundFile.Close(); + } + } + } +} \ No newline at end of file diff --git a/sources/Test/OpenMcdf.Benchmark/OpenMcdf.Benchmark.csproj b/sources/Test/OpenMcdf.Benchmark/OpenMcdf.Benchmark.csproj new file mode 100644 index 00000000..2f8767e7 --- /dev/null +++ b/sources/Test/OpenMcdf.Benchmark/OpenMcdf.Benchmark.csproj @@ -0,0 +1,16 @@ + + + + Exe + netcoreapp2.2 + + + + + + + + + + + diff --git a/sources/Test/OpenMcdf.Benchmark/Program.cs b/sources/Test/OpenMcdf.Benchmark/Program.cs new file mode 100644 index 00000000..f441ba1d --- /dev/null +++ b/sources/Test/OpenMcdf.Benchmark/Program.cs @@ -0,0 +1,12 @@ +using BenchmarkDotNet.Running; + +namespace OpenMcdf.Benchmark +{ + internal class Program + { + private static void Main(string[] args) + { + var summary = BenchmarkRunner.Run(); + } + } +} \ No newline at end of file