Skip to content

Commit

Permalink
Benchmarking: Makes benchmarking suites easier to use.
Browse files Browse the repository at this point in the history
  • Loading branch information
tgockel committed Dec 13, 2016
1 parent 8f0bd05 commit 9933679
Show file tree
Hide file tree
Showing 9 changed files with 319 additions and 35 deletions.
8 changes: 7 additions & 1 deletion msvc/vs2015/jsonv-tests/jsonv-tests.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
<ClCompile Include="..\..\..\src\jsonv-tests\algorithm_compare_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\algorithm_map_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\array_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\benchmark_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\char_convert_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\chrono_io.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\coerce_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\demangle_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\detail\token_patterns_tests.cpp" />
Expand All @@ -37,6 +39,7 @@
<ClCompile Include="..\..\..\src\jsonv-tests\path_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\serialization_builder_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\serialization_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\stopwatch.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\string_tests.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\test.cpp" />
<ClCompile Include="..\..\..\src\jsonv-tests\tokenizer_tests.cpp" />
Expand All @@ -47,10 +50,13 @@
<ClCompile Include="..\..\..\src\jsonv-tests\value_tests.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\jsonv-tests\chrono_io.hpp" />
<ClInclude Include="..\..\..\src\jsonv-tests\filesystem_util.hpp" />
<ClInclude Include="..\..\..\src\jsonv-tests\stopwatch.hpp" />
<ClInclude Include="..\..\..\src\jsonv-tests\test.hpp" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\src\jsonv-tests\data\canada.json" />
<None Include="..\..\..\src\jsonv-tests\data\diffs\arrays_different.json" />
<None Include="..\..\..\src\jsonv-tests\data\diffs\arrays_different_left_longer.json" />
<None Include="..\..\..\src\jsonv-tests\data\diffs\arrays_different_recursive.json" />
Expand Down Expand Up @@ -261,4 +267,4 @@
</PropertyGroup>
<Error Condition="!Exists('..\packages\boost.1.60.0.0\build\native\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\boost.1.60.0.0\build\native\boost.targets'))" />
</Target>
</Project>
</Project>
22 changes: 20 additions & 2 deletions msvc/vs2015/jsonv-tests/jsonv-tests.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,15 @@
<ClCompile Include="..\..\..\src\jsonv-tests\array_tests.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jsonv-tests\benchmark_tests.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jsonv-tests\char_convert_tests.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jsonv-tests\chrono_io.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jsonv-tests\coerce_tests.cpp">
<Filter>src</Filter>
</ClCompile>
Expand Down Expand Up @@ -71,6 +77,9 @@
<ClCompile Include="..\..\..\src\jsonv-tests\serialization_tests.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jsonv-tests\stopwatch.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jsonv-tests\string_tests.cpp">
<Filter>src</Filter>
</ClCompile>
Expand Down Expand Up @@ -106,14 +115,23 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\jsonv-tests\chrono_io.hpp">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jsonv-tests\filesystem_util.hpp">
<Filter>src</Filter>
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jsonv-tests\stopwatch.hpp">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jsonv-tests\test.hpp">
<Filter>include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\src\jsonv-tests\data\canada.json">
<Filter>src\data</Filter>
</None>
<None Include="..\..\..\src\jsonv-tests\data\generated.json">
<Filter>src\data</Filter>
</None>
Expand Down Expand Up @@ -311,4 +329,4 @@
</None>
<None Include="packages.config" />
</ItemGroup>
</Project>
</Project>
100 changes: 100 additions & 0 deletions src/jsonv-tests/benchmark_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/** \file
*
* Copyright (c) 2016 by Travis Gockel. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
* as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
* version.
*
* \author Travis Gockel (travis@gockelhut.com)
**/
#include "test.hpp"
#include "chrono_io.hpp"
#include "filesystem_util.hpp"
#include "stopwatch.hpp"

#include <jsonv/parse.hpp>
#include <jsonv/util.hpp>
#include <jsonv/value.hpp>

#include <fstream>
#include <iostream>

namespace jsonv_test
{

using namespace jsonv;

static const unsigned iterations = JSONV_DEBUG ? 1 : 100;

template <typename FLoadSource>
static void run_test(FLoadSource load, const std::string& from)
{
stopwatch timer;
for (unsigned cnt = 0; cnt < iterations; ++cnt)
{
auto src_data = load(from);
{
JSONV_TEST_TIME(timer);
parse(src_data);
}
}
std::cout << timer.get();
}

template <typename FLoadSource>
class benchmark_test :
public unit_test
{
public:
benchmark_test(FLoadSource load_source, std::string source_desc, std::string path) :
unit_test(std::string("benchmark/") + source_desc + "/" + filename(path)),
load_source(std::move(load_source)),
path(std::move(path))
{ }

virtual void run_impl() override
{
run_test(load_source, path);
}

private:
FLoadSource load_source;
std::string path;
};

class benchmark_test_initializer
{
public:
explicit benchmark_test_initializer(const std::string& rootpath)
{
using ifstream_loader = std::ifstream (*)(const std::string&);
ifstream_loader ifstream_load = [] (const std::string& p) { return std::ifstream(p); };

using string_loader = std::string (*)(const std::string&);
string_loader string_load = load_from_file;

recursive_directory_for_each(rootpath, ".json", [&, this] (const std::string& path)
{
_tests.emplace_back(new benchmark_test<ifstream_loader>(ifstream_load, "ifstream", path));
_tests.emplace_back(new benchmark_test<string_loader>(string_load, "string", path));
});
}

static std::string load_from_file(const std::string& path)
{
std::ifstream inputfile(path.c_str());
std::string out;
inputfile.seekg(0, std::ios::end);
out.reserve(inputfile.tellg());
inputfile.seekg(0, std::ios::beg);

out.assign(std::istreambuf_iterator<char>(inputfile), std::istreambuf_iterator<char>());
return out;
}

private:
std::deque<std::unique_ptr<unit_test>> _tests;
} benchmark_test_initializer_instance(test_path(""));

}
42 changes: 42 additions & 0 deletions src/jsonv-tests/chrono_io.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <iomanip>
#include <ostream>

#include "chrono_io.hpp"

namespace jsonv_test
{

std::ostream& operator<<(std::ostream& os, std::chrono::nanoseconds value)
{
using namespace std::chrono;

if (value < nanoseconds(0))
{
// Don't know how ISO 8601 is supposed to deal with negative durations since the Wikipedia did not mention them.
os << '-';
value = -value;
}
os << "PT";
auto hrs = duration_cast<hours>(value);
if (hrs > hours(0))
{
os << hrs.count() << 'H';
value -= hrs;
}
auto mins = duration_cast<minutes>(value);
if (mins > minutes(0))
{
os << mins.count() << 'M';
value -= mins;
}
auto secs = duration_cast<seconds>(value);
value -= secs;
os << secs.count();
os << '.';
os << std::setfill('0') << std::setw(9) << value.count();
os << 'S';

return os;
}

}
32 changes: 32 additions & 0 deletions src/jsonv-tests/chrono_io.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/** \file
* I/O for the chrono library.
*
* Copyright (c) 2016 by Travis Gockel. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
* as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
* version.
*
* \author Travis Gockel (travis@gockelhut.com)
**/
#ifndef __JSONV_TESTS_CHRONO_IO_HPP_INCLUDED__
#define __JSONV_TESTS_CHRONO_IO_HPP_INCLUDED__

#include <chrono>
#include <cstdint>
#include <iosfwd>

namespace jsonv_test
{

std::ostream& operator<<(std::ostream&, std::chrono::nanoseconds);

template <typename TRep, typename TPeriod>
std::ostream& operator<<(std::ostream& os, std::chrono::duration<TRep, TPeriod> value)
{
return os << std::chrono::duration_cast<std::chrono::nanoseconds>(value);
}

}

#endif/*__JSONV_TESTS_CHRONO_IO_HPP_INCLUDED__*/
9 changes: 9 additions & 0 deletions src/jsonv-tests/data/canada.json

Large diffs are not rendered by default.

33 changes: 1 addition & 32 deletions src/jsonv-tests/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** \file
*
* Copyright (c) 2012-2014 by Travis Gockel. All rights reserved.
* Copyright (c) 2012-2016 by Travis Gockel. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
* as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
Expand All @@ -23,35 +23,6 @@
#include "filesystem_util.hpp"
#include "test.hpp"

int benchmark(const std::string& filename, const int ntimes = 1000)
{
std::ifstream inputfile(filename.c_str());
std::string to_parse;

inputfile.seekg(0, std::ios::end);
to_parse.reserve(inputfile.tellg());
inputfile.seekg(0, std::ios::beg);

to_parse.assign((std::istreambuf_iterator<char>(inputfile)),
std::istreambuf_iterator<char>());

std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
for (int i = 0; i < ntimes; ++i)
{
jsonv::value x = jsonv::parse(to_parse);
}
std::chrono::steady_clock::time_point end_time = std::chrono::steady_clock::now();
std::chrono::microseconds us = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time);
std::cout << "[+] Finished successfully with an average of: " << (us.count() / ntimes) << " us\n";

return 0;
}

TEST(benchmark)
{
benchmark(jsonv_test::test_path("generated.json"), 10);
}

TEST(demo)
{
std::string src = "{ \"blazing\": [ 3, \"\\\"\\n\", 4.5, 5.123, 4.10921e19 ], "
Expand All @@ -69,8 +40,6 @@ int main(int argc, char** argv)
std::string filter;
if (argc == 2)
filter = argv[1];
else if (argc == 3 && std::string("benchmark") == argv[1])
return benchmark(argv[2]);

int fail_count = 0;
for (auto test : jsonv_test::get_unit_tests())
Expand Down
18 changes: 18 additions & 0 deletions src/jsonv-tests/stopwatch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "chrono_io.hpp"
#include "stopwatch.hpp"

#include <ostream>

namespace jsonv_test
{

std::ostream& operator<<(std::ostream& os, const stopwatch::values& x)
{
os << "{\"total\": \"" << x.sum << '\"';
os << ", \"count\": " << x.count;
os << ", \"mean\": \"" << x.mean << '\"';
os << '}';
return os;
}

}
Loading

0 comments on commit 9933679

Please sign in to comment.