From d026752df6ac69aff3d993e416bd599fc7effcb6 Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Thu, 29 Nov 2018 13:36:27 +0100 Subject: [PATCH] Add set functions --- .clang-format | 117 +++++++++ .gitmodules | 3 + cpp-seminar.pro | 3 +- preprocessor/preprocessor.pro | 16 ++ set_functions/set_functions-benchmark.cpp | 289 ++++++++++++++++++++++ set_functions/set_functions.pro | 7 + shared/benchmark_dependency.pri | 2 + 7 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 .clang-format create mode 100644 preprocessor/preprocessor.pro create mode 100644 set_functions/set_functions-benchmark.cpp create mode 100644 set_functions/set_functions.pro diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..8e1f593 --- /dev/null +++ b/.clang-format @@ -0,0 +1,117 @@ +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: false +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepLineBreaksForNonEmptyLines: false +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 8 +UseTab: Never +... diff --git a/.gitmodules b/.gitmodules index 96456a1..011ece9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "googletest"] path = googletest url = https://github.com/google/googletest.git +[submodule "ranges"] + path = ranges + url = https://github.com/ericniebler/range-v3.git diff --git a/cpp-seminar.pro b/cpp-seminar.pro index 71c15cf..35444c0 100644 --- a/cpp-seminar.pro +++ b/cpp-seminar.pro @@ -4,4 +4,5 @@ SUBDIRS = \ polymorphism \ sorting \ exceptions \ - fold-expression + fold-expression \ + set_functions diff --git a/preprocessor/preprocessor.pro b/preprocessor/preprocessor.pro new file mode 100644 index 0000000..d454df6 --- /dev/null +++ b/preprocessor/preprocessor.pro @@ -0,0 +1,16 @@ +include(../shared/test.pri) + +TARGET = preprocessor + +HEADERS += \ + config.h \ + interface.h + +SOURCES += \ + implementation.cpp + +win32:SOURCES += \ + implementation_win32.cpp + +unix:SOURCES += \ + implementation_unix.cpp diff --git a/set_functions/set_functions-benchmark.cpp b/set_functions/set_functions-benchmark.cpp new file mode 100644 index 0000000..fcee788 --- /dev/null +++ b/set_functions/set_functions-benchmark.cpp @@ -0,0 +1,289 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +class RandomGenerator +{ +public: + RandomGenerator(int seed) + : generator{seed} + {} + + int operator()() + { + return uniform_distribution(generator); + } + +private: + std::mt19937 generator; + std::uniform_int_distribution<> uniform_distribution{1, 1000}; +}; + +struct Entry +{ + std::string text; + int index = 0; +}; + +class SetFunctions : public benchmark::Fixture +{ +public: + void SetUp(benchmark::State &state) override + { + numbersSize = 1 << state.range(0); + + sortedNumbersOne.clear(); + sortedNumbersOne.resize(numbersSize); + std::iota(sortedNumbersOne.begin(), sortedNumbersOne.end(), 1); + + randomNumbersOne = sortedNumbersOne; + std::random_shuffle(randomNumbersOne.begin(), randomNumbersOne.end()); + + sortedNumbersTwo.clear(); + sortedNumbersTwo.resize(numbersSize); + std::iota(sortedNumbersTwo.begin(), sortedNumbersTwo.end(), numbersSize / 2); + + randomNumbersTwo = sortedNumbersTwo; + std::random_shuffle(randomNumbersTwo.begin(), randomNumbersTwo.end()); + + sortedStringOne.clear(); + sortedStringOne.reserve(numbersSize); + std::transform(sortedNumbersOne.begin(), sortedNumbersOne.end(), std::back_inserter(sortedStringOne), [] (int number) { + return std::to_string(number) + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; + }); + + sortedStringTwo.clear(); + sortedStringTwo.reserve(numbersSize); + std::transform(sortedNumbersTwo.begin(), sortedNumbersTwo.end(), std::back_inserter(sortedStringTwo), [] (int number) { + return std::to_string(number) + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; + }); + + randomStringOne.clear(); + randomStringOne.reserve(numbersSize); + std::transform(randomNumbersOne.begin(), randomNumbersOne.end(), std::back_inserter(randomStringOne), [] (int number) { + return std::to_string(number) + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; + }); + + randomStringTwo.clear(); + randomStringTwo.reserve(numbersSize); + std::transform(randomNumbersTwo.begin(), randomNumbersTwo.end(), std::back_inserter(randomStringTwo), [] (int number) { + return std::to_string(number) + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"; + }); + + entries.clear(); + entries.reserve(numbersSize); + int index = 0; + std::transform(randomNumbersOne.begin(), randomNumbersOne.end(), std::back_inserter(entries), [&] (int number) { + return Entry{std::to_string(number) + "12345678901234567890123456789012345678901234567890123456789012345678901234567890", ++index}; + }); + } + + void TearDown(benchmark::State &state) override + { + state.SetItemsProcessed(int64_t(state.iterations() * numbersSize)); + if (numbersSize > 1000) { + state.SetLabel("\tSample Size: " + + std::to_string(numbersSize / 1000) + + "K"); + } else { + state.SetLabel("\tSample Size: " + std::to_string(numbersSize)); + } + } + +public: + RandomGenerator generator{212}; + std::vector sortedNumbersOne; + std::vector sortedNumbersTwo; + std::vector sortedStringOne; + std::vector sortedStringTwo; + std::vector randomNumbersOne; + std::vector randomNumbersTwo; + std::vector randomStringOne; + std::vector randomStringTwo; + std::vector entries; + std::size_t numbersSize = 0; +}; + +BENCHMARK_DEFINE_F(SetFunctions, SetUnionInt)(benchmark::State &state) +{ + for (auto _ : state) { + std::vector result; + result.reserve(sortedNumbersOne.size() + sortedNumbersTwo.size()); + std::set_union(sortedNumbersOne.begin(), sortedNumbersOne.end(), sortedNumbersTwo.begin(), sortedNumbersTwo.end(), std::back_inserter(result)); + benchmark::DoNotOptimize(result); + } +} + +BENCHMARK_REGISTER_F(SetFunctions, SetUnionInt)->DenseRange(5, 17); + +BENCHMARK_DEFINE_F(SetFunctions, SetUnionIntWithSorting)(benchmark::State &state) +{ + for (auto _ : state) { + std::sort(std::begin(randomNumbersOne), std::end(randomNumbersOne)); + std::sort(std::begin(randomNumbersTwo), std::end(randomNumbersTwo)); + std::vector result; + result.reserve(randomNumbersOne.size() + randomNumbersTwo.size()); + std::set_union(randomNumbersOne.begin(), randomNumbersOne.end(), randomNumbersTwo.begin(), randomNumbersTwo.end(), std::back_inserter(result)); + benchmark::DoNotOptimize(result); + } +} + +BENCHMARK_REGISTER_F(SetFunctions, SetUnionIntWithSorting)->DenseRange(5, 17); + +BENCHMARK_DEFINE_F(SetFunctions, SetInt)(benchmark::State &state) +{ + for (auto _ : state) { + std::unordered_set resultSet(randomNumbersOne.begin(), randomNumbersOne.end()); + resultSet.insert(randomNumbersTwo.begin(), randomNumbersTwo.end()); + + std::vector result{resultSet.begin(), resultSet.end()}; + + benchmark::DoNotOptimize(result); + } +} + +BENCHMARK_REGISTER_F(SetFunctions, SetInt)->DenseRange(5, 17); + +BENCHMARK_DEFINE_F(SetFunctions, SetUnionStrings)(benchmark::State &state) +{ + for (auto _ : state) { + std::vector result; + result.reserve(sortedStringOne.size() + sortedStringTwo.size()); + std::set_union(std::make_move_iterator(sortedStringOne.begin()), + std::make_move_iterator(sortedStringOne.end()), + std::make_move_iterator(sortedStringTwo.begin()), + std::make_move_iterator(sortedStringTwo.end()), + std::back_inserter(result)); + benchmark::DoNotOptimize(result); + } +} + +BENCHMARK_REGISTER_F(SetFunctions, SetUnionStrings)->DenseRange(5, 17); + +BENCHMARK_DEFINE_F(SetFunctions, SetUnionStringWithSorting)(benchmark::State &state) +{ + for (auto _ : state) { + std::sort(std::begin(randomStringOne), std::end(randomStringOne)); + std::sort(std::begin(randomStringTwo), std::end(randomStringTwo)); + std::vector result; + result.reserve(randomStringOne.size() + randomStringTwo.size()); + std::set_union(std::make_move_iterator(randomStringOne.begin()), + std::make_move_iterator(randomStringOne.end()), + std::make_move_iterator(randomStringTwo.begin()), + std::make_move_iterator(randomStringTwo.end()), + std::back_inserter(result)); + benchmark::DoNotOptimize(result); + } +} + +BENCHMARK_REGISTER_F(SetFunctions, SetUnionStringWithSorting)->DenseRange(5, 17); + +BENCHMARK_DEFINE_F(SetFunctions, SetString)(benchmark::State &state) +{ + for (auto _ : state) { + std::unordered_set resultSet(randomStringOne.begin(), randomStringOne.end()); + resultSet.insert(randomStringTwo.begin(), randomStringTwo.end()); + + std::vector result{resultSet.begin(), resultSet.end()}; + + benchmark::DoNotOptimize(result); + } +} + +BENCHMARK_REGISTER_F(SetFunctions, SetString)->DenseRange(5, 17); + +BENCHMARK_DEFINE_F(SetFunctions, SetStringSorted)(benchmark::State &state) +{ + for (auto _ : state) { + std::unordered_set resultSet(sortedStringOne.begin(), sortedStringOne.end()); + resultSet.insert(sortedStringTwo.begin(), sortedStringTwo.end()); + + std::vector result{resultSet.begin(), resultSet.end()}; + + std::sort(std::begin(result), std::end(result)); + + benchmark::DoNotOptimize(result); + } +} + +BENCHMARK_REGISTER_F(SetFunctions, SetStringSorted)->DenseRange(5, 17); + +BENCHMARK_DEFINE_F(SetFunctions, UniqueOrderedSet)(benchmark::State &state) +{ + for (auto _ : state) { + std::vector result; + result.reserve(sortedStringOne.size()); + std::unordered_set set; + + + for (const std::string &entry : sortedStringOne) { + auto found = set.find(entry); + + if (found != set.end()) { + result.push_back(entry); + set.insert(found, entry); + } + } + + benchmark::DoNotOptimize(result); + } +} + +BENCHMARK_REGISTER_F(SetFunctions, UniqueOrderedSet)->DenseRange(5, 17); + +BENCHMARK_DEFINE_F(SetFunctions, UniqueSorted)(benchmark::State &state) +{ + for (auto _ : state) { + state.PauseTiming(); + auto result = entries; + state.ResumeTiming(); + + std::stable_sort(result.begin(), result.end(), [] (const Entry &first, const Entry &second) { + return first.text < second.text; + }); + + auto newEnd = std::unique(result.begin(), result.end(), [] (const Entry &first, const Entry &second) { + return first.text == second.text; + }); + + result.erase(newEnd, result.end()); + + std::sort(result.begin(), result.end(), [] (const Entry &first, const Entry &second) { + return first.index < second.index; + }); + + + benchmark::DoNotOptimize(result); + } +} + +BENCHMARK_REGISTER_F(SetFunctions, UniqueSorted)->DenseRange(5, 17); diff --git a/set_functions/set_functions.pro b/set_functions/set_functions.pro new file mode 100644 index 0000000..044ac3c --- /dev/null +++ b/set_functions/set_functions.pro @@ -0,0 +1,7 @@ +include(../shared/benchmark.pri) + +TARGET = set_functions + +SOURCES += \ + set_functions-benchmark.cpp + diff --git a/shared/benchmark_dependency.pri b/shared/benchmark_dependency.pri index 51a56b3..475bd73 100644 --- a/shared/benchmark_dependency.pri +++ b/shared/benchmark_dependency.pri @@ -4,8 +4,10 @@ INCLUDEPATH += $$GOOGLEBENCHMARK_DIR/include DEFINES += HAVE_STD_REGEX WITH_BENCHMARKS SOURCES += \ + $$GOOGLEBENCHMARK_DIR/src/benchmark_api_internal.cc \ $$GOOGLEBENCHMARK_DIR/src/benchmark.cc \ $$GOOGLEBENCHMARK_DIR/src/benchmark_register.cc \ + $$GOOGLEBENCHMARK_DIR/src/benchmark_runner.cc \ $$GOOGLEBENCHMARK_DIR/src/colorprint.cc \ $$GOOGLEBENCHMARK_DIR/src/commandlineflags.cc \ $$GOOGLEBENCHMARK_DIR/src/complexity.cc \ -- GitLab