First
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
#-------------------------------------------------------------------------------------------
|
||||
# Copyright (C) Electronic Arts Inc. All rights reserved.
|
||||
#-------------------------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------------------------------------------------------------------
|
||||
# CMake info
|
||||
#-------------------------------------------------------------------------------------------
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(EASTLBenchmarks CXX)
|
||||
include(CTest)
|
||||
|
||||
#-------------------------------------------------------------------------------------------
|
||||
# Defines
|
||||
#-------------------------------------------------------------------------------------------
|
||||
add_definitions(-D_CHAR16T)
|
||||
|
||||
#-------------------------------------------------------------------------------------------
|
||||
# Include directories
|
||||
#-------------------------------------------------------------------------------------------
|
||||
include_directories(source)
|
||||
include_directories(../test/source)
|
||||
|
||||
#-------------------------------------------------------------------------------------------
|
||||
# Compiler Flags
|
||||
#-------------------------------------------------------------------------------------------
|
||||
set (CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/../scripts/CMake")
|
||||
include(CommonCppFlags)
|
||||
|
||||
# Libstdc++ calls new internally, since DLLs have no weak symbols, runtime symbol resolution fails and EASTL's new is not called.
|
||||
# Linking against static libstdc++ fixes this.
|
||||
# See https://github.com/electronicarts/EASTL/issues/40 for more info.
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND MINGW)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -static-libstdc++")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} -static-libstdc++")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} -static-libstdc++")
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_BUILD_TYPE MATCHES "MinSizeRel" AND MINGW)
|
||||
message(FATAL_ERROR "FIXME: MinSizeRel on MingW-w64's Clang fails to link.")
|
||||
endif()
|
||||
|
||||
# The benchmark suite fails to compile if char8_t is enabled, so disable it.
|
||||
if (EASTL_NO_CHAR8T_FLAG)
|
||||
add_compile_options(${EASTL_NO_CHAR8T_FLAG})
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------------------
|
||||
# Source files
|
||||
#-------------------------------------------------------------------------------------------
|
||||
file(GLOB EASTLBENCHMARK_SOURCES "source/*.cpp" "../test/source/EASTLTestAllocator.cpp" "../test/source/EASTLTest.cpp")
|
||||
set(SOURCES ${EASTLBENCHMARK_SOURCES})
|
||||
|
||||
#-------------------------------------------------------------------------------------------
|
||||
# Defines
|
||||
#-------------------------------------------------------------------------------------------
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
add_definitions(-D_SCL_SECURE_NO_WARNINGS)
|
||||
add_definitions(-DEASTL_THREAD_SUPPORT_AVAILABLE=0)
|
||||
add_definitions(-DEASTL_OPENSOURCE=1)
|
||||
add_definitions(-D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS) # silence std::hash_map deprecation warnings
|
||||
if (EASTL_STD_ITERATOR_CATEGORY_ENABLED)
|
||||
add_definitions(-DEASTL_STD_ITERATOR_CATEGORY_ENABLED=1)
|
||||
endif()
|
||||
|
||||
if(NOT EASTL_BUILD_TESTS)
|
||||
add_subdirectory(../test/packages/EAStdC ../test/EAStdC)
|
||||
add_subdirectory(../test/packages/EAAssert ../test/EAAssert)
|
||||
add_subdirectory(../test/packages/EAThread ../test/EAThread)
|
||||
add_subdirectory(../test/packages/EATest ../test/EATest)
|
||||
add_subdirectory(../test/packages/EAMain ../test/EAMain)
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------------------
|
||||
# Executable definition
|
||||
#-------------------------------------------------------------------------------------------
|
||||
add_executable(EASTLBenchmarks ${EASTLBENCHMARK_SOURCES})
|
||||
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
set(EASTLBenchmark_Libraries
|
||||
EABase
|
||||
EAAssert
|
||||
EAMain
|
||||
EAThread
|
||||
EAStdC
|
||||
EASTL
|
||||
EATest)
|
||||
target_link_libraries(EASTLBenchmarks ${EASTLBenchmark_Libraries} Threads::Threads)
|
||||
|
||||
#-------------------------------------------------------------------------------------------
|
||||
# Run Unit tests and verify the results.
|
||||
#-------------------------------------------------------------------------------------------
|
||||
add_test(EASTLBenchmarkRuns EASTLBenchmarks)
|
||||
set_tests_properties (EASTLBenchmarkRuns PROPERTIES PASS_REGULAR_EXPRESSION "RETURNCODE=0")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,366 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Microsoft STL generates warnings.
|
||||
#pragma warning(disable: 4267) // 'initializing' : conversion from 'size_t' to 'const int', possible loss of data
|
||||
#endif
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <EASTL/bitset.h>
|
||||
|
||||
|
||||
EA_DISABLE_ALL_VC_WARNINGS()
|
||||
#include <bitset>
|
||||
EA_RESTORE_ALL_VC_WARNINGS()
|
||||
|
||||
|
||||
using namespace EA;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Bitset>
|
||||
void TestSet(EA::StdC::Stopwatch& stopwatch, Bitset& b)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for(int i = 0; i < 100000; i++)
|
||||
{
|
||||
b.set();
|
||||
Benchmark::DoNothing(&b);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Bitset>
|
||||
void TestSetIndex(EA::StdC::Stopwatch& stopwatch, Bitset& b, size_t index)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for(int i = 0; i < 100000; i++)
|
||||
{
|
||||
b.set(index);
|
||||
Benchmark::DoNothing(&b);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Bitset>
|
||||
void TestReset(EA::StdC::Stopwatch& stopwatch, Bitset& b)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for(int i = 0; i < 100000; i++)
|
||||
{
|
||||
b.reset();
|
||||
Benchmark::DoNothing(&b);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Bitset>
|
||||
void TestFlip(EA::StdC::Stopwatch& stopwatch, Bitset& b)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for(int i = 0; i < 100000; i++)
|
||||
{
|
||||
b.flip();
|
||||
Benchmark::DoNothing(&b);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Bitset>
|
||||
void TestTest(EA::StdC::Stopwatch& stopwatch, Bitset& b, unsigned nANDValue)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for(unsigned i = 0; i < 100000; i++)
|
||||
Benchmark::DoNothing(b.test(i & nANDValue)); // We use & instead of % because the former is always fast due to forced power of 2.
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Bitset>
|
||||
void TestCount(EA::StdC::Stopwatch& stopwatch, Bitset& b)
|
||||
{
|
||||
size_t temp = 0;
|
||||
stopwatch.Restart();
|
||||
for(int i = 0; i < 100000; i++)
|
||||
{
|
||||
temp += b.count();
|
||||
Benchmark::DoNothing(&temp);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Bitset>
|
||||
void TestRightShift(EA::StdC::Stopwatch& stopwatch, Bitset& b, size_t n)
|
||||
{
|
||||
size_t temp = 0;
|
||||
stopwatch.Restart();
|
||||
for(int i = 0; i < 100000; i++)
|
||||
{
|
||||
b >>= n;
|
||||
Benchmark::DoNothing(&temp);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
void BenchmarkBitset()
|
||||
{
|
||||
EASTLTest_Printf("Bitset\n");
|
||||
|
||||
EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
|
||||
{
|
||||
std::bitset<15> stdBitset15;
|
||||
eastl::bitset<15> eaBitset15;
|
||||
|
||||
std::bitset<35> stdBitset35;
|
||||
eastl::bitset<35> eaBitset35;
|
||||
|
||||
std::bitset<75> stdBitset75;
|
||||
eastl::bitset<75> eaBitset75;
|
||||
|
||||
std::bitset<1500> stdBitset1500;
|
||||
eastl::bitset<1500> eaBitset1500;
|
||||
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
///////////////////////////////
|
||||
// Test set()
|
||||
///////////////////////////////
|
||||
|
||||
TestSet(stopwatch1, stdBitset15);
|
||||
TestSet(stopwatch2, eaBitset15);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<15>/set()", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestSet(stopwatch1, stdBitset35);
|
||||
TestSet(stopwatch2, eaBitset35);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<35>/set()", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestSet(stopwatch1, stdBitset75);
|
||||
TestSet(stopwatch2, eaBitset75);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<75>/set()", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestSet(stopwatch1, stdBitset1500);
|
||||
TestSet(stopwatch2, eaBitset1500);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<1500>/set()", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test set(index)
|
||||
///////////////////////////////
|
||||
|
||||
TestSetIndex(stopwatch1, stdBitset15, 13);
|
||||
TestSetIndex(stopwatch2, eaBitset15, 13);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<15>/set(i)", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestSetIndex(stopwatch1, stdBitset35, 33);
|
||||
TestSetIndex(stopwatch2, eaBitset35, 33);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<35>/set(i)", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestSetIndex(stopwatch1, stdBitset75, 73);
|
||||
TestSetIndex(stopwatch2, eaBitset75, 73);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<75>/set(i)", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestSetIndex(stopwatch1, stdBitset1500, 730);
|
||||
TestSetIndex(stopwatch2, eaBitset1500, 730);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<1500>/set(i)", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test reset()
|
||||
///////////////////////////////
|
||||
|
||||
TestReset(stopwatch1, stdBitset15);
|
||||
TestReset(stopwatch2, eaBitset15);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<15>/reset", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestReset(stopwatch1, stdBitset35);
|
||||
TestReset(stopwatch2, eaBitset35);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<35>/reset", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestReset(stopwatch1, stdBitset75);
|
||||
TestReset(stopwatch2, eaBitset75);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<75>/reset", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestReset(stopwatch1, stdBitset1500);
|
||||
TestReset(stopwatch2, eaBitset1500);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<1500>/reset", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test flip
|
||||
///////////////////////////////
|
||||
|
||||
TestFlip(stopwatch1, stdBitset15);
|
||||
TestFlip(stopwatch2, eaBitset15);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<15>/flip", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestFlip(stopwatch1, stdBitset35);
|
||||
TestFlip(stopwatch2, eaBitset35);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<35>/flip", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestFlip(stopwatch1, stdBitset75);
|
||||
TestFlip(stopwatch2, eaBitset75);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<75>/flip", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestFlip(stopwatch1, stdBitset1500);
|
||||
TestFlip(stopwatch2, eaBitset1500);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<1500>/flip", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test test
|
||||
///////////////////////////////
|
||||
|
||||
TestTest(stopwatch1, stdBitset15, 7);
|
||||
TestTest(stopwatch2, eaBitset15, 7);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<15>/test", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestTest(stopwatch1, stdBitset35, 31);
|
||||
TestTest(stopwatch2, eaBitset35, 31);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<35>/test", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestTest(stopwatch1, stdBitset75, 63);
|
||||
TestTest(stopwatch2, eaBitset75, 63);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<75>/test", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestTest(stopwatch1, stdBitset1500, 1023);
|
||||
TestTest(stopwatch2, eaBitset1500, 1023);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<1500>/test", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test count
|
||||
///////////////////////////////
|
||||
|
||||
TestCount(stopwatch1, stdBitset15);
|
||||
TestCount(stopwatch2, eaBitset15);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<15>/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestCount(stopwatch1, stdBitset35);
|
||||
TestCount(stopwatch2, eaBitset35);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<35>/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestCount(stopwatch1, stdBitset75);
|
||||
TestCount(stopwatch2, eaBitset75);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<75>/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestCount(stopwatch1, stdBitset1500);
|
||||
TestCount(stopwatch2, eaBitset1500);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<1500>/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test >>=
|
||||
///////////////////////////////
|
||||
|
||||
TestRightShift(stopwatch1, stdBitset15, 1);
|
||||
TestRightShift(stopwatch2, eaBitset15, 1);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<15>/>>=/1", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),
|
||||
GetStdSTLType() == kSTLPort ? "STLPort is broken, neglects wraparound check." : NULL);
|
||||
|
||||
TestRightShift(stopwatch1, stdBitset35, 1);
|
||||
TestRightShift(stopwatch2, eaBitset35, 1);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<35>/>>=/1", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),
|
||||
GetStdSTLType() == kSTLPort ? "STLPort is broken, neglects wraparound check." : NULL);
|
||||
|
||||
TestRightShift(stopwatch1, stdBitset75, 1);
|
||||
TestRightShift(stopwatch2, eaBitset75, 1);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<75>/>>=/1", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),
|
||||
GetStdSTLType() == kSTLPort ? "STLPort is broken, neglects wraparound check." : NULL);
|
||||
|
||||
TestRightShift(stopwatch1, stdBitset1500, 1);
|
||||
TestRightShift(stopwatch2, eaBitset1500, 1);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("bitset<1500>/>>=/1", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),
|
||||
GetStdSTLType() == kSTLPort ? "STLPort is broken, neglects wraparound check." : NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,342 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
#include <EASTL/deque.h>
|
||||
#include <EASTL/vector.h>
|
||||
#include <EASTL/sort.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#pragma warning(disable: 4350) // behavior change: X called instead of Y
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
using namespace EA;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ValuePair
|
||||
{
|
||||
uint32_t key;
|
||||
uint32_t v;
|
||||
};
|
||||
|
||||
struct VPCompare
|
||||
{
|
||||
bool operator()(const ValuePair& vp1, const ValuePair& vp2) const
|
||||
{
|
||||
return (vp1.key == vp2.key) ? (vp1.v < vp2.v) : (vp1.key < vp2.key);
|
||||
}
|
||||
};
|
||||
|
||||
bool operator<(const ValuePair& vp1, const ValuePair& vp2)
|
||||
{
|
||||
return (vp1.key == vp2.key) ? (vp1.v < vp2.v) : (vp1.key < vp2.key);
|
||||
}
|
||||
|
||||
bool operator==(const ValuePair& vp1, const ValuePair& vp2)
|
||||
{
|
||||
return (vp1.key == vp2.key) && (vp1.v == vp2.v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EASTL_DECLARE_POD(ValuePair)
|
||||
EASTL_DECLARE_TRIVIAL_CONSTRUCTOR(ValuePair)
|
||||
EASTL_DECLARE_TRIVIAL_COPY(ValuePair)
|
||||
EASTL_DECLARE_TRIVIAL_ASSIGN(ValuePair)
|
||||
EASTL_DECLARE_TRIVIAL_DESTRUCTOR(ValuePair)
|
||||
EASTL_DECLARE_TRIVIAL_RELOCATE(ValuePair)
|
||||
|
||||
|
||||
|
||||
typedef std::deque<ValuePair> StdDeque;
|
||||
typedef eastl::deque<ValuePair, EASTLAllocatorType, 128> EaDeque; // What value do we pick for the subarray size to make the comparison fair? Using the default isn't ideal because it results in this test measuring speed efficiency and ignoring memory efficiency.
|
||||
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Container>
|
||||
void TestPushBack(EA::StdC::Stopwatch& stopwatch, Container& c, eastl::vector<uint32_t>& intVector)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for(eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)
|
||||
{
|
||||
const ValuePair vp = { intVector[j], intVector[j] };
|
||||
c.push_back(vp);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestPushFront(EA::StdC::Stopwatch& stopwatch, Container& c, eastl::vector<uint32_t>& intVector)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for(eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)
|
||||
{
|
||||
const ValuePair vp = { intVector[j], intVector[j] };
|
||||
c.push_front(vp);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
uint64_t temp = 0;
|
||||
stopwatch.Restart();
|
||||
for(typename Container::size_type j = 0, jEnd = c.size(); j < jEnd; j++)
|
||||
temp += c[j].key;
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)(temp & 0xffffffff));
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestIteration(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::iterator it = c.begin(), itEnd = c.end();
|
||||
stopwatch.Restart();
|
||||
while(it != itEnd)
|
||||
++it;
|
||||
stopwatch.Stop();
|
||||
if(it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)(*it).key);
|
||||
|
||||
/* Alternative way to measure:
|
||||
const eastl_size_t n = c.size();
|
||||
stopwatch.Restart();
|
||||
for(eastl_size_t i = 0; i < n; ++i)
|
||||
++it;
|
||||
stopwatch.Stop();
|
||||
if(it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)(*it).key);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestFind(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
// Intentionally use eastl find in order to measure just
|
||||
// vector access speed and not be polluted by sort speed.
|
||||
const ValuePair vp = { 0xffffffff, 0 };
|
||||
stopwatch.Restart();
|
||||
typename Container::iterator it = eastl::find(c.begin(), c.end(), vp);
|
||||
stopwatch.Stop();
|
||||
if(it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)(*it).key);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestSort(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
// Intentionally use eastl sort in order to measure just
|
||||
// vector access speed and not be polluted by sort speed.
|
||||
VPCompare vpCompare;
|
||||
stopwatch.Restart();
|
||||
eastl::quick_sort(c.begin(), c.end(), vpCompare);
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c[0].key);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
const ValuePair vp = { 0xffffffff, 0 };
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
|
||||
stopwatch.Restart();
|
||||
for(j = 0, jEnd = 2000, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
it = c.insert(it, vp);
|
||||
|
||||
if(it == c.end()) // Try to safely increment the iterator three times.
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestErase(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
|
||||
stopwatch.Restart();
|
||||
for(j = 0, jEnd = 2000, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
it = c.erase(it);
|
||||
|
||||
if(it == c.end()) // Try to safely increment the iterator three times.
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
void BenchmarkDeque()
|
||||
{
|
||||
EASTLTest_Printf("Deque\n");
|
||||
|
||||
EA::UnitTest::RandGenT<uint32_t> rng(EA::UnitTest::GetRandSeed());
|
||||
EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
|
||||
{ // Exercise some declarations
|
||||
int nErrorCount = 0;
|
||||
ValuePair vp1 = { 0, 0 }, vp2 = { 0, 0 };
|
||||
VPCompare c1, c2;
|
||||
|
||||
VERIFY(c1.operator()(vp1, vp2) == c2.operator()(vp1, vp2));
|
||||
VERIFY((vp1 < vp2) || (vp1 == vp2) || !(vp1 == vp2));
|
||||
}
|
||||
|
||||
{
|
||||
eastl::vector<uint32_t> intVector(100000);
|
||||
eastl::generate(intVector.begin(), intVector.end(), rng);
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
StdDeque stdDeque;
|
||||
EaDeque eaDeque;
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test push_back
|
||||
///////////////////////////////
|
||||
|
||||
TestPushBack(stopwatch1, stdDeque, intVector);
|
||||
TestPushBack(stopwatch2, eaDeque, intVector);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("deque<ValuePair>/push_back", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test push_front
|
||||
///////////////////////////////
|
||||
|
||||
TestPushFront(stopwatch1, stdDeque, intVector);
|
||||
TestPushFront(stopwatch2, eaDeque, intVector);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("deque<ValuePair>/push_front", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test operator[]
|
||||
///////////////////////////////
|
||||
|
||||
TestBracket(stopwatch1, stdDeque);
|
||||
TestBracket(stopwatch2, eaDeque);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("deque<ValuePair>/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test iteration
|
||||
///////////////////////////////
|
||||
|
||||
TestIteration(stopwatch1, stdDeque);
|
||||
TestIteration(stopwatch2, eaDeque);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("deque<ValuePair>/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test find()
|
||||
///////////////////////////////
|
||||
|
||||
TestFind(stopwatch1, stdDeque);
|
||||
TestFind(stopwatch2, eaDeque);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("deque<ValuePair>/find", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test sort
|
||||
///////////////////////////////
|
||||
|
||||
// Currently VC++ complains about our sort function decrementing std::iterator that is already at begin(). In the strictest sense,
|
||||
// that's a valid complaint, but we aren't testing std STL here. We will want to revise our sort function eventually.
|
||||
#if !defined(_MSC_VER) || !defined(_ITERATOR_DEBUG_LEVEL) || (_ITERATOR_DEBUG_LEVEL < 2)
|
||||
TestSort(stopwatch1, stdDeque);
|
||||
TestSort(stopwatch2, eaDeque);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("deque<ValuePair>/sort", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test insert
|
||||
///////////////////////////////
|
||||
|
||||
TestInsert(stopwatch1, stdDeque);
|
||||
TestInsert(stopwatch2, eaDeque);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("deque<ValuePair>/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase
|
||||
///////////////////////////////
|
||||
|
||||
TestErase(stopwatch1, stdDeque);
|
||||
TestErase(stopwatch2, eaDeque);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("deque<ValuePair>/erase", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,469 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <EASTL/vector.h>
|
||||
#include <EASTL/hash_map.h>
|
||||
#include <EASTL/string.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
|
||||
|
||||
|
||||
EA_DISABLE_ALL_VC_WARNINGS()
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
EA_RESTORE_ALL_VC_WARNINGS()
|
||||
|
||||
|
||||
|
||||
using namespace EA;
|
||||
|
||||
|
||||
// HashString8
|
||||
//
|
||||
// We define a string
|
||||
//
|
||||
template <typename String>
|
||||
struct HashString8
|
||||
{
|
||||
// Defined for EASTL, STLPort, SGI, etc. and Metrowerks-related hash tables:
|
||||
size_t operator()(const String& s) const
|
||||
{
|
||||
const uint8_t* p = (const uint8_t*) s.c_str();
|
||||
uint32_t c, stringHash = UINT32_C(2166136261);
|
||||
while((c = *p++) != 0)
|
||||
stringHash = (stringHash * 16777619) ^ c;
|
||||
return stringHash;
|
||||
}
|
||||
|
||||
// Defined for Dinkumware-related (e.g. MS STL) hash tables:
|
||||
bool operator()(const String& s1, const String& s2) const
|
||||
{
|
||||
return s1 < s2;
|
||||
}
|
||||
|
||||
// Defined for Dinkumware-related (e.g. MS STL) hash tables:
|
||||
enum {
|
||||
bucket_size = 7,
|
||||
min_buckets = 8
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
using StdMapUint32TO = std::unordered_map<uint32_t, TestObject>;
|
||||
using StdMapStrUint32 = std::unordered_map<std::string, uint32_t, HashString8<std::string>>;
|
||||
|
||||
using EaMapUint32TO = eastl::hash_map<uint32_t, TestObject>;
|
||||
using EaMapStrUint32 = eastl::hash_map<eastl::string, uint32_t, HashString8<eastl::string>>;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Container, typename Value>
|
||||
void TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
c.insert(pArrayBegin, pArrayEnd);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestIteration(EA::StdC::Stopwatch& stopwatch, const Container& c, const Value& findValue)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
typename Container::const_iterator it = eastl::find(c.begin(), c.end(), findValue); // It shouldn't matter what find implementation we use here, as it merely iterates values.
|
||||
stopwatch.Stop();
|
||||
if(it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%p", &*it);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
Benchmark::DoNothing(&c[pArrayBegin->first]);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestFind(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
typename Container::iterator it = c.find(pArrayBegin->first);
|
||||
Benchmark::DoNothing(&it);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestFindAsStd(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
typename Container::iterator it = c.find(pArrayBegin->first.c_str());
|
||||
Benchmark::DoNothing(&it);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestFindAsEa(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
typename Container::iterator it = c.find_as(pArrayBegin->first.c_str());
|
||||
Benchmark::DoNothing(&it);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestCount(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
typename Container::size_type temp = 0;
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
temp += c.count(pArrayBegin->first);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)temp);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestEraseValue(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
c.erase(pArrayBegin->first);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestErasePosition(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
|
||||
stopwatch.Restart();
|
||||
for(j = 0, jEnd = c.size() / 3, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
// The erase fucntion is supposed to return an iterator, but the C++ standard was
|
||||
// not initially clear about it and some STL implementations don't do it correctly.
|
||||
#if (defined(_MSC_VER) || defined(_CPPLIB_VER)) // _CPPLIB_VER is something defined by Dinkumware STL.
|
||||
it = c.erase(it);
|
||||
#else
|
||||
// This pathway may execute at a slightly different speed than the
|
||||
// standard behaviour, but that's fine for the benchmark because the
|
||||
// benchmark is measuring the speed of erasing while iterating, and
|
||||
// however it needs to get done by the given STL is how it is measured.
|
||||
const typename Container::iterator itErase(it++);
|
||||
c.erase(itErase);
|
||||
#endif
|
||||
|
||||
++it;
|
||||
++it;
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%p %p", &c, &it);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestEraseRange(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it1 = c.begin();
|
||||
typename Container::iterator it2 = c.begin();
|
||||
|
||||
for(j = 0, jEnd = c.size() / 3; j < jEnd; ++j)
|
||||
++it2;
|
||||
|
||||
stopwatch.Restart();
|
||||
c.erase(it1, it2);
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%p %p %p", &c, &it1, &it2);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestClear(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
c.clear();
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
void BenchmarkHash()
|
||||
{
|
||||
EASTLTest_Printf("HashMap\n");
|
||||
|
||||
EA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());
|
||||
EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
|
||||
{
|
||||
eastl::vector< std::pair<uint32_t, TestObject> > stdVectorUT(10000);
|
||||
eastl::vector< eastl::pair<uint32_t, TestObject> > eaVectorUT(10000);
|
||||
|
||||
eastl::vector< std::pair< std::string, uint32_t> > stdVectorSU(10000);
|
||||
eastl::vector< eastl::pair<eastl::string, uint32_t> > eaVectorSU(10000);
|
||||
|
||||
for(eastl_size_t i = 0, iEnd = stdVectorUT.size(); i < iEnd; i++)
|
||||
{
|
||||
const uint32_t n1 = rng.RandLimit((uint32_t)(iEnd / 2));
|
||||
const uint32_t n2 = rng.RandValue();
|
||||
|
||||
stdVectorUT[i] = std::pair<uint32_t, TestObject>(n1, TestObject(n2));
|
||||
eaVectorUT[i] = eastl::pair<uint32_t, TestObject>(n1, TestObject(n2));
|
||||
|
||||
char str_n1[32];
|
||||
sprintf(str_n1, "%u", (unsigned)n1);
|
||||
|
||||
stdVectorSU[i] = std::pair< std::string, uint32_t>( std::string(str_n1), n2);
|
||||
eaVectorSU[i] = eastl::pair<eastl::string, uint32_t>(eastl::string(str_n1), n2);
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
StdMapUint32TO stdMapUint32TO;
|
||||
EaMapUint32TO eaMapUint32TO;
|
||||
|
||||
StdMapStrUint32 stdMapStrUint32;
|
||||
EaMapStrUint32 eaMapStrUint32;
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test insert(const value_type&)
|
||||
///////////////////////////////
|
||||
|
||||
TestInsert(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size());
|
||||
TestInsert(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<uint32_t, TestObject>/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestInsert(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());
|
||||
TestInsert(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<string, uint32_t>/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test iteration
|
||||
///////////////////////////////
|
||||
|
||||
TestIteration(stopwatch1, stdMapUint32TO, StdMapUint32TO::value_type(9999999, TestObject(9999999)));
|
||||
TestIteration(stopwatch2, eaMapUint32TO, EaMapUint32TO::value_type(9999999, TestObject(9999999)));
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<uint32_t, TestObject>/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestIteration(stopwatch1, stdMapStrUint32, StdMapStrUint32::value_type( std::string("9999999"), 9999999));
|
||||
TestIteration(stopwatch2, eaMapStrUint32, EaMapStrUint32::value_type(eastl::string("9999999"), 9999999));
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<string, uint32_t>/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test operator[]
|
||||
///////////////////////////////
|
||||
|
||||
TestBracket(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size());
|
||||
TestBracket(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<uint32_t, TestObject>/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestBracket(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());
|
||||
TestBracket(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<string, uint32_t>/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test find
|
||||
///////////////////////////////
|
||||
|
||||
TestFind(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size());
|
||||
TestFind(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<uint32_t, TestObject>/find", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestFind(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());
|
||||
TestFind(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<string, uint32_t>/find", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test find_as
|
||||
///////////////////////////////
|
||||
|
||||
TestFindAsStd(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());
|
||||
TestFindAsEa(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<string, uint32_t>/find_as/char*", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test count
|
||||
///////////////////////////////
|
||||
|
||||
TestCount(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size());
|
||||
TestCount(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<uint32_t, TestObject>/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestCount(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());
|
||||
TestCount(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<string, uint32_t>/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase(const key_type& key)
|
||||
///////////////////////////////
|
||||
|
||||
TestEraseValue(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + (stdVectorUT.size() / 2));
|
||||
TestEraseValue(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + (eaVectorUT.size() / 2));
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<uint32_t, TestObject>/erase val", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestEraseValue(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + (stdVectorSU.size() / 2));
|
||||
TestEraseValue(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + (eaVectorSU.size() / 2));
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<string, uint32_t>/erase val", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase(iterator position)
|
||||
///////////////////////////////
|
||||
|
||||
TestErasePosition(stopwatch1, stdMapUint32TO);
|
||||
TestErasePosition(stopwatch2, eaMapUint32TO);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<uint32_t, TestObject>/erase pos", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestErasePosition(stopwatch1, stdMapStrUint32);
|
||||
TestErasePosition(stopwatch2, eaMapStrUint32);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<string, uint32_t>/erase pos", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase(iterator first, iterator last)
|
||||
///////////////////////////////
|
||||
|
||||
TestEraseRange(stopwatch1, stdMapUint32TO);
|
||||
TestEraseRange(stopwatch2, eaMapUint32TO);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<uint32_t, TestObject>/erase range", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestEraseRange(stopwatch1, stdMapStrUint32);
|
||||
TestEraseRange(stopwatch2, eaMapStrUint32);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<string, uint32_t>/erase range", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test clear()
|
||||
///////////////////////////////
|
||||
|
||||
// Clear the containers of whatever they happen to have. We want the containers to have full data.
|
||||
TestClear(stopwatch1, stdMapUint32TO);
|
||||
TestClear(stopwatch2, eaMapUint32TO);
|
||||
TestClear(stopwatch1, stdMapStrUint32);
|
||||
TestClear(stopwatch2, eaMapStrUint32);
|
||||
|
||||
// Re-set the containers with full data.
|
||||
TestInsert(stopwatch1, stdMapUint32TO, stdVectorUT.data(), stdVectorUT.data() + stdVectorUT.size());
|
||||
TestInsert(stopwatch2, eaMapUint32TO, eaVectorUT.data(), eaVectorUT.data() + eaVectorUT.size());
|
||||
TestInsert(stopwatch1, stdMapStrUint32, stdVectorSU.data(), stdVectorSU.data() + stdVectorSU.size());
|
||||
TestInsert(stopwatch2, eaMapStrUint32, eaVectorSU.data(), eaVectorSU.data() + eaVectorSU.size());
|
||||
|
||||
// Now clear the data again, this time measuring it.
|
||||
TestClear(stopwatch1, stdMapUint32TO);
|
||||
TestClear(stopwatch2, eaMapUint32TO);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<uint32_t, TestObject>/clear", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestClear(stopwatch1, stdMapStrUint32);
|
||||
TestClear(stopwatch2, eaMapStrUint32);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("hash_map<string, uint32_t>/clear", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <EASTL/heap.h>
|
||||
#include <EASTL/vector.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#pragma warning(disable: 4350) // behavior change: X called instead of Y
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
using namespace EA;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Iterator>
|
||||
void TestMakeHeapStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
std::make_heap(first, last);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void TestMakeHeapEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
eastl::make_heap(first, last);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
void TestPushHeapStd(EA::StdC::Stopwatch& stopwatch, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(first2 != last2)
|
||||
{
|
||||
*last1++ = *first2++;
|
||||
std::push_heap(first1, last1);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
template <typename Iterator1, typename Iterator2>
|
||||
void TestPushHeapEa(EA::StdC::Stopwatch& stopwatch, Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(first2 != last2)
|
||||
{
|
||||
*last1++ = *first2++;
|
||||
eastl::push_heap(first1, last1);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename Iterator>
|
||||
void TestPopHeapStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last, Iterator popEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(last != popEnd)
|
||||
std::pop_heap(first, last--);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void TestPopHeapEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last, Iterator popEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(last != popEnd)
|
||||
eastl::pop_heap(first, last--);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename Iterator>
|
||||
void TestSortHeapStd(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
std::sort_heap(first, last);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void TestSortHeapEa(EA::StdC::Stopwatch& stopwatch, Iterator first, Iterator last)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
eastl::sort_heap(first, last);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
void BenchmarkHeap()
|
||||
{
|
||||
EASTLTest_Printf("Heap (Priority Queue)\n");
|
||||
|
||||
EA::UnitTest::RandGenT<uint32_t> rng(EA::UnitTest::GetRandSeed());
|
||||
EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
|
||||
{
|
||||
const int kArraySize = 100000;
|
||||
|
||||
// uint32[]
|
||||
uint32_t* const pIntArrayS = new uint32_t[kArraySize * 2]; // * 2 because we will be adding more items via push_heap.
|
||||
uint32_t* const pIntArrayE = new uint32_t[kArraySize * 2]; // S means Std; E means EA.
|
||||
uint32_t* const pIntArray2 = new uint32_t[kArraySize]; // This will be used for pop_heap.
|
||||
|
||||
eastl::generate(pIntArrayS, pIntArrayS + kArraySize, rng);
|
||||
eastl::copy(pIntArrayS, pIntArrayS + kArraySize, pIntArrayE);
|
||||
eastl::copy(pIntArrayS, pIntArrayS + kArraySize, pIntArray2);
|
||||
|
||||
|
||||
// vector<TestObject>
|
||||
std::vector<TestObject> stdVectorTO(kArraySize * 2);
|
||||
std::vector<TestObject> stdVectorTO2(kArraySize);
|
||||
eastl::vector<TestObject> eaVectorTO(kArraySize * 2);
|
||||
eastl::vector<TestObject> eaVectorTO2(kArraySize);
|
||||
|
||||
for(int k = 0; k < kArraySize; k++)
|
||||
{
|
||||
stdVectorTO[k] = TestObject(pIntArrayS[k]);
|
||||
stdVectorTO2[k] = TestObject(pIntArrayS[k]);
|
||||
eaVectorTO[k] = TestObject(pIntArrayS[k]);
|
||||
eaVectorTO2[k] = TestObject(pIntArrayS[k]);
|
||||
}
|
||||
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
///////////////////////////////
|
||||
// Test make_heap
|
||||
///////////////////////////////
|
||||
|
||||
TestMakeHeapStd(stopwatch1, pIntArrayS, pIntArrayS + kArraySize);
|
||||
TestMakeHeapEa (stopwatch2, pIntArrayE, pIntArrayE + kArraySize);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("heap (uint32_t[])/make_heap", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestMakeHeapStd(stopwatch1, stdVectorTO.begin(), stdVectorTO.begin() + kArraySize);
|
||||
TestMakeHeapEa (stopwatch2, eaVectorTO.begin(), eaVectorTO.begin() + kArraySize);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("heap (vector<TestObject>)/make_heap", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test push_heap
|
||||
///////////////////////////////
|
||||
|
||||
TestPushHeapStd(stopwatch1, pIntArrayS, pIntArrayS + kArraySize, pIntArray2, pIntArray2 + kArraySize);
|
||||
TestPushHeapEa (stopwatch2, pIntArrayE, pIntArrayE + kArraySize, pIntArray2, pIntArray2 + kArraySize);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("heap (uint32_t[])/push_heap", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestPushHeapStd(stopwatch1, stdVectorTO.begin(), stdVectorTO.begin() + kArraySize, stdVectorTO2.begin(), stdVectorTO2.begin() + kArraySize);
|
||||
TestPushHeapEa (stopwatch2, eaVectorTO.begin(), eaVectorTO.begin() + kArraySize, eaVectorTO2.begin(), eaVectorTO2.begin() + kArraySize);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("heap (vector<TestObject>)/push_heap", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test pop_heap
|
||||
///////////////////////////////
|
||||
|
||||
TestPopHeapStd(stopwatch1, pIntArrayS, pIntArrayS + (kArraySize * 2), pIntArrayS + kArraySize); // * 2 because we used push_heap above to add more items.
|
||||
TestPopHeapEa (stopwatch2, pIntArrayE, pIntArrayE + (kArraySize * 2), pIntArrayE + kArraySize);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("heap (uint32_t[])/pop_heap", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestPopHeapStd(stopwatch1, stdVectorTO.begin(), stdVectorTO.begin() + (kArraySize * 2), stdVectorTO.begin() + kArraySize); // * 2 because we used push_heap above to add more items.
|
||||
TestPopHeapEa (stopwatch2, eaVectorTO.begin(), eaVectorTO.begin() + (kArraySize * 2), eaVectorTO.begin() + kArraySize);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("heap (vector<TestObject>)/pop_heap", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test sort_heap
|
||||
///////////////////////////////
|
||||
|
||||
TestSortHeapStd(stopwatch1, pIntArrayS, pIntArrayS + kArraySize);
|
||||
TestSortHeapEa (stopwatch2, pIntArrayE, pIntArrayE + kArraySize);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("heap (uint32_t[])/sort_heap", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestSortHeapStd(stopwatch1, stdVectorTO.begin(), stdVectorTO.begin() + kArraySize);
|
||||
TestSortHeapEa (stopwatch2, eaVectorTO.begin(), eaVectorTO.begin() + kArraySize);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("heap (vector<TestObject>)/sort_heap", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
}
|
||||
|
||||
delete[] pIntArrayS;
|
||||
delete[] pIntArrayE;
|
||||
delete[] pIntArray2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <EASTL/list.h>
|
||||
#include <EASTL/vector.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
#include <EASTL/random.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#pragma warning(disable: 4555) // expression has no effect; expected expression with side-effect
|
||||
#pragma warning(disable: 4350) // behavior change: X called instead of Y
|
||||
#endif
|
||||
#include <list>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
using namespace EA;
|
||||
using namespace eastl;
|
||||
|
||||
|
||||
|
||||
typedef std::list<TestObject> StdListTO;
|
||||
typedef eastl::list<TestObject> EaListTO;
|
||||
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
void DoNothing(void*)
|
||||
{
|
||||
// Empty
|
||||
}
|
||||
|
||||
|
||||
template <typename ContainerSource, typename Container>
|
||||
void TestCtorIterator(EA::StdC::Stopwatch& stopwatch, const ContainerSource& cs, Container*) // Dummy Container argument because of GCC 2.X limitations.
|
||||
{
|
||||
stopwatch.Restart();
|
||||
Container c(cs.begin(), cs.end());
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.back().mX);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestCtorN(EA::StdC::Stopwatch& stopwatch, Container*) // Dummy Container argument because of GCC 2.X limitations.
|
||||
{
|
||||
stopwatch.Restart();
|
||||
Container c(10000);
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.back().mX);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestPushBack(EA::StdC::Stopwatch& stopwatch, Container& c, const TestObject* pTOBegin, const TestObject* const pTOEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pTOBegin != pTOEnd)
|
||||
c.push_back(*pTOBegin++);
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.back().mX);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c, const TestObject* pTOBegin, const TestObject* const pTOEnd)
|
||||
{
|
||||
typename Container::iterator it = c.begin();
|
||||
stopwatch.Restart();
|
||||
while(pTOBegin != pTOEnd)
|
||||
{
|
||||
it = c.insert(it, *pTOBegin++);
|
||||
|
||||
if(++it == c.end()) // Try to safely increment the iterator a couple times
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.back().mX);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestSize(EA::StdC::Stopwatch& stopwatch, Container& c, void (*pFunction)(...))
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for(int i = 0; (i < 10000) && c.size(); i++)
|
||||
(*pFunction)(&c);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestFind(EA::StdC::Stopwatch& stopwatch, Container& c, const TestObject& to)
|
||||
{
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
stopwatch.Restart();
|
||||
typename Container::iterator it = eastl::find(c.begin(), c.end(), to);
|
||||
stopwatch.Stop();
|
||||
if(it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%d", (*it).mX);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestReverse(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
stopwatch.Restart();
|
||||
c.reverse();
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.back().mX);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestRemove(EA::StdC::Stopwatch& stopwatch, Container& c, const TestObject* pTOBegin, const TestObject* const pTOEnd)
|
||||
{
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
stopwatch.Restart();
|
||||
while(pTOBegin != pTOEnd)
|
||||
c.remove(*pTOBegin++);
|
||||
stopwatch.Stop();
|
||||
if(!c.empty())
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.back().mX);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestSplice(EA::StdC::Stopwatch& stopwatch, Container& c, Container& cSource)
|
||||
{
|
||||
typename Container::iterator it = c.begin();
|
||||
int i = 0, iEnd = (int)cSource.size() - 5;
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
stopwatch.Restart();
|
||||
while(i++ != iEnd)
|
||||
c.splice(it, cSource, cSource.begin());
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.back().mX);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestErase(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::iterator it = c.begin();
|
||||
int i = 0, iEnd = (int)c.size() - 5;
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
stopwatch.Restart();
|
||||
while(i++ != iEnd)
|
||||
{
|
||||
it = c.erase(it);
|
||||
|
||||
if(it == c.end()) // Try to safely increment the iterator a couple times
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.back().mX);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
|
||||
void BenchmarkList()
|
||||
{
|
||||
EASTLTest_Printf("List\n");
|
||||
|
||||
EASTLTest_Rand rng(EA::UnitTest::GetRandSeed());
|
||||
EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
|
||||
EaListTO eaListTO_1(1);
|
||||
EaListTO eaListTO_10(10);
|
||||
EaListTO eaListTO_100(100);
|
||||
StdListTO stdListTO_1(1);
|
||||
StdListTO stdListTO_10(10);
|
||||
StdListTO stdListTO_100(100);
|
||||
|
||||
{
|
||||
char buffer[32];
|
||||
sprintf(buffer, "%p", &DoNothing);
|
||||
}
|
||||
|
||||
{
|
||||
eastl::vector<TestObject> toVector(100000);
|
||||
for(eastl_size_t i = 0, iEnd = toVector.size(); i < iEnd; ++i)
|
||||
toVector[i] = TestObject((int)i);
|
||||
random_shuffle(toVector.begin(), toVector.end(), rng);
|
||||
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
StdListTO stdListTO;
|
||||
EaListTO eaListTO;
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test list(InputIterator first, InputIterator last)
|
||||
///////////////////////////////
|
||||
|
||||
TestCtorIterator(stopwatch1, toVector, &stdListTO);
|
||||
TestCtorIterator(stopwatch2, toVector, &eaListTO);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/ctor(it)", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test list(size_type n)
|
||||
///////////////////////////////
|
||||
|
||||
TestCtorN(stopwatch1, &stdListTO);
|
||||
TestCtorN(stopwatch2, &eaListTO);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/ctor(n)", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test push_back()
|
||||
///////////////////////////////
|
||||
|
||||
TestPushBack(stopwatch1, stdListTO, toVector.data(), toVector.data() + toVector.size());
|
||||
TestPushBack(stopwatch2, eaListTO, toVector.data(), toVector.data() + toVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/push_back", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test insert()
|
||||
///////////////////////////////
|
||||
|
||||
TestInsert(stopwatch1, stdListTO, toVector.data(), toVector.data() + toVector.size());
|
||||
TestInsert(stopwatch2, eaListTO, toVector.data(), toVector.data() + toVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test size()
|
||||
///////////////////////////////
|
||||
|
||||
TestSize(stopwatch1, stdListTO_1, Benchmark::DoNothing);
|
||||
TestSize(stopwatch2, eaListTO_1, Benchmark::DoNothing);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/size/1", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
TestSize(stopwatch1, stdListTO_10, Benchmark::DoNothing);
|
||||
TestSize(stopwatch2, eaListTO_10, Benchmark::DoNothing);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/size/10", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()
|
||||
#if !EASTL_LIST_SIZE_CACHE
|
||||
, "EASTL is configured to not cache the list size."
|
||||
#endif
|
||||
);
|
||||
|
||||
TestSize(stopwatch1, stdListTO_100, Benchmark::DoNothing);
|
||||
TestSize(stopwatch2, eaListTO_100, Benchmark::DoNothing);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/size/100", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime()
|
||||
#if !EASTL_LIST_SIZE_CACHE
|
||||
, "EASTL is configured to not cache the list size."
|
||||
#endif
|
||||
);
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test find()
|
||||
///////////////////////////////
|
||||
|
||||
TestFind(stopwatch1, stdListTO, TestObject(99999999));
|
||||
TestFind(stopwatch2, eaListTO, TestObject(99999999));
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/find", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test reverse()
|
||||
///////////////////////////////
|
||||
|
||||
TestReverse(stopwatch1, stdListTO);
|
||||
TestReverse(stopwatch2, eaListTO);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/reverse", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test remove()
|
||||
///////////////////////////////
|
||||
|
||||
random_shuffle(toVector.begin(), toVector.end(), rng);
|
||||
TestRemove(stopwatch1, stdListTO, &toVector[0], &toVector[20]);
|
||||
TestRemove(stopwatch2, eaListTO, &toVector[0], &toVector[20]);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/remove", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test splice()
|
||||
///////////////////////////////
|
||||
StdListTO listCopyStd(stdListTO);
|
||||
EaListTO listCopyEa(eaListTO);
|
||||
|
||||
TestSplice(stopwatch1, stdListTO, listCopyStd);
|
||||
TestSplice(stopwatch2, eaListTO, listCopyEa);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/splice", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase()
|
||||
///////////////////////////////
|
||||
|
||||
TestErase(stopwatch1, stdListTO);
|
||||
TestErase(stopwatch2, eaListTO);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("list<TestObject>/erase", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,382 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <EASTL/map.h>
|
||||
#include <EASTL/vector.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
|
||||
EA_DISABLE_ALL_VC_WARNINGS()
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
EA_RESTORE_ALL_VC_WARNINGS()
|
||||
|
||||
|
||||
using namespace EA;
|
||||
|
||||
|
||||
typedef std::map<TestObject, uint32_t> StdMapTOUint32;
|
||||
typedef eastl::map<TestObject, uint32_t> EaMapTOUint32;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Container, typename Value>
|
||||
void TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd, const Value& highValue)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
c.insert(pArrayBegin, pArrayEnd);
|
||||
stopwatch.Stop();
|
||||
c.insert(highValue);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestIteration(EA::StdC::Stopwatch& stopwatch, const Container& c, const Value& findValue)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
typename Container::const_iterator it = eastl::find(c.begin(), c.end(), findValue); // It shouldn't matter what find implementation we use here, as it merely iterates values.
|
||||
stopwatch.Stop();
|
||||
if(it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%p", &*it);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
Benchmark::DoNothing(c[pArrayBegin->first]);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestFind(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
Benchmark::DoNothing(c.find(pArrayBegin->first)->second);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestCount(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
typename Container::size_type temp = 0;
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
temp += c.count(pArrayBegin->first);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)temp);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestLowerBound(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
Benchmark::DoNothing(c.lower_bound(pArrayBegin->first)->second);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestUpperBound(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
Benchmark::DoNothing(c.upper_bound(pArrayBegin->first)->second);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestEqualRange(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
Benchmark::DoNothing(c.equal_range(pArrayBegin->first).second->second);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container, typename Value>
|
||||
void TestEraseValue(EA::StdC::Stopwatch& stopwatch, Container& c, const Value* pArrayBegin, const Value* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
c.erase(pArrayBegin->first);
|
||||
++pArrayBegin;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestErasePosition(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
|
||||
stopwatch.Restart();
|
||||
for(j = 0, jEnd = c.size() / 3, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
// The erase fucntion is supposed to return an iterator, but the C++ standard was
|
||||
// not initially clear about it and some STL implementations don't do it correctly.
|
||||
#if (((defined(_MSC_VER) || defined(_CPPLIB_VER)) && !defined(_HAS_STRICT_CONFORMANCE))) // _CPPLIB_VER is something defined by Dinkumware STL.
|
||||
it = c.erase(it); // Standard behavior.
|
||||
#else
|
||||
// This pathway may execute at a slightly different speed than the
|
||||
// standard behaviour, but that's fine for the benchmark because the
|
||||
// benchmark is measuring the speed of erasing while iterating, and
|
||||
// however it needs to get done by the given STL is how it is measured.
|
||||
const typename Container::iterator itErase(it++);
|
||||
c.erase(itErase);
|
||||
#endif
|
||||
|
||||
++it;
|
||||
++it;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%p %p", &c, &it);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestEraseRange(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it1 = c.begin();
|
||||
typename Container::iterator it2 = c.begin();
|
||||
|
||||
for(j = 0, jEnd = c.size() / 3; j < jEnd; ++j)
|
||||
++it2;
|
||||
|
||||
stopwatch.Restart();
|
||||
c.erase(it1, it2);
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%p %p %p", &c, &it1, &it2);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestClear(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
c.clear();
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
void BenchmarkMap()
|
||||
{
|
||||
EASTLTest_Printf("Map\n");
|
||||
|
||||
EA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());
|
||||
EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
|
||||
{
|
||||
eastl::vector< std::pair<TestObject, uint32_t> > stdVector(10000);
|
||||
eastl::vector< eastl::pair<TestObject, uint32_t> > eaVector(10000);
|
||||
|
||||
for(eastl_size_t i = 0, iEnd = stdVector.size(); i < iEnd; i++)
|
||||
{
|
||||
const uint32_t n1 = rng.RandLimit(((uint32_t)iEnd / 2));
|
||||
const uint32_t n2 = rng.RandValue();
|
||||
|
||||
stdVector[i] = std::pair<TestObject, uint32_t>(TestObject(n1), n2);
|
||||
eaVector[i] = eastl::pair<TestObject, uint32_t>(TestObject(n1), n2);
|
||||
}
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
StdMapTOUint32 stdMapTOUint32;
|
||||
EaMapTOUint32 eaMapTOUint32;
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test insert(const value_type&)
|
||||
///////////////////////////////
|
||||
const std::pair<TestObject, uint32_t> stdHighValue(TestObject(0x7fffffff), 0x7fffffff);
|
||||
const eastl::pair<TestObject, uint32_t> eaHighValue(TestObject(0x7fffffff), 0x7fffffff);
|
||||
|
||||
TestInsert(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size(), stdHighValue);
|
||||
TestInsert(stopwatch2, eaMapTOUint32, eaVector.data(), eaVector.data() + eaVector.size(), eaHighValue);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test iteration
|
||||
///////////////////////////////
|
||||
|
||||
TestIteration(stopwatch1, stdMapTOUint32, StdMapTOUint32::value_type(TestObject(9999999), 9999999));
|
||||
TestIteration(stopwatch2, eaMapTOUint32, EaMapTOUint32::value_type(TestObject(9999999), 9999999));
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test operator[]
|
||||
///////////////////////////////
|
||||
|
||||
TestBracket(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());
|
||||
TestBracket(stopwatch2, eaMapTOUint32, eaVector.data(), eaVector.data() + eaVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test find
|
||||
///////////////////////////////
|
||||
|
||||
TestFind(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());
|
||||
TestFind(stopwatch2, eaMapTOUint32, eaVector.data(), eaVector.data() + eaVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/find", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test count
|
||||
///////////////////////////////
|
||||
|
||||
TestCount(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());
|
||||
TestCount(stopwatch2, eaMapTOUint32, eaVector.data(), eaVector.data() + eaVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test lower_bound
|
||||
///////////////////////////////
|
||||
|
||||
TestLowerBound(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());
|
||||
TestLowerBound(stopwatch2, eaMapTOUint32, eaVector.data(), eaVector.data() + eaVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/lower_bound", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test upper_bound
|
||||
///////////////////////////////
|
||||
|
||||
TestUpperBound(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());
|
||||
TestUpperBound(stopwatch2, eaMapTOUint32, eaVector.data(), eaVector.data() + eaVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/upper_bound", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test equal_range
|
||||
///////////////////////////////
|
||||
|
||||
TestEqualRange(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + stdVector.size());
|
||||
TestEqualRange(stopwatch2, eaMapTOUint32, eaVector.data(), eaVector.data() + eaVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/equal_range", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase(const key_type& key)
|
||||
///////////////////////////////
|
||||
|
||||
TestEraseValue(stopwatch1, stdMapTOUint32, stdVector.data(), stdVector.data() + (stdVector.size() / 2));
|
||||
TestEraseValue(stopwatch2, eaMapTOUint32, eaVector.data(), eaVector.data() + (eaVector.size() / 2));
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/erase/key", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase(iterator position)
|
||||
///////////////////////////////
|
||||
|
||||
TestErasePosition(stopwatch1, stdMapTOUint32);
|
||||
TestErasePosition(stopwatch2, eaMapTOUint32);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/erase/pos", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),
|
||||
GetStdSTLType() == kSTLMS ? "MS uses a code bloating implementation of erase." : NULL);
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase(iterator first, iterator last)
|
||||
///////////////////////////////
|
||||
|
||||
TestEraseRange(stopwatch1, stdMapTOUint32);
|
||||
TestEraseRange(stopwatch2, eaMapTOUint32);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/erase/range", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test clear()
|
||||
///////////////////////////////
|
||||
|
||||
TestClear(stopwatch1, stdMapTOUint32);
|
||||
TestClear(stopwatch2, eaMapTOUint32);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("map<TestObject, uint32_t>/clear", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <EASTL/set.h>
|
||||
#include <EASTL/vector.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
|
||||
EA_DISABLE_ALL_VC_WARNINGS()
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
EA_RESTORE_ALL_VC_WARNINGS()
|
||||
|
||||
|
||||
using namespace EA;
|
||||
|
||||
|
||||
typedef std::set<uint32_t> StdSetUint32;
|
||||
typedef eastl::set<uint32_t> EaSetUint32;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Container>
|
||||
void TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
c.insert(pArrayBegin, pArrayEnd);
|
||||
stopwatch.Stop();
|
||||
|
||||
// Intentionally push back a high uint32_t value. We do this so that
|
||||
// later upper_bound, lower_bound and equal_range never return end().
|
||||
c.insert(0xffffffff);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestIteration(EA::StdC::Stopwatch& stopwatch, const Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
typename Container::const_iterator it = eastl::find(c.begin(), c.end(), uint32_t(9999999));
|
||||
stopwatch.Stop();
|
||||
if(it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)*it);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestFind(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)
|
||||
{
|
||||
uint32_t temp = 0;
|
||||
typename Container::iterator it;
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
it = c.find(*pArrayBegin++);
|
||||
temp += *it;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)temp);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestCount(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)
|
||||
{
|
||||
typename Container::size_type temp = 0;
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
temp += c.count(*pArrayBegin++);
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)temp);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestLowerBound(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)
|
||||
{
|
||||
uint32_t temp = 0;
|
||||
typename Container::iterator it;
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
it = c.lower_bound(*pArrayBegin++);
|
||||
temp += *it; // We know that it != end because earlier we inserted 0xffffffff.
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)temp);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestUpperBound(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)
|
||||
{
|
||||
uint32_t temp = 0;
|
||||
typename Container::iterator it;
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
it = c.upper_bound(*pArrayBegin++);
|
||||
temp += *it; // We know that it != end because earlier we inserted 0xffffffff.
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)temp);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestEqualRange(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)
|
||||
{
|
||||
uint32_t temp = 0;
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
{
|
||||
temp += *(c.equal_range(*pArrayBegin++).first); // We know that it != end because earlier we inserted 0xffffffff.
|
||||
}
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)temp);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestEraseValue(EA::StdC::Stopwatch& stopwatch, Container& c, const uint32_t* pArrayBegin, const uint32_t* pArrayEnd)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(pArrayBegin != pArrayEnd)
|
||||
c.erase(*pArrayBegin++);
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestErasePosition(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
|
||||
stopwatch.Restart();
|
||||
for(j = 0, jEnd = c.size() / 3, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
// The erase fucntion is supposed to return an iterator, but the C++ standard was
|
||||
// not initially clear about it and some STL implementations don't do it correctly.
|
||||
#if (((defined(_MSC_VER) || defined(_CPPLIB_VER)) && !defined(_HAS_STRICT_CONFORMANCE))) // _CPPLIB_VER is something defined by Dinkumware STL.
|
||||
it = c.erase(it);
|
||||
#else
|
||||
// This pathway may execute at a slightly different speed than the
|
||||
// standard behaviour, but that's fine for the benchmark because the
|
||||
// benchmark is measuring the speed of erasing while iterating, and
|
||||
// however it needs to get done by the given STL is how it is measured.
|
||||
const typename Container::iterator itErase(it++);
|
||||
c.erase(itErase);
|
||||
#endif
|
||||
|
||||
++it;
|
||||
++it;
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestEraseRange(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it1 = c.begin();
|
||||
typename Container::iterator it2 = c.begin();
|
||||
|
||||
for(j = 0, jEnd = c.size() / 3; j < jEnd; ++j)
|
||||
++it2;
|
||||
|
||||
stopwatch.Restart();
|
||||
c.erase(it1, it2);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestClear(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
c.clear();
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)c.size());
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
void BenchmarkSet()
|
||||
{
|
||||
EASTLTest_Printf("Set\n");
|
||||
|
||||
EA::UnitTest::Rand rng(EA::UnitTest::GetRandSeed());
|
||||
EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
|
||||
{
|
||||
eastl::vector<uint32_t> intVector(10000);
|
||||
for(eastl_size_t i = 0, iEnd = intVector.size(); i < iEnd; i++)
|
||||
intVector[i] = (uint32_t)rng.RandLimit(((uint32_t)iEnd / 2)); // This will result in duplicates and even a few triplicates.
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
StdSetUint32 stdSetUint32;
|
||||
EaSetUint32 eaSetUint32;
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test insert(const value_type&)
|
||||
///////////////////////////////
|
||||
|
||||
TestInsert(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
TestInsert(stopwatch2, eaSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test iteration
|
||||
///////////////////////////////
|
||||
|
||||
TestIteration(stopwatch1, stdSetUint32);
|
||||
TestIteration(stopwatch2, eaSetUint32);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test find
|
||||
///////////////////////////////
|
||||
|
||||
TestFind(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
TestFind(stopwatch2, eaSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/find", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test count
|
||||
///////////////////////////////
|
||||
|
||||
TestCount(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
TestCount(stopwatch2, eaSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/count", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test lower_bound
|
||||
///////////////////////////////
|
||||
|
||||
TestLowerBound(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
TestLowerBound(stopwatch2, eaSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/lower_bound", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test upper_bound
|
||||
///////////////////////////////
|
||||
|
||||
TestUpperBound(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
TestUpperBound(stopwatch2, eaSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/upper_bound", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test equal_range
|
||||
///////////////////////////////
|
||||
|
||||
TestEqualRange(stopwatch1, stdSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
TestEqualRange(stopwatch2, eaSetUint32, intVector.data(), intVector.data() + intVector.size());
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/equal_range", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase(const key_type& key)
|
||||
///////////////////////////////
|
||||
|
||||
TestEraseValue(stopwatch1, stdSetUint32, &intVector[0], &intVector[intVector.size() / 2]);
|
||||
TestEraseValue(stopwatch2, eaSetUint32, &intVector[0], &intVector[intVector.size() / 2]);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/erase/val", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase(iterator position)
|
||||
///////////////////////////////
|
||||
|
||||
TestErasePosition(stopwatch1, stdSetUint32);
|
||||
TestErasePosition(stopwatch2, eaSetUint32);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/erase/pos", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime(),
|
||||
GetStdSTLType() == kSTLMS ? "MS uses a code bloating implementation of erase." : NULL);
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase(iterator first, iterator last)
|
||||
///////////////////////////////
|
||||
|
||||
TestEraseRange(stopwatch1, stdSetUint32);
|
||||
TestEraseRange(stopwatch2, eaSetUint32);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/erase range", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test clear()
|
||||
///////////////////////////////
|
||||
|
||||
TestClear(stopwatch1, stdSetUint32);
|
||||
TestClear(stopwatch2, eaSetUint32);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("set<uint32_t>/clear", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,667 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
#include <EASTL/bonus/tuple_vector.h>
|
||||
#include <EASTL/sort.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#pragma warning(disable: 4350)
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
using namespace EA;
|
||||
|
||||
|
||||
typedef std::vector<uint64_t> StdVectorUint64;
|
||||
typedef eastl::tuple_vector<uint64_t> EaTupleVectorUint64;
|
||||
|
||||
struct PaddingStruct
|
||||
{
|
||||
char padding[56] = { 0 };
|
||||
};
|
||||
static const PaddingStruct DefaultPadding;
|
||||
typedef eastl::tuple<uint64_t, PaddingStruct> PaddedTuple;
|
||||
typedef std::vector<PaddedTuple> StdVectorUint64Padded;
|
||||
typedef eastl::tuple_vector<uint64_t, PaddingStruct> EaTupleVectorUint64Padded;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// MovableType
|
||||
//
|
||||
struct MovableType
|
||||
{
|
||||
int8_t* mpData;
|
||||
enum { kDataSize = 128 };
|
||||
|
||||
MovableType() : mpData(new int8_t[kDataSize])
|
||||
{ memset(mpData, 0, kDataSize); }
|
||||
|
||||
MovableType(const MovableType& x) : mpData(new int8_t[kDataSize])
|
||||
{ memcpy(mpData, x.mpData, kDataSize); }
|
||||
|
||||
MovableType& operator=(const MovableType& x)
|
||||
{
|
||||
if(!mpData)
|
||||
mpData = new int8_t[kDataSize];
|
||||
memcpy(mpData, x.mpData, kDataSize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if EASTL_MOVE_SEMANTICS_ENABLED
|
||||
MovableType(MovableType&& x) EA_NOEXCEPT : mpData(x.mpData)
|
||||
{ x.mpData = NULL; }
|
||||
|
||||
MovableType& operator=(MovableType&& x)
|
||||
{
|
||||
eastl::swap(mpData, x.mpData); // In practice it may not be right to do a swap, depending on the case.
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
~MovableType()
|
||||
{ delete[] mpData; }
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// AutoRefCount
|
||||
//
|
||||
// Basic ref-counted object.
|
||||
//
|
||||
template <typename T>
|
||||
class AutoRefCount
|
||||
{
|
||||
public:
|
||||
T* mpObject;
|
||||
|
||||
public:
|
||||
AutoRefCount() EA_NOEXCEPT : mpObject(NULL)
|
||||
{}
|
||||
|
||||
AutoRefCount(T* pObject) EA_NOEXCEPT : mpObject(pObject)
|
||||
{
|
||||
if(mpObject)
|
||||
mpObject->AddRef();
|
||||
}
|
||||
|
||||
AutoRefCount(T* pObject, int) EA_NOEXCEPT : mpObject(pObject)
|
||||
{
|
||||
// Inherit the existing refcount.
|
||||
}
|
||||
|
||||
AutoRefCount(const AutoRefCount& x) EA_NOEXCEPT : mpObject(x.mpObject)
|
||||
{
|
||||
if(mpObject)
|
||||
mpObject->AddRef();
|
||||
}
|
||||
|
||||
AutoRefCount& operator=(const AutoRefCount& x)
|
||||
{
|
||||
return operator=(x.mpObject);
|
||||
}
|
||||
|
||||
AutoRefCount& operator=(T* pObject)
|
||||
{
|
||||
if(pObject != mpObject)
|
||||
{
|
||||
T* const pTemp = mpObject; // Create temporary to prevent possible problems with re-entrancy.
|
||||
if(pObject)
|
||||
pObject->AddRef();
|
||||
mpObject = pObject;
|
||||
if(pTemp)
|
||||
pTemp->Release();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if EASTL_MOVE_SEMANTICS_ENABLED
|
||||
AutoRefCount(AutoRefCount&& x) EA_NOEXCEPT : mpObject(x.mpObject)
|
||||
{
|
||||
x.mpObject = NULL;
|
||||
}
|
||||
|
||||
AutoRefCount& operator=(AutoRefCount&& x)
|
||||
{
|
||||
if(mpObject)
|
||||
mpObject->Release();
|
||||
mpObject = x.mpObject;
|
||||
x.mpObject = NULL;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
~AutoRefCount()
|
||||
{
|
||||
if(mpObject)
|
||||
mpObject->Release();
|
||||
}
|
||||
|
||||
T& operator *() const EA_NOEXCEPT
|
||||
{ return *mpObject; }
|
||||
|
||||
T* operator ->() const EA_NOEXCEPT
|
||||
{ return mpObject; }
|
||||
|
||||
operator T*() const EA_NOEXCEPT
|
||||
{ return mpObject; }
|
||||
|
||||
}; // class AutoRefCount
|
||||
|
||||
|
||||
struct RefCounted
|
||||
{
|
||||
int mRefCount;
|
||||
static int msAddRefCount;
|
||||
static int msReleaseCount;
|
||||
|
||||
RefCounted() : mRefCount(1) {}
|
||||
|
||||
int AddRef()
|
||||
{ ++msAddRefCount; return ++mRefCount; }
|
||||
|
||||
int Release()
|
||||
{
|
||||
++msReleaseCount;
|
||||
if(mRefCount > 1)
|
||||
return --mRefCount;
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int RefCounted::msAddRefCount = 0;
|
||||
int RefCounted::msReleaseCount = 0;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Container>
|
||||
void TestPushBack(EA::StdC::Stopwatch& stopwatch, Container& c, eastl::vector<uint32_t>& intVector)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for(eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)
|
||||
c.push_back((uint64_t)intVector[j]);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
uint64_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 & 0xffffffff));
|
||||
}
|
||||
|
||||
void TestBracket(EA::StdC::Stopwatch& stopwatch, EaTupleVectorUint64& c)
|
||||
{
|
||||
uint64_t temp = 0;
|
||||
stopwatch.Restart();
|
||||
for (typename EaTupleVectorUint64::size_type j = 0, jEnd = c.size(); j < jEnd; j++)
|
||||
temp += eastl::get<0>(c[j]);
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)(temp & 0xffffffff));
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void TestFind(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
typedef typename Container::iterator iterator_t; // This typedef is required to get this code to compile on RVCT
|
||||
iterator_t it = eastl::find(c.begin(), c.end(), UINT64_C(0xffffffffffff));
|
||||
stopwatch.Stop();
|
||||
if(it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)*it);
|
||||
}
|
||||
|
||||
void TestFind(EA::StdC::Stopwatch& stopwatch, EaTupleVectorUint64& c)
|
||||
{
|
||||
eastl::tuple<uint64_t> val(0xffffffffffff);
|
||||
stopwatch.Restart();
|
||||
EaTupleVectorUint64::iterator it = eastl::find(c.begin(), c.end(), val);
|
||||
stopwatch.Stop();
|
||||
if (it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)eastl::get<0>(*it));
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void TestSort(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
// Intentionally use eastl sort in order to measure just
|
||||
// vector access speed and not be polluted by sort speed.
|
||||
stopwatch.Restart();
|
||||
eastl::quick_sort(c.begin(), c.end());
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)(c[0] & 0xffffffff));
|
||||
}
|
||||
|
||||
void TestSort(EA::StdC::Stopwatch& stopwatch, EaTupleVectorUint64& c)
|
||||
{
|
||||
// Intentionally use eastl sort in order to measure just
|
||||
// vector access speed and not be polluted by sort speed.
|
||||
stopwatch.Restart();
|
||||
eastl::quick_sort(c.begin(), c.end());
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)(eastl::get<0>(c[0]) & 0xffffffff));
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
|
||||
stopwatch.Restart();
|
||||
for(j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
it = c.insert(it, UINT64_C(0xffffffffffff));
|
||||
|
||||
if(it == c.end()) // Try to safely increment the iterator three times.
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestErase(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
|
||||
stopwatch.Restart();
|
||||
for(j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
it = c.erase(it);
|
||||
|
||||
if(it == c.end()) // Try to safely increment the iterator three times.
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestMoveReallocate(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(c.size() < 8192)
|
||||
c.resize(c.capacity() + 1);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestMoveErase(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(!c.empty())
|
||||
c.erase(c.begin());
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Variations of test functions for the Padded structures
|
||||
template <typename Container>
|
||||
void TestTuplePushBack(EA::StdC::Stopwatch& stopwatch, Container& c, eastl::vector<uint32_t>& intVector)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for (eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)
|
||||
{
|
||||
PaddedTuple tup((uint64_t)intVector[j], DefaultPadding);
|
||||
c.push_back(tup);
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestTupleBracket(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
uint64_t temp = 0;
|
||||
stopwatch.Restart();
|
||||
for (typename Container::size_type j = 0, jEnd = c.size(); j < jEnd; j++)
|
||||
temp += eastl::get<0>(c[j]);
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)(temp & 0xffffffff));
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestTupleFind(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
typedef typename Container::iterator iterator_t; // This typedef is required to get this code to compile on RVCT
|
||||
iterator_t it = eastl::find_if(c.begin(), c.end(), [](auto tup) { return eastl::get<0>(tup) == 0xFFFFFFFF; });
|
||||
stopwatch.Stop();
|
||||
if (it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)eastl::get<0>(*it));
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void TestTupleSort(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
// Intentionally use eastl sort in order to measure just
|
||||
// vector access speed and not be polluted by sort speed.
|
||||
stopwatch.Restart();
|
||||
eastl::quick_sort(c.begin(), c.end(), [](auto a, auto b) { return eastl::get<0>(a) < eastl::get<0>(b); });
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)(eastl::get<0>(c[0]) & 0xffffffff));
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void TestTupleInsert(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
PaddedTuple tup(0xFFFFFFFF, DefaultPadding);
|
||||
|
||||
stopwatch.Restart();
|
||||
for (j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
it = c.insert(it, tup);
|
||||
|
||||
if (it == c.end()) // Try to safely increment the iterator three times.
|
||||
it = c.begin();
|
||||
if (++it == c.end())
|
||||
it = c.begin();
|
||||
if (++it == c.end())
|
||||
it = c.begin();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void TestTupleErase(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
|
||||
stopwatch.Restart();
|
||||
for (j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
it = c.erase(it);
|
||||
|
||||
if (it == c.end()) // Try to safely increment the iterator three times.
|
||||
it = c.begin();
|
||||
if (++it == c.end())
|
||||
it = c.begin();
|
||||
if (++it == c.end())
|
||||
it = c.begin();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void BenchmarkTupleVector()
|
||||
{
|
||||
EASTLTest_Printf("TupleVector\n");
|
||||
|
||||
EA::UnitTest::RandGenT<uint32_t> rng(EA::UnitTest::GetRandSeed());
|
||||
EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
|
||||
{
|
||||
eastl::vector<uint32_t> intVector(100000);
|
||||
eastl::generate(intVector.begin(), intVector.end(), rng);
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
StdVectorUint64 stdVectorUint64;
|
||||
EaTupleVectorUint64 eaTupleVectorUint64;
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test push_back
|
||||
///////////////////////////////
|
||||
|
||||
TestPushBack(stopwatch1, stdVectorUint64, intVector);
|
||||
TestPushBack(stopwatch2, eaTupleVectorUint64, intVector);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64>/push_back", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test operator[].
|
||||
///////////////////////////////
|
||||
|
||||
TestBracket(stopwatch1, stdVectorUint64);
|
||||
TestBracket(stopwatch2, eaTupleVectorUint64);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64>/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test iteration via find().
|
||||
///////////////////////////////
|
||||
|
||||
TestFind(stopwatch1, stdVectorUint64);
|
||||
TestFind(stopwatch2, eaTupleVectorUint64);
|
||||
TestFind(stopwatch1, stdVectorUint64);
|
||||
TestFind(stopwatch2, eaTupleVectorUint64);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64>/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test sort
|
||||
///////////////////////////////
|
||||
|
||||
// Currently VC++ complains about our sort function decrementing std::iterator that is already at begin(). In the strictest sense,
|
||||
// that's a valid complaint, but we aren't testing std STL here. We will want to revise our sort function eventually.
|
||||
#if !defined(_MSC_VER) || !defined(_ITERATOR_DEBUG_LEVEL) || (_ITERATOR_DEBUG_LEVEL < 2)
|
||||
TestSort(stopwatch1, stdVectorUint64);
|
||||
TestSort(stopwatch2, eaTupleVectorUint64);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64>/sort", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
#endif
|
||||
|
||||
///////////////////////////////
|
||||
// Test insert
|
||||
///////////////////////////////
|
||||
|
||||
TestInsert(stopwatch1, stdVectorUint64);
|
||||
TestInsert(stopwatch2, eaTupleVectorUint64);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64>/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase
|
||||
///////////////////////////////
|
||||
|
||||
TestErase(stopwatch1, stdVectorUint64);
|
||||
TestErase(stopwatch2, eaTupleVectorUint64);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64>/erase", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Test move of MovableType
|
||||
// Should be much faster with C++11 move.
|
||||
///////////////////////////////////////////
|
||||
|
||||
std::vector<MovableType> stdVectorMovableType;
|
||||
eastl::tuple_vector<MovableType> eaTupleVectorMovableType;
|
||||
|
||||
TestMoveReallocate(stopwatch1, stdVectorMovableType);
|
||||
TestMoveReallocate(stopwatch2, eaTupleVectorMovableType);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<MovableType>/reallocate", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
TestMoveErase(stopwatch1, stdVectorMovableType);
|
||||
TestMoveErase(stopwatch2, eaTupleVectorMovableType);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<MovableType>/erase", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Test move of AutoRefCount
|
||||
// Should be much faster with C++11 move.
|
||||
///////////////////////////////////////////
|
||||
|
||||
std::vector<AutoRefCount<RefCounted> > stdVectorAutoRefCount;
|
||||
eastl::tuple_vector<AutoRefCount<RefCounted> > eaTupleVectorAutoRefCount;
|
||||
|
||||
for(size_t a = 0; a < 2048; a++)
|
||||
{
|
||||
stdVectorAutoRefCount.push_back(AutoRefCount<RefCounted>(new RefCounted));
|
||||
eaTupleVectorAutoRefCount.push_back(AutoRefCount<RefCounted>(new RefCounted));
|
||||
}
|
||||
|
||||
RefCounted::msAddRefCount = 0;
|
||||
RefCounted::msReleaseCount = 0;
|
||||
TestMoveErase(stopwatch1, stdVectorAutoRefCount);
|
||||
//EASTLTest_Printf("tuple_vector<AutoRefCount>/erase std counts: %d %d\n", RefCounted::msAddRefCount, RefCounted::msReleaseCount);
|
||||
|
||||
RefCounted::msAddRefCount = 0;
|
||||
RefCounted::msReleaseCount = 0;
|
||||
TestMoveErase(stopwatch2, eaTupleVectorAutoRefCount);
|
||||
//EASTLTest_Printf("tuple_vector<AutoRefCount>/erase EA counts: %d %d\n", RefCounted::msAddRefCount, RefCounted::msReleaseCount);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<AutoRefCount>/erase", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Test various operations with "padded" data, to demonstrate access/modification of sparse data
|
||||
|
||||
StdVectorUint64Padded stdVectorUint64Padded;
|
||||
EaTupleVectorUint64Padded eaTupleVectorUint64Padded;
|
||||
|
||||
///////////////////////////////
|
||||
// Test push_back
|
||||
///////////////////////////////
|
||||
|
||||
TestTuplePushBack(stopwatch1, stdVectorUint64Padded, intVector);
|
||||
TestTuplePushBack(stopwatch2, eaTupleVectorUint64Padded, intVector);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64,Padding>/push_back", stopwatch1.GetUnits(),
|
||||
stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test operator[].
|
||||
///////////////////////////////
|
||||
|
||||
TestTupleBracket(stopwatch1, stdVectorUint64Padded);
|
||||
TestTupleBracket(stopwatch2, eaTupleVectorUint64Padded);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64,Padding>/operator[]", stopwatch1.GetUnits(),
|
||||
stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test iteration via find().
|
||||
///////////////////////////////
|
||||
|
||||
TestTupleFind(stopwatch1, stdVectorUint64Padded);
|
||||
TestTupleFind(stopwatch2, eaTupleVectorUint64Padded);
|
||||
TestTupleFind(stopwatch1, stdVectorUint64Padded);
|
||||
TestTupleFind(stopwatch2, eaTupleVectorUint64Padded);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64,Padding>/iteration", stopwatch1.GetUnits(),
|
||||
stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test sort
|
||||
///////////////////////////////
|
||||
|
||||
// Currently VC++ complains about our sort function decrementing std::iterator that is already at
|
||||
// begin(). In the strictest sense, that's a valid complaint, but we aren't testing std STL here. We
|
||||
// will want to revise our sort function eventually.
|
||||
#if !defined(_MSC_VER) || !defined(_ITERATOR_DEBUG_LEVEL) || (_ITERATOR_DEBUG_LEVEL < 2)
|
||||
TestTupleSort(stopwatch1, stdVectorUint64Padded);
|
||||
TestTupleSort(stopwatch2, eaTupleVectorUint64Padded);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64,Padding>/sort", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(),
|
||||
stopwatch2.GetElapsedTime());
|
||||
#endif
|
||||
|
||||
///////////////////////////////
|
||||
// Test insert
|
||||
///////////////////////////////
|
||||
|
||||
TestTupleInsert(stopwatch1, stdVectorUint64Padded);
|
||||
TestTupleInsert(stopwatch2, eaTupleVectorUint64Padded);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64,Padding>/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(),
|
||||
stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase
|
||||
///////////////////////////////
|
||||
|
||||
TestTupleErase(stopwatch1, stdVectorUint64Padded);
|
||||
TestTupleErase(stopwatch2, eaTupleVectorUint64Padded);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("tuple_vector<uint64,Padding>/erase", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(),
|
||||
stopwatch2.GetElapsedTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,452 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <EASTL/algorithm.h>
|
||||
#include <EASTL/vector.h>
|
||||
#include <EASTL/sort.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#pragma warning(disable: 4350)
|
||||
#endif
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
using namespace EA;
|
||||
|
||||
|
||||
typedef std::vector<uint64_t> StdVectorUint64;
|
||||
typedef eastl::vector<uint64_t> EaVectorUint64;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// MovableType
|
||||
//
|
||||
struct MovableType
|
||||
{
|
||||
int8_t* mpData;
|
||||
enum { kDataSize = 128 };
|
||||
|
||||
MovableType() : mpData(new int8_t[kDataSize])
|
||||
{ memset(mpData, 0, kDataSize); }
|
||||
|
||||
MovableType(const MovableType& x) : mpData(new int8_t[kDataSize])
|
||||
{ memcpy(mpData, x.mpData, kDataSize); }
|
||||
|
||||
MovableType& operator=(const MovableType& x)
|
||||
{
|
||||
if(!mpData)
|
||||
mpData = new int8_t[kDataSize];
|
||||
memcpy(mpData, x.mpData, kDataSize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MovableType(MovableType&& x) EA_NOEXCEPT : mpData(x.mpData)
|
||||
{ x.mpData = NULL; }
|
||||
|
||||
MovableType& operator=(MovableType&& x)
|
||||
{
|
||||
eastl::swap(mpData, x.mpData); // In practice it may not be right to do a swap, depending on the case.
|
||||
return *this;
|
||||
}
|
||||
|
||||
~MovableType()
|
||||
{ delete[] mpData; }
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// AutoRefCount
|
||||
//
|
||||
// Basic ref-counted object.
|
||||
//
|
||||
template <typename T>
|
||||
class AutoRefCount
|
||||
{
|
||||
public:
|
||||
T* mpObject;
|
||||
|
||||
public:
|
||||
AutoRefCount() EA_NOEXCEPT : mpObject(NULL)
|
||||
{}
|
||||
|
||||
AutoRefCount(T* pObject) EA_NOEXCEPT : mpObject(pObject)
|
||||
{
|
||||
if(mpObject)
|
||||
mpObject->AddRef();
|
||||
}
|
||||
|
||||
AutoRefCount(T* pObject, int) EA_NOEXCEPT : mpObject(pObject)
|
||||
{
|
||||
// Inherit the existing refcount.
|
||||
}
|
||||
|
||||
AutoRefCount(const AutoRefCount& x) EA_NOEXCEPT : mpObject(x.mpObject)
|
||||
{
|
||||
if(mpObject)
|
||||
mpObject->AddRef();
|
||||
}
|
||||
|
||||
AutoRefCount& operator=(const AutoRefCount& x)
|
||||
{
|
||||
return operator=(x.mpObject);
|
||||
}
|
||||
|
||||
AutoRefCount& operator=(T* pObject)
|
||||
{
|
||||
if(pObject != mpObject)
|
||||
{
|
||||
T* const pTemp = mpObject; // Create temporary to prevent possible problems with re-entrancy.
|
||||
if(pObject)
|
||||
pObject->AddRef();
|
||||
mpObject = pObject;
|
||||
if(pTemp)
|
||||
pTemp->Release();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
AutoRefCount(AutoRefCount&& x) EA_NOEXCEPT : mpObject(x.mpObject)
|
||||
{
|
||||
x.mpObject = NULL;
|
||||
}
|
||||
|
||||
AutoRefCount& operator=(AutoRefCount&& x)
|
||||
{
|
||||
if(mpObject)
|
||||
mpObject->Release();
|
||||
mpObject = x.mpObject;
|
||||
x.mpObject = NULL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~AutoRefCount()
|
||||
{
|
||||
if(mpObject)
|
||||
mpObject->Release();
|
||||
}
|
||||
|
||||
T& operator *() const EA_NOEXCEPT
|
||||
{ return *mpObject; }
|
||||
|
||||
T* operator ->() const EA_NOEXCEPT
|
||||
{ return mpObject; }
|
||||
|
||||
operator T*() const EA_NOEXCEPT
|
||||
{ return mpObject; }
|
||||
|
||||
}; // class AutoRefCount
|
||||
|
||||
|
||||
struct RefCounted
|
||||
{
|
||||
int mRefCount;
|
||||
static int msAddRefCount;
|
||||
static int msReleaseCount;
|
||||
|
||||
RefCounted() : mRefCount(1) {}
|
||||
|
||||
int AddRef()
|
||||
{ ++msAddRefCount; return ++mRefCount; }
|
||||
|
||||
int Release()
|
||||
{
|
||||
++msReleaseCount;
|
||||
if(mRefCount > 1)
|
||||
return --mRefCount;
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
int RefCounted::msAddRefCount = 0;
|
||||
int RefCounted::msReleaseCount = 0;
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Container>
|
||||
void TestPushBack(EA::StdC::Stopwatch& stopwatch, Container& c, eastl::vector<uint32_t>& intVector)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
for(eastl_size_t j = 0, jEnd = intVector.size(); j < jEnd; j++)
|
||||
c.push_back((uint64_t)intVector[j]);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestBracket(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
uint64_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 & 0xffffffff));
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestFind(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
typedef typename Container::iterator iterator_t; // This typedef is required to get this code to compile on RVCT
|
||||
iterator_t it = eastl::find(c.begin(), c.end(), UINT64_C(0xffffffffffff));
|
||||
stopwatch.Stop();
|
||||
if(it != c.end())
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)*it);
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestSort(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
// Intentionally use eastl sort in order to measure just
|
||||
// vector access speed and not be polluted by sort speed.
|
||||
stopwatch.Restart();
|
||||
eastl::quick_sort(c.begin(), c.end());
|
||||
stopwatch.Stop();
|
||||
sprintf(Benchmark::gScratchBuffer, "%u", (unsigned)(c[0] & 0xffffffff));
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestInsert(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
|
||||
stopwatch.Restart();
|
||||
for(j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
it = c.insert(it, UINT64_C(0xffffffffffff));
|
||||
|
||||
if(it == c.end()) // Try to safely increment the iterator three times.
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestErase(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
typename Container::size_type j, jEnd;
|
||||
typename Container::iterator it;
|
||||
|
||||
stopwatch.Restart();
|
||||
for(j = 0, jEnd = 100, it = c.begin(); j < jEnd; ++j)
|
||||
{
|
||||
it = c.erase(it);
|
||||
|
||||
if(it == c.end()) // Try to safely increment the iterator three times.
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
if(++it == c.end())
|
||||
it = c.begin();
|
||||
}
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestMoveReallocate(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(c.size() < 8192)
|
||||
c.resize(c.capacity() + 1);
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
template <typename Container>
|
||||
void TestMoveErase(EA::StdC::Stopwatch& stopwatch, Container& c)
|
||||
{
|
||||
stopwatch.Restart();
|
||||
while(!c.empty())
|
||||
c.erase(c.begin());
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void BenchmarkVector()
|
||||
{
|
||||
EASTLTest_Printf("Vector\n");
|
||||
|
||||
EA::UnitTest::RandGenT<uint32_t> rng(EA::UnitTest::GetRandSeed());
|
||||
EA::StdC::Stopwatch stopwatch1(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
EA::StdC::Stopwatch stopwatch2(EA::StdC::Stopwatch::kUnitsCPUCycles);
|
||||
|
||||
{
|
||||
eastl::vector<uint32_t> intVector(100000);
|
||||
eastl::generate(intVector.begin(), intVector.end(), rng);
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
StdVectorUint64 stdVectorUint64;
|
||||
EaVectorUint64 eaVectorUint64;
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test push_back
|
||||
///////////////////////////////
|
||||
|
||||
TestPushBack(stopwatch1, stdVectorUint64, intVector);
|
||||
TestPushBack(stopwatch2, eaVectorUint64, intVector);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("vector<uint64>/push_back", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test operator[].
|
||||
///////////////////////////////
|
||||
|
||||
TestBracket(stopwatch1, stdVectorUint64);
|
||||
TestBracket(stopwatch2, eaVectorUint64);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("vector<uint64>/operator[]", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test iteration via find().
|
||||
///////////////////////////////
|
||||
|
||||
TestFind(stopwatch1, stdVectorUint64);
|
||||
TestFind(stopwatch2, eaVectorUint64);
|
||||
TestFind(stopwatch1, stdVectorUint64);
|
||||
TestFind(stopwatch2, eaVectorUint64);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("vector<uint64>/iteration", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test sort
|
||||
///////////////////////////////
|
||||
|
||||
// Currently VC++ complains about our sort function decrementing std::iterator that is already at begin(). In the strictest sense,
|
||||
// that's a valid complaint, but we aren't testing std STL here. We will want to revise our sort function eventually.
|
||||
#if !defined(_MSC_VER) || !defined(_ITERATOR_DEBUG_LEVEL) || (_ITERATOR_DEBUG_LEVEL < 2)
|
||||
TestSort(stopwatch1, stdVectorUint64);
|
||||
TestSort(stopwatch2, eaVectorUint64);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("vector<uint64>/sort", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
#endif
|
||||
|
||||
///////////////////////////////
|
||||
// Test insert
|
||||
///////////////////////////////
|
||||
|
||||
TestInsert(stopwatch1, stdVectorUint64);
|
||||
TestInsert(stopwatch2, eaVectorUint64);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("vector<uint64>/insert", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
// Test erase
|
||||
///////////////////////////////
|
||||
|
||||
TestErase(stopwatch1, stdVectorUint64);
|
||||
TestErase(stopwatch2, eaVectorUint64);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("vector<uint64>/erase", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Test move of MovableType
|
||||
// Should be much faster with C++11 move.
|
||||
///////////////////////////////////////////
|
||||
|
||||
std::vector<MovableType> stdVectorMovableType;
|
||||
eastl::vector<MovableType> eaVectorMovableType;
|
||||
|
||||
TestMoveReallocate(stopwatch1, stdVectorMovableType);
|
||||
TestMoveReallocate(stopwatch2, eaVectorMovableType);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("vector<MovableType>/reallocate", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
TestMoveErase(stopwatch1, stdVectorMovableType);
|
||||
TestMoveErase(stopwatch2, eaVectorMovableType);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("vector<MovableType>/erase", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
// Test move of AutoRefCount
|
||||
// Should be much faster with C++11 move.
|
||||
///////////////////////////////////////////
|
||||
|
||||
std::vector<AutoRefCount<RefCounted> > stdVectorAutoRefCount;
|
||||
eastl::vector<AutoRefCount<RefCounted> > eaVectorAutoRefCount;
|
||||
|
||||
for(size_t a = 0; a < 2048; a++)
|
||||
{
|
||||
stdVectorAutoRefCount.push_back(AutoRefCount<RefCounted>(new RefCounted));
|
||||
eaVectorAutoRefCount.push_back(AutoRefCount<RefCounted>(new RefCounted));
|
||||
}
|
||||
|
||||
RefCounted::msAddRefCount = 0;
|
||||
RefCounted::msReleaseCount = 0;
|
||||
TestMoveErase(stopwatch1, stdVectorAutoRefCount);
|
||||
EASTLTest_Printf("vector<AutoRefCount>/erase std counts: %d %d\n", RefCounted::msAddRefCount, RefCounted::msReleaseCount);
|
||||
|
||||
RefCounted::msAddRefCount = 0;
|
||||
RefCounted::msReleaseCount = 0;
|
||||
TestMoveErase(stopwatch2, eaVectorAutoRefCount);
|
||||
EASTLTest_Printf("vector<AutoRefCount>/erase EA counts: %d %d\n", RefCounted::msAddRefCount, RefCounted::msReleaseCount);
|
||||
|
||||
if(i == 1)
|
||||
Benchmark::AddResult("vector<AutoRefCount>/erase", stopwatch1.GetUnits(), stopwatch1.GetElapsedTime(), stopwatch2.GetElapsedTime());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,291 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#include <EASTL/string.h>
|
||||
#include <EAMain/EAMain.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 0)
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
namespace Benchmark
|
||||
{
|
||||
static int64_t ConvertStopwatchUnits(EA::StdC::Stopwatch::Units unitsSource, int64_t valueSource, EA::StdC::Stopwatch::Units unitsDest)
|
||||
{
|
||||
using namespace EA::StdC;
|
||||
|
||||
int64_t valueDest = valueSource;
|
||||
|
||||
if(unitsSource != unitsDest)
|
||||
{
|
||||
double sourceMultiplier;
|
||||
|
||||
switch (unitsSource)
|
||||
{
|
||||
case Stopwatch::kUnitsCPUCycles:
|
||||
sourceMultiplier = Stopwatch::GetUnitsPerCPUCycle(unitsDest); // This will typically be a number less than 1.
|
||||
valueDest = (int64_t)(valueSource * sourceMultiplier);
|
||||
break;
|
||||
|
||||
case Stopwatch::kUnitsCycles:
|
||||
sourceMultiplier = Stopwatch::GetUnitsPerStopwatchCycle(unitsDest); // This will typically be a number less than 1.
|
||||
valueDest = (int64_t)(valueSource * sourceMultiplier);
|
||||
break;
|
||||
|
||||
case Stopwatch::kUnitsNanoseconds:
|
||||
case Stopwatch::kUnitsMicroseconds:
|
||||
case Stopwatch::kUnitsMilliseconds:
|
||||
case Stopwatch::kUnitsSeconds:
|
||||
case Stopwatch::kUnitsMinutes:
|
||||
case Stopwatch::kUnitsUserDefined:
|
||||
// To do. Also, handle the case of unitsDest being Cycles or CPUCycles and unitsSource being a time.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return valueDest;
|
||||
}
|
||||
|
||||
void WriteTime(int64_t timeNS, eastl::string& sTime)
|
||||
{
|
||||
if(timeNS > 1000000000)
|
||||
sTime.sprintf(" %6.2f s", (double)timeNS / 1000000000);
|
||||
else if(timeNS > 1000000)
|
||||
sTime.sprintf("%6.1f ms", (double)timeNS / 1000000);
|
||||
else if(timeNS > 1000)
|
||||
sTime.sprintf("%6.1f us", (double)timeNS / 1000);
|
||||
else
|
||||
sTime.sprintf("%6.1f ns", (double)timeNS / 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Environment gEnvironment;
|
||||
|
||||
Environment& GetEnvironment()
|
||||
{
|
||||
return gEnvironment;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ResultSet gResultSet;
|
||||
|
||||
ResultSet& GetResultSet()
|
||||
{
|
||||
return gResultSet;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Scratch sprintf buffer
|
||||
char gScratchBuffer[1024];
|
||||
|
||||
|
||||
void DoNothing(...)
|
||||
{
|
||||
// Intentionally nothing.
|
||||
}
|
||||
|
||||
|
||||
void AddResult(const char* pName, int units, int64_t nTime1, int64_t nTime2, const char* pNotes)
|
||||
{
|
||||
Result result;
|
||||
|
||||
result.msName = pName;
|
||||
result.mUnits = units;
|
||||
result.mTime1 = nTime1;
|
||||
result.mTime1NS = ConvertStopwatchUnits((EA::StdC::Stopwatch::Units)units, nTime1, EA::StdC::Stopwatch::kUnitsNanoseconds);
|
||||
result.mTime2 = nTime2;
|
||||
result.mTime2NS = ConvertStopwatchUnits((EA::StdC::Stopwatch::Units)units, nTime2, EA::StdC::Stopwatch::kUnitsNanoseconds);
|
||||
|
||||
if(pNotes)
|
||||
result.msNotes = pNotes;
|
||||
|
||||
gResultSet.insert(result);
|
||||
}
|
||||
|
||||
|
||||
void PrintResultLine(const Result& result)
|
||||
{
|
||||
const double fRatio = (double)result.mTime1 / (double)result.mTime2;
|
||||
const double fRatioPrinted = (fRatio > 100) ? 100 : fRatio;
|
||||
const double fPercentChange = fabs(((double)result.mTime1 - (double)result.mTime2) / (((double)result.mTime1 + (double)result.mTime2) / 2));
|
||||
const bool bDifference = (result.mTime1 > 10) && (result.mTime2 > 10) && (fPercentChange > 0.25);
|
||||
const char* pDifference = (bDifference ? (result.mTime1 < result.mTime2 ? "-" : "+") : "");
|
||||
|
||||
eastl::string sClockTime1, sClockTime2;
|
||||
|
||||
WriteTime(result.mTime1NS, sClockTime1); // This converts an integer in nanoseconds (e.g. 23400000) to a string (e.g. "23.4 ms")
|
||||
WriteTime(result.mTime2NS, sClockTime2);
|
||||
|
||||
EA::UnitTest::Report("%-43s | %13" PRIu64 " %s | %13" PRIu64 " %s | %10.2f%10s", result.msName.c_str(), result.mTime1, sClockTime1.c_str(), result.mTime2, sClockTime2.c_str(), fRatioPrinted, pDifference);
|
||||
|
||||
if(result.msNotes.length()) // If there are any notes...
|
||||
EA::UnitTest::Report(" %s", result.msNotes.c_str());
|
||||
EA::UnitTest::Report("\n");
|
||||
}
|
||||
|
||||
|
||||
#if defined(EASTL_BENCHMARK_WRITE_FILE) && EASTL_BENCHMARK_WRITE_FILE
|
||||
|
||||
#if !defined(EASTL_BENCHMARK_WRITE_FILE_PATH)
|
||||
#define EASTL_BENCHMARK_WRITE_FILE_PATH "BenchmarkResults.txt"
|
||||
#endif
|
||||
|
||||
struct FileWriter
|
||||
{
|
||||
FILE* mpReportFile;
|
||||
EA::EAMain::ReportFunction mpSavedReportFunction;
|
||||
static FileWriter* gpFileWriter;
|
||||
|
||||
static void StaticPrintfReportFunction(const char8_t* pText)
|
||||
{
|
||||
if(gpFileWriter)
|
||||
gpFileWriter->PrintfReportFunction(pText);
|
||||
}
|
||||
|
||||
void PrintfReportFunction(const char8_t* pText)
|
||||
{
|
||||
fwrite(pText, strlen(pText), 1, mpReportFile);
|
||||
EA::EAMain::ReportFunction gpReportFunction = EA::EAMain::GetDefaultReportFunction();
|
||||
gpReportFunction(pText);
|
||||
}
|
||||
|
||||
FileWriter() : mpReportFile(NULL), mpSavedReportFunction(NULL)
|
||||
{
|
||||
mpReportFile = fopen(EASTL_BENCHMARK_WRITE_FILE_PATH, "w+");
|
||||
|
||||
if(mpReportFile)
|
||||
{
|
||||
gpFileWriter = this;
|
||||
mpSavedReportFunction = EA::EAMain::GetDefaultReportFunction();
|
||||
EA::EAMain::SetReportFunction(StaticPrintfReportFunction);
|
||||
}
|
||||
}
|
||||
|
||||
~FileWriter()
|
||||
{
|
||||
if(mpReportFile)
|
||||
{
|
||||
gpFileWriter = NULL;
|
||||
EA::EAMain::SetReportFunction(mpSavedReportFunction);
|
||||
fclose(mpReportFile);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
FileWriter* FileWriter::gpFileWriter = NULL;
|
||||
#endif
|
||||
|
||||
|
||||
void PrintResults()
|
||||
{
|
||||
#if defined(EASTL_BENCHMARK_WRITE_FILE) && EASTL_BENCHMARK_WRITE_FILE
|
||||
FileWriter fileWriter; // This will auto-execute.
|
||||
#endif
|
||||
|
||||
// Print the results
|
||||
EA::UnitTest::Report("\n");
|
||||
EA::UnitTest::Report("****************************************************************************************\n");
|
||||
EA::UnitTest::Report("EASTL Benchmark test results\n");
|
||||
EA::UnitTest::Report("****************************************************************************************\n");
|
||||
EA::UnitTest::Report("\n");
|
||||
EA::UnitTest::Report("EASTL version: %s\n", EASTL_VERSION);
|
||||
EA::UnitTest::Report("Platform: %s\n", gEnvironment.msPlatform.c_str());
|
||||
EA::UnitTest::Report("Compiler: %s\n", EA_COMPILER_STRING);
|
||||
#if defined(EA_DEBUG) || defined(_DEBUG)
|
||||
EA::UnitTest::Report("Allocator: PPMalloc::GeneralAllocatorDebug. Thread safety enabled.\n");
|
||||
EA::UnitTest::Report("Build: Debug. Inlining disabled. STL debug features disabled.\n");
|
||||
#else
|
||||
EA::UnitTest::Report("Allocator: PPMalloc::GeneralAllocator. Thread safety enabled.\n");
|
||||
EA::UnitTest::Report("Build: Full optimization. Inlining enabled.\n");
|
||||
#endif
|
||||
EA::UnitTest::Report("\n");
|
||||
EA::UnitTest::Report("Values are ticks and time to complete tests; smaller values are better.\n");
|
||||
EA::UnitTest::Report("\n");
|
||||
EA::UnitTest::Report("%-43s%26s%26s%13s%13s\n", "Test", gEnvironment.msSTLName1.c_str(), gEnvironment.msSTLName2.c_str(), "Ratio", "Difference?");
|
||||
EA::UnitTest::Report("---------------------------------------------------------------------------------------------------------------------\n");
|
||||
|
||||
eastl::string sTestTypeLast;
|
||||
eastl::string sTestTypeTemp;
|
||||
|
||||
for(ResultSet::iterator it = gResultSet.begin(); it != gResultSet.end(); ++it)
|
||||
{
|
||||
const Result& result = *it;
|
||||
|
||||
eastl_size_t n = result.msName.find('/');
|
||||
if(n == eastl::string::npos)
|
||||
n = result.msName.length();
|
||||
sTestTypeTemp.assign(result.msName, 0, n);
|
||||
|
||||
if(sTestTypeTemp != sTestTypeLast) // If it looks like we are changing to a new test type... add an empty line to help readability.
|
||||
{
|
||||
if(it != gResultSet.begin())
|
||||
EA::UnitTest::Report("\n");
|
||||
sTestTypeLast = sTestTypeTemp;
|
||||
}
|
||||
|
||||
PrintResultLine(result);
|
||||
}
|
||||
|
||||
// We will print out a final line that has the sum of the rows printed above.
|
||||
Result resultSum;
|
||||
resultSum.msName = "sum";
|
||||
|
||||
for(ResultSet::iterator its = gResultSet.begin(); its != gResultSet.end(); ++its)
|
||||
{
|
||||
const Result& resultTemp = *its;
|
||||
|
||||
EASTL_ASSERT(resultTemp.mUnits == EA::StdC::Stopwatch::kUnitsCPUCycles); // Our ConvertStopwatchUnits call below assumes that every measured time is CPUCycles.
|
||||
resultSum.mTime1 += resultTemp.mTime1;
|
||||
resultSum.mTime2 += resultTemp.mTime2;
|
||||
}
|
||||
|
||||
// We do this convert as a final step instead of the loop in order to avoid loss of precision.
|
||||
resultSum.mTime1NS = ConvertStopwatchUnits(EA::StdC::Stopwatch::kUnitsCPUCycles, resultSum.mTime1, EA::StdC::Stopwatch::kUnitsNanoseconds);
|
||||
resultSum.mTime2NS = ConvertStopwatchUnits(EA::StdC::Stopwatch::kUnitsCPUCycles, resultSum.mTime2, EA::StdC::Stopwatch::kUnitsNanoseconds);
|
||||
EA::UnitTest::Report("\n");
|
||||
PrintResultLine(resultSum);
|
||||
|
||||
EA::UnitTest::Report("\n");
|
||||
EA::UnitTest::Report("****************************************************************************************\n");
|
||||
EA::UnitTest::Report("\n");
|
||||
|
||||
// Clear the results
|
||||
gResultSet.clear();
|
||||
gEnvironment.clear();
|
||||
}
|
||||
|
||||
} // namespace Benchmark
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifndef EASTLBENCHMARK_H
|
||||
#define EASTLBENCHMARK_H
|
||||
|
||||
|
||||
// Intrinsic control
|
||||
//
|
||||
// Our benchmark results are being skewed by inconsistent decisions by the
|
||||
// VC++ compiler to use intrinsic functions. Additionally, many of our
|
||||
// benchmarks work on large blocks of elements, whereas intrinsics often
|
||||
// are an improvement only over small blocks of elements. As a result,
|
||||
// enabling of intrinsics is often resulting in poor benchmark results for
|
||||
// code that gets an intrinsic enabled for it, even though it will often
|
||||
// happen in real code to be the opposite case. The disabling of intrinsics
|
||||
// here often results in EASTL performance being lower than it would be in
|
||||
// real-world situations.
|
||||
//
|
||||
#include <string.h>
|
||||
#ifdef _MSC_VER
|
||||
#pragma function(strlen, strcmp, strcpy, strcat, memcpy, memcmp, memset)
|
||||
#endif
|
||||
|
||||
|
||||
#include <EASTL/set.h>
|
||||
#include <EASTL/string.h>
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
void BenchmarkSort();
|
||||
void BenchmarkList();
|
||||
void BenchmarkString();
|
||||
void BenchmarkVector();
|
||||
void BenchmarkDeque();
|
||||
void BenchmarkSet();
|
||||
void BenchmarkMap();
|
||||
void BenchmarkHash();
|
||||
void BenchmarkAlgorithm();
|
||||
void BenchmarkHeap();
|
||||
void BenchmarkBitset();
|
||||
void BenchmarkTupleVector();
|
||||
|
||||
|
||||
namespace Benchmark
|
||||
{
|
||||
|
||||
// Environment
|
||||
//
|
||||
// The environment for this benchmark test.
|
||||
//
|
||||
struct Environment
|
||||
{
|
||||
eastl::string8 msPlatform; // Name of test platform (e.g. "Windows")
|
||||
eastl::string8 msSTLName1; // Name of competitor #1 (e.g. "EASTL").
|
||||
eastl::string8 msSTLName2; // Name of competitor #2 (e.g. "MS STL").
|
||||
|
||||
void clear() { msPlatform.set_capacity(0); msSTLName1.set_capacity(0); msSTLName2.set_capacity(0); }
|
||||
};
|
||||
|
||||
Environment& GetEnvironment();
|
||||
|
||||
|
||||
// Result
|
||||
//
|
||||
// An individual benchmark result.
|
||||
//
|
||||
struct Result
|
||||
{
|
||||
eastl::string8 msName; // Test name (e.g. "vector/insert").
|
||||
int mUnits; // Timing units (e.g. EA::StdC::Stopwatch::kUnitsSeconds).
|
||||
int64_t mTime1; // Time of competitor #1.
|
||||
uint64_t mTime1NS; // Nanoseconds.
|
||||
int64_t mTime2; // Time of competitor #2.
|
||||
int64_t mTime2NS; // Nanoseconds.
|
||||
eastl::string8 msNotes; // Any comments to attach to this result.
|
||||
|
||||
Result() : msName(), mUnits(EA::StdC::Stopwatch::kUnitsCPUCycles),
|
||||
mTime1(0), mTime1NS(0), mTime2(0), mTime2NS(0), msNotes() { }
|
||||
};
|
||||
|
||||
inline bool operator<(const Result& r1, const Result& r2)
|
||||
{ return r1.msName < r2.msName; }
|
||||
|
||||
typedef eastl::set<Result> ResultSet;
|
||||
|
||||
ResultSet& GetResultSet();
|
||||
|
||||
|
||||
// Scratch sprintf buffer
|
||||
extern char gScratchBuffer[1024];
|
||||
|
||||
|
||||
|
||||
// Utility functions
|
||||
//
|
||||
void DoNothing(...);
|
||||
void AddResult(const char* pName, int units, int64_t nTime1, int64_t nTime2, const char* pNotes = NULL);
|
||||
void PrintResults();
|
||||
void WriteTime(int64_t timeNS, eastl::string& sTime);
|
||||
|
||||
|
||||
} // namespace Benchmark
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// LargePOD
|
||||
///
|
||||
/// Implements a structure which is essentially a largish POD. Useful for testing
|
||||
/// containers and algorithms for their ability to efficiently work with PODs.
|
||||
/// This class isn't strictly a POD by the definition of the C++ standard,
|
||||
/// but it suffices for our interests.
|
||||
///
|
||||
struct LargeObject
|
||||
{
|
||||
int32_t mData[2048];
|
||||
};
|
||||
|
||||
struct LargePOD
|
||||
{
|
||||
LargeObject mLargeObject1;
|
||||
LargeObject mLargeObject2;
|
||||
const char* mpName1;
|
||||
const char* mpName2;
|
||||
|
||||
explicit LargePOD(int32_t x = 0) // A true POD doesn't have a non-trivial constructor.
|
||||
{
|
||||
memset(mLargeObject1.mData, 0, sizeof(mLargeObject1.mData));
|
||||
memset(mLargeObject2.mData, 0, sizeof(mLargeObject2.mData));
|
||||
mLargeObject1.mData[0] = x;
|
||||
|
||||
mpName1 = "LargePOD1";
|
||||
mpName2 = "LargePOD2";
|
||||
}
|
||||
|
||||
LargePOD(const LargePOD& largePOD) // A true POD doesn't have a non-trivial copy-constructor.
|
||||
: mLargeObject1(largePOD.mLargeObject1),
|
||||
mLargeObject2(largePOD.mLargeObject2),
|
||||
mpName1(largePOD.mpName1),
|
||||
mpName2(largePOD.mpName2)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~LargePOD() { }
|
||||
|
||||
LargePOD& operator=(const LargePOD& largePOD) // A true POD doesn't have a non-trivial assignment operator.
|
||||
{
|
||||
if(&largePOD != this)
|
||||
{
|
||||
mLargeObject1 = largePOD.mLargeObject1;
|
||||
mLargeObject2 = largePOD.mLargeObject2;
|
||||
mpName1 = largePOD.mpName1;
|
||||
mpName2 = largePOD.mpName2;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual void DoSomething() // Note that by declaring this virtual, this class is not truly a POD.
|
||||
{ // But it acts like a POD for the purposes of EASTL algorithms.
|
||||
mLargeObject1.mData[1]++;
|
||||
}
|
||||
|
||||
operator int()
|
||||
{
|
||||
return (int)mLargeObject1.mData[0];
|
||||
}
|
||||
};
|
||||
|
||||
//EASTL_DECLARE_POD(LargePOD);
|
||||
//EASTL_DECLARE_TRIVIAL_CONSTRUCTOR(LargePOD);
|
||||
//EASTL_DECLARE_TRIVIAL_COPY(LargePOD);
|
||||
//EASTL_DECLARE_TRIVIAL_ASSIGN(LargePOD);
|
||||
//EASTL_DECLARE_TRIVIAL_DESTRUCTOR(LargePOD);
|
||||
//EASTL_DECLARE_TRIVIAL_RELOCATE(LargePOD);
|
||||
|
||||
// Operators
|
||||
// We specifically define only == and <, in order to verify that
|
||||
// our containers and algorithms are not mistakenly expecting other
|
||||
// operators for the contained and manipulated classes.
|
||||
inline bool operator==(const LargePOD& t1, const LargePOD& t2)
|
||||
{
|
||||
return (memcmp(&t1.mLargeObject1, &t2.mLargeObject1, sizeof(t1.mLargeObject1)) == 0) &&
|
||||
(memcmp(&t1.mLargeObject2, &t2.mLargeObject2, sizeof(t1.mLargeObject2)) == 0) &&
|
||||
(strcmp(t1.mpName1, t2.mpName1) == 0) &&
|
||||
(strcmp(t1.mpName2, t2.mpName2) == 0);
|
||||
}
|
||||
|
||||
inline bool operator<(const LargePOD& t1, const LargePOD& t2)
|
||||
{
|
||||
return (memcmp(&t1.mLargeObject1, &t2.mLargeObject1, sizeof(t1.mLargeObject1)) < 0) &&
|
||||
(memcmp(&t1.mLargeObject2, &t2.mLargeObject2, sizeof(t1.mLargeObject2)) < 0) &&
|
||||
(strcmp(t1.mpName1, t2.mpName1) < 0) &&
|
||||
(strcmp(t1.mpName2, t2.mpName2) < 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // Header sentry
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) Electronic Arts Inc. All rights reserved.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "EASTLBenchmark.h"
|
||||
#include "EASTLTest.h"
|
||||
#if !EASTL_OPENSOURCE
|
||||
#include <PPMalloc/EAGeneralAllocatorDebug.h>
|
||||
#endif
|
||||
#include <EAStdC/EASprintf.h>
|
||||
#include <EAStdC/EAStopwatch.h>
|
||||
#include <EAStdC/EAString.h>
|
||||
#include <EASTL/internal/config.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
EA_DISABLE_VC_WARNING(4946)
|
||||
#include "EAMain/EAEntryPointMain.inl"
|
||||
#include "EASTLTestAllocator.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// gpEAGeneralAllocator / gpEAGeneralAllocatorDebug
|
||||
//
|
||||
#if !EASTL_OPENSOURCE
|
||||
namespace EA
|
||||
{
|
||||
namespace Allocator
|
||||
{
|
||||
#ifdef EA_DEBUG
|
||||
extern GeneralAllocatorDebug gGeneralAllocator;
|
||||
extern PPM_API GeneralAllocatorDebug* gpEAGeneralAllocatorDebug;
|
||||
#else
|
||||
extern GeneralAllocator gGeneralAllocator;
|
||||
extern PPM_API GeneralAllocator* gpEAGeneralAllocator;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Required by EASTL.
|
||||
//
|
||||
#if !defined(EASTL_EASTDC_VSNPRINTF) || !EASTL_EASTDC_VSNPRINTF
|
||||
int Vsnprintf8(char8_t* pDestination, size_t n, const char8_t* pFormat, va_list arguments)
|
||||
{
|
||||
return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);
|
||||
}
|
||||
|
||||
int Vsnprintf16(char16_t* pDestination, size_t n, const char16_t* pFormat, va_list arguments)
|
||||
{
|
||||
return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);
|
||||
}
|
||||
|
||||
#if (EASTDC_VERSION_N >= 10600)
|
||||
int Vsnprintf32(char32_t* pDestination, size_t n, const char32_t* pFormat, va_list arguments)
|
||||
{
|
||||
return EA::StdC::Vsnprintf(pDestination, n, pFormat, arguments);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// main
|
||||
//
|
||||
int EAMain(int argc, char* argv[])
|
||||
{
|
||||
bool bWaitAtEnd = false;
|
||||
bool bPrintHelp = false;
|
||||
int nOptionCount = 0;
|
||||
int nErrorCount = 0;
|
||||
|
||||
EA::EAMain::PlatformStartup();
|
||||
EA::EAMain::SetVerbosity(2); // Default value.
|
||||
|
||||
// Set up debug parameters.
|
||||
#ifdef EA_DEBUG
|
||||
// Only enable this temporarily to help find any problems you might find.
|
||||
// EA::Allocator::gpEAGeneralAllocatorDebug->SetAutoHeapValidation(EA::Allocator::GeneralAllocator::kHeapValidationLevelBasic, 16);
|
||||
#endif
|
||||
|
||||
// Parse command line arguments
|
||||
for(int i = 1; i < argc; i++)
|
||||
{
|
||||
if(strstr(argv[i], "-w") == argv[i])
|
||||
{
|
||||
bWaitAtEnd = true;
|
||||
nOptionCount++;
|
||||
}
|
||||
else if(strstr(argv[i], "-v") == argv[i])
|
||||
{
|
||||
uint32_t verbosity = EA::StdC::AtoU32(argv[i] + 3);
|
||||
EA::EAMain::SetVerbosity(verbosity);
|
||||
nOptionCount++;
|
||||
}
|
||||
else if(strstr(argv[i], "-l:") == argv[i])
|
||||
{
|
||||
gEASTL_TestLevel = atoi(argv[i] + 3);
|
||||
if(gEASTL_TestLevel < kEASTL_TestLevelLow)
|
||||
gEASTL_TestLevel = kEASTL_TestLevelLow;
|
||||
else if(gEASTL_TestLevel > kEASTL_TestLevelHigh)
|
||||
gEASTL_TestLevel = kEASTL_TestLevelHigh;
|
||||
nOptionCount++;
|
||||
}
|
||||
else if(strstr(argv[i], "-s:") == argv[i])
|
||||
{
|
||||
uint32_t seed = (eastl_size_t)atoi(argv[i] + 3);
|
||||
EA::UnitTest::SetRandSeed(seed);
|
||||
nOptionCount++;
|
||||
}
|
||||
else if((strstr(argv[i], "-?") == argv[i]) || (strstr(argv[i], "-h") == argv[i]))
|
||||
{
|
||||
bPrintHelp = true;
|
||||
nOptionCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Print user help.
|
||||
if(!bPrintHelp)
|
||||
bPrintHelp = (nOptionCount == 0);
|
||||
|
||||
if(bPrintHelp)
|
||||
{
|
||||
EASTLTest_Printf("Options\n");
|
||||
EASTLTest_Printf(" -w Wait at end.\n");
|
||||
EASTLTest_Printf(" -l:N Test level in range of [1, 10]. 10 means maximum testing.\n");
|
||||
EASTLTest_Printf(" -s:N Specify a randomization seed. 0 is default and means use clock.\n");
|
||||
EASTLTest_Printf(" -? Show help.\n");
|
||||
}
|
||||
|
||||
|
||||
// Set up test information
|
||||
Benchmark::Environment& environment = Benchmark::GetEnvironment();
|
||||
environment.msPlatform = EA_PLATFORM_DESCRIPTION;
|
||||
environment.msSTLName1 = GetStdSTLName();
|
||||
environment.msSTLName2 = "EASTL";
|
||||
|
||||
|
||||
// Run tests
|
||||
#ifndef EA_DEBUG
|
||||
EA::UnitTest::SetHighThreadPriority();
|
||||
#endif
|
||||
|
||||
EA::StdC::Stopwatch stopwatch(EA::StdC::Stopwatch::kUnitsSeconds, true); // Measure seconds, start the counting immediately.
|
||||
|
||||
BenchmarkAlgorithm();
|
||||
BenchmarkList();
|
||||
BenchmarkString();
|
||||
BenchmarkVector();
|
||||
BenchmarkDeque();
|
||||
BenchmarkSet();
|
||||
BenchmarkMap();
|
||||
BenchmarkHash();
|
||||
BenchmarkHeap();
|
||||
BenchmarkBitset();
|
||||
BenchmarkSort();
|
||||
BenchmarkTupleVector();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
#ifndef EA_DEBUG
|
||||
EA::UnitTest::SetNormalThreadPriority();
|
||||
#endif
|
||||
|
||||
Benchmark::PrintResults();
|
||||
|
||||
eastl::string sClockTime;
|
||||
Benchmark::WriteTime(stopwatch.GetElapsedTime(), sClockTime);
|
||||
|
||||
EASTLTest_Printf("Time to complete all tests: %s.\n", sClockTime.c_str());
|
||||
|
||||
// Done
|
||||
if(bWaitAtEnd)
|
||||
{
|
||||
EASTLTest_Printf("\nPress any key to exit.\n");
|
||||
getchar(); // Wait for the user and shutdown
|
||||
}
|
||||
|
||||
EA::EAMain::PlatformShutdown(nErrorCount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user