aboutsummaryrefslogtreecommitdiff
path: root/EASTL/benchmark/source/BenchmarkString.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'EASTL/benchmark/source/BenchmarkString.cpp')
-rw-r--r--EASTL/benchmark/source/BenchmarkString.cpp531
1 files changed, 531 insertions, 0 deletions
diff --git a/EASTL/benchmark/source/BenchmarkString.cpp b/EASTL/benchmark/source/BenchmarkString.cpp
new file mode 100644
index 0000000..5dfefbc
--- /dev/null
+++ b/EASTL/benchmark/source/BenchmarkString.cpp
@@ -0,0 +1,531 @@
+/////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "EASTLBenchmark.h"
+#include "EASTLTest.h"
+#include <EAStdC/EAStopwatch.h>
+#include <EASTL/algorithm.h>
+#include <EASTL/string.h>
+#include <EASTL/sort.h>
+
+EA_DISABLE_ALL_VC_WARNINGS()
+#include <algorithm>
+#include <string>
+#include <stdio.h>
+#include <stdlib.h>
+EA_RESTORE_ALL_VC_WARNINGS()
+
+
+using namespace EA;
+
+
+namespace
+{
+ template <typename Container>
+ void TestPushBack(EA::StdC::Stopwatch& stopwatch, Container& c)
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 100000; i++)
+ c.push_back((typename Container::value_type)(i & ((typename Container::value_type)~0)));
+ stopwatch.Stop();
+ }
+
+
+ template <typename Container, typename T>
+ void TestInsert1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p)
+ {
+ const typename Container::size_type s = c.size();
+ stopwatch.Restart();
+ for(int i = 0; i < 100; i++)
+ c.insert(s - (typename Container::size_type)(i * 317), p);
+ stopwatch.Stop();
+ }
+
+
+ template <typename Container>
+ void TestErase1(EA::StdC::Stopwatch& stopwatch, Container& c)
+ {
+ const typename Container::size_type s = c.size();
+ stopwatch.Restart();
+ for(int i = 0; i < 100; i++)
+ c.erase(s - (typename Container::size_type)(i * 339), 7);
+ stopwatch.Stop();
+ }
+
+
+ template <typename Container, typename T>
+ void TestReplace1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int n)
+ {
+ const typename Container::size_type s = c.size();
+ stopwatch.Restart();
+ for(int i = 0; i < 1000; i++)
+ c.replace(s - (typename Container::size_type)(i * 5), ((n - 2) + (i & 3)), p, n); // The second argument rotates through n-2, n-1, n, n+1, n-2, etc.
+ stopwatch.Stop();
+ }
+
+
+ template <typename Container>
+ void TestReserve(EA::StdC::Stopwatch& stopwatch, Container& c)
+ {
+ const typename Container::size_type s = c.capacity();
+ stopwatch.Restart();
+ for(int i = 0; i < 1000; i++)
+ c.reserve((s - 2) + (i & 3)); // The second argument rotates through n-2, n-1, n, n+1, n-2, etc.
+ stopwatch.Stop();
+ }
+
+
+ template <typename Container>
+ void TestSize(EA::StdC::Stopwatch& stopwatch, Container& c)
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 1000; i++)
+ Benchmark::DoNothing(&c, c.size());
+ stopwatch.Stop();
+ }
+
+
+ template <typename Container>
+ void TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c)
+ {
+ int32_t temp = 0;
+ stopwatch.Restart();
+ for(typename Container::size_type j = 0, jEnd = c.size(); j < jEnd; j++)
+ temp += c[j];
+ stopwatch.Stop();
+ sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)temp);
+ }
+
+
+ template <typename Container>
+ void TestFind(EA::StdC::Stopwatch& stopwatch, Container& c)
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 1000; i++)
+ Benchmark::DoNothing(&c, *eastl::find(c.begin(), c.end(), (typename Container::value_type)~0));
+ stopwatch.Stop();
+ }
+
+
+ template <typename Container, typename T>
+ void TestFind1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 1000; i++)
+ Benchmark::DoNothing(&c, c.find(p, (typename Container::size_type)pos, (typename Container::size_type)n));
+ stopwatch.Stop();
+ }
+
+
+ template <typename Container, typename T>
+ void TestRfind1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 1000; i++)
+ Benchmark::DoNothing(&c, c.rfind(p, (typename Container::size_type)pos, (typename Container::size_type)n));
+ stopwatch.Stop();
+ }
+
+ template <typename Container, typename T>
+ void TestFirstOf1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 1000; i++)
+ Benchmark::DoNothing(&c, c.find_first_of(p, (typename Container::size_type)pos, (typename Container::size_type)n));
+ stopwatch.Stop();
+ }
+
+ template <typename Container, typename T>
+ void TestLastOf1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 1000; i++)
+ Benchmark::DoNothing(&c, c.find_last_of(p, (typename Container::size_type)pos, (typename Container::size_type)n));
+ stopwatch.Stop();
+ }
+
+ template <typename Container, typename T>
+ void TestFirstNotOf1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 1000; i++)
+ Benchmark::DoNothing(&c, c.find_first_not_of(p, (typename Container::size_type)pos, (typename Container::size_type)n));
+ stopwatch.Stop();
+ }
+
+ template <typename Container, typename T>
+ void TestLastNotOf1(EA::StdC::Stopwatch& stopwatch, Container& c, T* p, int pos, int n)
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 1000; i++)
+ Benchmark::DoNothing(&c, c.find_last_not_of(p, (typename Container::size_type)pos, (typename Container::size_type)n));
+ stopwatch.Stop();
+ }
+
+
+ template <typename Container>
+ void TestCompare(EA::StdC::Stopwatch& stopwatch, Container& c1, Container& c2) // size()
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 500; i++)
+ Benchmark::DoNothing(&c1, c1.compare(c2));
+ stopwatch.Stop();
+ }
+
+
+ template <typename Container>
+ void TestSwap(EA::StdC::Stopwatch& stopwatch, Container& c1, Container& c2) // size()
+ {
+ stopwatch.Restart();
+ for(int i = 0; i < 10000; i++) // Make sure this is an even count so that when done things haven't changed.
+ {
+ c1.swap(c2);
+ Benchmark::DoNothing(&c1);
+ }
+ stopwatch.Stop();
+ }
+
+} // namespace
+
+
+
+
+void BenchmarkString()
+{
+ EASTLTest_Printf("String\n");
+
+ EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);
+ EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);
+
+ {
+ for(int i = 0; i < 2; i++)
+ {
+ std::basic_string<char8_t> ss8(16, 0); // We initialize to size of 16 because different implementations may make
+ eastl::basic_string<char8_t> es8(16, 0); // different tradeoffs related to startup size. Initial operations are faster
+ // when strings start with a higher reserve, but they use more memory.
+ std::basic_string<char16_t> ss16(16, 0); // We try to nullify this tradeoff for the tests below by starting all at
+ eastl::basic_string<char16_t> es16(16, 0); // the same baseline allocation.
+
+
+ ///////////////////////////////
+ // Test push_back
+ ///////////////////////////////
+
+ TestPushBack(stopwatch1, ss8);
+ TestPushBack(stopwatch2, es8);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/push_back", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestPushBack(stopwatch1, ss16);
+ TestPushBack(stopwatch2, es16);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/push_back", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test insert(size_type position, const value_type* p)
+ ///////////////////////////////
+
+ const char8_t pInsert1_8[] = { 'a', 0 };
+ TestInsert1(stopwatch1, ss8, pInsert1_8);
+ TestInsert1(stopwatch2, es8, pInsert1_8);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/insert/pos,p", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ const char16_t pInsert1_16[] = { 'a', 0 };
+ TestInsert1(stopwatch1, ss16, pInsert1_16);
+ TestInsert1(stopwatch2, es16, pInsert1_16);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/insert/pos,p", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test erase(size_type position, size_type n)
+ ///////////////////////////////
+
+ TestErase1(stopwatch1, ss8);
+ TestErase1(stopwatch2, es8);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/erase/pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestErase1(stopwatch1, ss16);
+ TestErase1(stopwatch2, es16);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/erase/pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test replace(size_type position, size_type n1, const value_type* p, size_type n2)
+ ///////////////////////////////
+
+ const int kReplace1Size = 8;
+ const char8_t pReplace1_8[kReplace1Size] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
+
+ TestReplace1(stopwatch1, ss8, pReplace1_8, kReplace1Size);
+ TestReplace1(stopwatch2, es8, pReplace1_8, kReplace1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/replace/pos,n,p,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ const char16_t pReplace1_16[kReplace1Size] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
+
+ TestReplace1(stopwatch1, ss16, pReplace1_16, kReplace1Size);
+ TestReplace1(stopwatch2, es16, pReplace1_16, kReplace1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/replace/pos,n,p,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test reserve(size_type)
+ ///////////////////////////////
+
+ TestReserve(stopwatch1, ss8);
+ TestReserve(stopwatch2, es8);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/reserve", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestReserve(stopwatch1, ss16);
+ TestReserve(stopwatch2, es16);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/reserve", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test size()
+ ///////////////////////////////
+
+ TestSize(stopwatch1, ss8);
+ TestSize(stopwatch2, es8);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/size", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestSize(stopwatch1, ss16);
+ TestSize(stopwatch2, es16);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/size", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test operator[].
+ ///////////////////////////////
+
+ TestBracket(stopwatch1, ss8);
+ TestBracket(stopwatch2, es8);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestBracket(stopwatch1, ss16);
+ TestBracket(stopwatch2, es16);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test iteration via find().
+ ///////////////////////////////
+
+ TestFind(stopwatch1, ss8);
+ TestFind(stopwatch2, es8);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestFind(stopwatch1, ss16);
+ TestFind(stopwatch2, es16);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test find(const value_type* p, size_type position, size_type n)
+ ///////////////////////////////
+
+ const int kFind1Size = 7;
+ const char8_t pFind1_8[kFind1Size] = { 'p', 'a', 't', 't', 'e', 'r', 'n' };
+
+ ss8.insert(ss8.size() / 2, pFind1_8);
+ es8.insert(es8.size() / 2, pFind1_8);
+
+ TestFind1(stopwatch1, ss8, pFind1_8, 15, kFind1Size);
+ TestFind1(stopwatch2, es8, pFind1_8, 15, kFind1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/find/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ const char16_t pFind1_16[kFind1Size] = { 'p', 'a', 't', 't', 'e', 'r', 'n' };
+
+ #if !defined(EA_PLATFORM_IPHONE) && (!defined(EA_COMPILER_CLANG) && defined(EA_PLATFORM_MINGW)) // Crashes on iPhone.
+ ss16.insert(ss8.size() / 2, pFind1_16);
+ #endif
+ es16.insert(es8.size() / 2, pFind1_16);
+
+ TestFind1(stopwatch1, ss16, pFind1_16, 15, kFind1Size);
+ TestFind1(stopwatch2, es16, pFind1_16, 15, kFind1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/find/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test rfind(const value_type* p, size_type position, size_type n)
+ ///////////////////////////////
+
+ TestRfind1(stopwatch1, ss8, pFind1_8, 15, kFind1Size);
+ TestRfind1(stopwatch2, es8, pFind1_8, 15, kFind1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/rfind/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestRfind1(stopwatch1, ss16, pFind1_16, 15, kFind1Size);
+ TestRfind1(stopwatch2, es16, pFind1_16, 15, kFind1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/rfind/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ //NOTICE (RASHIN):
+ //FindFirstOf variants are incredibly slow on palm pixi debug builds.
+ //Disabling for now...
+ #if !defined(EA_DEBUG)
+ ///////////////////////////////
+ // Test find_first_of(const value_type* p, size_type position, size_type n
+ ///////////////////////////////
+
+ const int kFindOf1Size = 7;
+ const char8_t pFindOf1_8[kFindOf1Size] = { '~', '~', '~', '~', '~', '~', '~' };
+
+ TestFirstOf1(stopwatch1, ss8, pFindOf1_8, 15, kFindOf1Size);
+ TestFirstOf1(stopwatch2, es8, pFindOf1_8, 15, kFindOf1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/find_first_of/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ const char16_t pFindOf1_16[kFindOf1Size] = { '~', '~', '~', '~', '~', '~', '~' };
+
+ TestFirstOf1(stopwatch1, ss16, pFindOf1_16, 15, kFindOf1Size);
+ TestFirstOf1(stopwatch2, es16, pFindOf1_16, 15, kFindOf1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/find_first_of/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test find_last_of(const value_type* p, size_type position, size_type n
+ ///////////////////////////////
+
+ TestLastOf1(stopwatch1, ss8, pFindOf1_8, 15, kFindOf1Size);
+ TestLastOf1(stopwatch2, es8, pFindOf1_8, 15, kFindOf1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/find_last_of/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestLastOf1(stopwatch1, ss16, pFindOf1_16, 15, kFindOf1Size);
+ TestLastOf1(stopwatch2, es16, pFindOf1_16, 15, kFindOf1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/find_last_of/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test find_first_not_of(const value_type* p, size_type position, size_type n
+ ///////////////////////////////
+
+ TestFirstNotOf1(stopwatch1, ss8, pFind1_8, 15, kFind1Size);
+ TestFirstNotOf1(stopwatch2, es8, pFind1_8, 15, kFind1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/find_first_not_of/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestFirstNotOf1(stopwatch1, ss16, pFind1_16, 15, kFind1Size);
+ TestFirstNotOf1(stopwatch2, es16, pFind1_16, 15, kFind1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/find_first_not_of/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+ ///////////////////////////////
+ // Test find_last_of(const value_type* p, size_type position, size_type n
+ ///////////////////////////////
+
+ TestLastNotOf1(stopwatch1, ss8, pFind1_8, 15, kFind1Size);
+ TestLastNotOf1(stopwatch2, es8, pFind1_8, 15, kFind1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/find_last_of/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestLastNotOf1(stopwatch1, ss16, pFind1_16, 15, kFind1Size);
+ TestLastNotOf1(stopwatch2, es16, pFind1_16, 15, kFind1Size);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/find_last_of/p,pos,n", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ #endif
+
+ ///////////////////////////////
+ // Test compare()
+ ///////////////////////////////
+
+ std::basic_string<char8_t> ss8X(ss8);
+ eastl::basic_string<char8_t> es8X(es8);
+ std::basic_string<char16_t> ss16X(ss16);
+ eastl::basic_string<char16_t> es16X(es16);
+
+ TestCompare(stopwatch1, ss8, ss8X);
+ TestCompare(stopwatch2, es8, es8X);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/compare", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestCompare(stopwatch1, ss16, ss16X);
+ TestCompare(stopwatch2, es16, es16X);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/compare", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+
+
+ ///////////////////////////////
+ // Test swap()
+ ///////////////////////////////
+
+ TestSwap(stopwatch1, ss8, ss8X);
+ TestSwap(stopwatch2, es8, es8X);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char8_t>/swap", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ TestSwap(stopwatch1, ss16, ss16X);
+ TestSwap(stopwatch2, es16, es16X);
+
+ if(i == 1)
+ Benchmark::AddResult("string<char16_t>/swap", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
+
+ }
+ }
+
+}
+
+
+
+
+
+
+
+
+