[*] Updated tests
(linux almost certainly will not build post net connect multiple endpoints commit)
This commit is contained in:
parent
d22eb40b4e
commit
709cb9ca97
@ -1 +1 @@
|
||||
Subproject commit 122fc74a669596e200481ada884497854d07c5d1
|
||||
Subproject commit b61015a6a5fabbdc28f3f4229344c5437d0c26a4
|
@ -1 +1 @@
|
||||
Subproject commit 85a575eb9531d92c67cae5a547206494b55f4ebf
|
||||
Subproject commit 62c29d060062f4add0c5c4b59ccad5dde0c3d937
|
@ -1 +1 @@
|
||||
Subproject commit 1e9053b9383167eca317a941945ecf5d6a61aed4
|
||||
Subproject commit 91ee13089027fe3ff80a9514238c5c394ffd2e02
|
29
Build_UserScripts/brotli.aurora.json
Normal file
29
Build_UserScripts/brotli.aurora.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "brotli",
|
||||
"type": "generic",
|
||||
"include": "c/include",
|
||||
"sources": [
|
||||
"c/common/**.*",
|
||||
"c/dec/**.*",
|
||||
"c/enc/**.*",
|
||||
"c/include/**.*"
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"filter": {
|
||||
"platforms": "mac"
|
||||
},
|
||||
"then": {
|
||||
"defines": "OS_MACOSX"
|
||||
}
|
||||
},
|
||||
{
|
||||
"filter": {
|
||||
"platforms": "linux"
|
||||
},
|
||||
"then": {
|
||||
"defines": "OS_LINUX"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -150,6 +150,50 @@ TEST(Echo, BenchmarkLite)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FilterNames, GetIdx)
|
||||
{
|
||||
auto uIdx = AuLog::LogClassGetNext();
|
||||
ASSERT_TRUE(uIdx);
|
||||
AuLogDbg("Got unique id: {}", uIdx.value());
|
||||
AuLog::LogClassRelease(uIdx.value());
|
||||
}
|
||||
|
||||
TEST(FilterNames, GetIdx2)
|
||||
{
|
||||
auto uIdx = AuLog::LogClassGetNext();
|
||||
ASSERT_TRUE(uIdx);
|
||||
AuLogDbg("Got unique id: {} (same as last time? or +1 at least?))", uIdx.value());
|
||||
ASSERT_TRUE(AuLog::LogClassInUse(uIdx.value()));
|
||||
AuLog::LogClassRelease(uIdx.value());
|
||||
ASSERT_FALSE(AuLog::LogClassInUse(uIdx.value()));
|
||||
ASSERT_FALSE(AuLog::LogClassInUse(uIdx.value() - 1));
|
||||
}
|
||||
|
||||
TEST(FilterNames, GetIdx3)
|
||||
{
|
||||
auto uIdx = AuLog::LogClassGetNext();
|
||||
ASSERT_TRUE(uIdx);
|
||||
AuLogDbg("Got unique id: {} (same as last time? or +1 at least?))", uIdx.value());
|
||||
ASSERT_TRUE(AuLog::LogClassInUse(uIdx.value()));
|
||||
AuLog::LogClassRelease(uIdx.value());
|
||||
ASSERT_FALSE(AuLog::LogClassInUse(uIdx.value()));
|
||||
ASSERT_FALSE(AuLog::LogClassInUse(uIdx.value() - 1));
|
||||
}
|
||||
|
||||
TEST(FilterNames, Strings)
|
||||
{
|
||||
auto uIdx = AuLog::LogClassGetNext();
|
||||
ASSERT_TRUE(uIdx);
|
||||
AuLogDbg("Got unique id: {} (same as last time? or +1 at least?))", uIdx.value());
|
||||
ASSERT_TRUE(AuLog::LogClassInUse(uIdx.value()));
|
||||
static const auto kString = "hello world";
|
||||
AuLog::LogClassAssociateName(uIdx.value(), kString);
|
||||
ASSERT_EQ(AuLog::LogClassGetNameUnsafe(uIdx.value()), kString);
|
||||
AuLog::LogClassRelease(uIdx.value());
|
||||
ASSERT_FALSE(AuLog::LogClassInUse(uIdx.value()));
|
||||
ASSERT_TRUE(AuLog::LogClassGetNameUnsafe(uIdx.value()).empty());
|
||||
}
|
||||
|
||||
void RunTests()
|
||||
{
|
||||
Aurora::RuntimeStartInfo info;
|
||||
|
@ -226,7 +226,7 @@ TEST(Net, ConnectGoogleIP2022)
|
||||
|
||||
AuNet::NetSocketConnect nsConnect;
|
||||
nsConnect.pDriver = pDriver;
|
||||
nsConnect.endpoint = AuNet::NetEndpoint(AuNet::ETransportProtocol::eProtocolTCP, kHTTP11Address, 80);
|
||||
nsConnect.endpoint = AuNet::NetEndpoint(AuNet::ETransportProtocol::eProtocolTCP, kHTTP11Address, 80);
|
||||
|
||||
auto pSocket = pNetProcessor->GetSocketService()->Connect(nsConnect);
|
||||
ASSERT_TRUE(bool(pSocket));
|
||||
@ -237,6 +237,178 @@ TEST(Net, ConnectGoogleIP2022)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Net, ConnectGoogleIP2022SingleshotEvent)
|
||||
{
|
||||
auto pIoProcessor = AuIO::NewIOProcessorNoQueue(false);
|
||||
ASSERT_TRUE(bool(pIoProcessor));
|
||||
|
||||
auto pNetProcessor = AuNet::NewNetworkInterface();
|
||||
ASSERT_TRUE(bool(pNetProcessor));
|
||||
|
||||
auto pNetWorker = pNetProcessor->GetWorkersService()->Attach(pIoProcessor);
|
||||
ASSERT_TRUE(bool(pNetWorker));
|
||||
|
||||
auto pStats = AuMakeShared<DriverStat>();
|
||||
ASSERT_TRUE(bool(pStats));
|
||||
|
||||
auto pDriver = NewTestSocketDriver(pStats);
|
||||
ASSERT_TRUE(bool(pDriver));
|
||||
|
||||
auto pRealDriver = AuMakeShared<AuNet::ISocketDriverFunctional>();
|
||||
|
||||
static AuSPtr<AuNet::ISocket> gDriverSocket;
|
||||
pRealDriver->OnPreestablishFunctional = [&](const AuSPtr<AuNet::ISocket> &socket) -> bool
|
||||
{
|
||||
gDriverSocket = socket;
|
||||
return true;
|
||||
};
|
||||
|
||||
pRealDriver->OnEstablishFunctional = [&]()
|
||||
{
|
||||
auto pChannel = gDriverSocket->ToChannel();
|
||||
pChannel->AsStreamWriter()->Write(AuMemoryViewRead("GET / HTTP/1.1\r\nConnection: close\r\n\r\n", 37));
|
||||
};
|
||||
|
||||
pRealDriver->OnFatalErrorReportedFunctional = [&](const AuNet::NetError &error)
|
||||
{
|
||||
AuLogDbg("[3] On error: {}", NetErrorToExtendedString(error));
|
||||
};
|
||||
|
||||
pRealDriver->OnStreamUpdatedFunctional = [&]()
|
||||
{
|
||||
auto pChannel = gDriverSocket->ToChannel();
|
||||
auto pReader = pChannel->AsReadableByteBuffer();
|
||||
|
||||
AuString message;
|
||||
message.resize(pReader->RemainingBytes());
|
||||
pReader->Read(message.data(), message.size());
|
||||
|
||||
AuLogDbg("Stream updated: {}", message);
|
||||
};
|
||||
|
||||
pDriver->pProxy = pRealDriver;
|
||||
|
||||
AuNet::NetSocketConnect nsConnect;
|
||||
nsConnect.pDriver = pDriver;
|
||||
nsConnect.endpoint = AuNet::NetEndpoint(AuNet::ETransportProtocol::eProtocolTCP, kHTTP11Address, 80);
|
||||
|
||||
auto pSocket = pNetProcessor->GetSocketService()->Connect(nsConnect);
|
||||
ASSERT_TRUE(bool(pSocket));
|
||||
|
||||
|
||||
auto pSocketListener = AuMakeShared<AuNet::ISocketChannelEventListenerFunctional>();
|
||||
pSocketListener->OnDataFunctional = []()
|
||||
{
|
||||
AuLogDbg("ISocketChannelEventListenerFunctional::OnDataFunctional");
|
||||
// singleshot / reject after 1
|
||||
return false;
|
||||
};
|
||||
|
||||
pSocketListener->OnRejectedFunctional = []()
|
||||
{
|
||||
AuLogDbg("ISocketChannelEventListenerFunctional::OnRejectedFunctional");
|
||||
};
|
||||
|
||||
pSocketListener->OnCompleteFunctional = []()
|
||||
{
|
||||
AuLogDbg("ISocketChannelEventListenerFunctional::OnCompleteFunctional");
|
||||
};
|
||||
|
||||
pSocket->ToChannel()->AddEventListener(pSocketListener);
|
||||
|
||||
while (pIoProcessor->HasItems())
|
||||
{
|
||||
pIoProcessor->RunTick();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(Net, ConnectGoogleIP2022Multiple)
|
||||
{
|
||||
auto pIoProcessor = AuIO::NewIOProcessorNoQueue(false);
|
||||
ASSERT_TRUE(bool(pIoProcessor));
|
||||
|
||||
auto pNetProcessor = AuNet::NewNetworkInterface();
|
||||
ASSERT_TRUE(bool(pNetProcessor));
|
||||
|
||||
auto pNetWorker = pNetProcessor->GetWorkersService()->Attach(pIoProcessor);
|
||||
ASSERT_TRUE(bool(pNetWorker));
|
||||
|
||||
auto pStats = AuMakeShared<DriverStat>();
|
||||
ASSERT_TRUE(bool(pStats));
|
||||
|
||||
auto pDriver = NewTestSocketDriver(pStats);
|
||||
ASSERT_TRUE(bool(pDriver));
|
||||
|
||||
auto pRealDriver = AuMakeShared<AuNet::ISocketDriverFunctional>();
|
||||
|
||||
static AuSPtr<AuNet::ISocket> gDriverSocket;
|
||||
pRealDriver->OnPreestablishFunctional = [&](const AuSPtr<AuNet::ISocket> &socket) -> bool
|
||||
{
|
||||
gDriverSocket = socket;
|
||||
return true;
|
||||
};
|
||||
|
||||
pRealDriver->OnEstablishFunctional = [&]()
|
||||
{
|
||||
auto pChannel = gDriverSocket->ToChannel();
|
||||
pChannel->AsStreamWriter()->Write(AuMemoryViewRead("GET / HTTP/1.1\r\nConnection: close\r\n\r\n", 37));
|
||||
};
|
||||
|
||||
pRealDriver->OnFatalErrorReportedFunctional = [&](const AuNet::NetError &error)
|
||||
{
|
||||
AuLogDbg("[3] On error: {}", NetErrorToExtendedString(error));
|
||||
};
|
||||
|
||||
pRealDriver->OnStreamUpdatedFunctional = [&]()
|
||||
{
|
||||
auto pChannel = gDriverSocket->ToChannel();
|
||||
auto pReader = pChannel->AsReadableByteBuffer();
|
||||
|
||||
AuString message;
|
||||
message.resize(pReader->RemainingBytes());
|
||||
pReader->Read(message.data(), message.size());
|
||||
|
||||
AuLogDbg("Stream updated: {}", message);
|
||||
};
|
||||
|
||||
pDriver->pProxy = pRealDriver;
|
||||
|
||||
AuNet::NetSocketConnect nsConnect;
|
||||
nsConnect.pDriver = pDriver;
|
||||
nsConnect.endpoint = AuNet::NetEndpoint(AuNet::ETransportProtocol::eProtocolTCP, kHTTP11Address, 80);
|
||||
|
||||
auto pSocket = pNetProcessor->GetSocketService()->Connect(nsConnect);
|
||||
ASSERT_TRUE(bool(pSocket));
|
||||
|
||||
|
||||
auto pSocketListener = AuMakeShared<AuNet::ISocketChannelEventListenerFunctional>();
|
||||
pSocketListener->OnDataFunctional = []()
|
||||
{
|
||||
AuLogDbg("ISocketChannelEventListenerFunctional::OnDataFunctional (multiple)");
|
||||
return true;
|
||||
};
|
||||
|
||||
pSocketListener->OnRejectedFunctional = []()
|
||||
{
|
||||
AuLogDbg("ISocketChannelEventListenerFunctional::OnRejectedFunctional (multiple)");
|
||||
};
|
||||
|
||||
pSocketListener->OnCompleteFunctional = []()
|
||||
{
|
||||
AuLogDbg("ISocketChannelEventListenerFunctional::OnCompleteFunctional (multiple)");
|
||||
};
|
||||
|
||||
pSocket->ToChannel()->AddEventListener(pSocketListener);
|
||||
|
||||
while (pIoProcessor->HasItems())
|
||||
{
|
||||
pIoProcessor->RunTick();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Resolve, GoogleA)
|
||||
{
|
||||
auto pIoProcessor = AuIO::NewIOProcessorNoQueue(false);
|
||||
@ -301,33 +473,6 @@ TEST(Resolve, GoogleAAAA)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Adapters, Print)
|
||||
{
|
||||
auto pNetProcessor = AuNet::NewNetworkInterface();
|
||||
ASSERT_TRUE(bool(pNetProcessor));
|
||||
|
||||
AuLogInfo("Hostname: {}", pNetProcessor->GetInterfacesService()->GetHostname());
|
||||
|
||||
auto ifaces = pNetProcessor->GetInterfacesService()->GetAdapters();
|
||||
for (const auto &pAdapter : ifaces)
|
||||
{
|
||||
AuString dns = "";
|
||||
for (const auto &dnsIP : pAdapter->GetDNS())
|
||||
{
|
||||
dns += fmt::format(" dns-server={}", dnsIP.ToString());
|
||||
}
|
||||
|
||||
AuLogInfo("Found adapter interface (family: {}): \n\tName: {}\n\tDevice: {}\n\tAddress: {}\n\tMulticast: {}\n\tGateway: {}\n\tDNS: {}\n\n",
|
||||
AuNet::EIPProtocolToString(pAdapter->ToFamily()),
|
||||
pAdapter->ToName(),
|
||||
pAdapter->ToDevice(),
|
||||
pAdapter->ToAddress().ToString(),
|
||||
pAdapter->ToBroadcastAddress().ToString(),
|
||||
pAdapter->ToGateway().ToString(),
|
||||
dns);
|
||||
}
|
||||
}
|
||||
|
||||
void RunTests()
|
||||
{
|
||||
Aurora::RuntimeStartInfo info;
|
||||
|
@ -81,7 +81,6 @@ TEST(DemoTelemetryPoke, TelemetryHint)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Demo, ThrowStringLiteral)
|
||||
{
|
||||
try
|
||||
@ -100,11 +99,6 @@ TEST(DemoTelemetryPoke, ErrnoHint)
|
||||
AuDebug::CheckErrors();
|
||||
}
|
||||
|
||||
TEST(DemoSysError, AA)
|
||||
{
|
||||
SysPushErrorGeneric("Hello World");
|
||||
}
|
||||
|
||||
TEST(DemoAssert, A)
|
||||
{
|
||||
SysAssertExp(true, "i will not fail {}", 100);
|
||||
|
@ -8,6 +8,65 @@
|
||||
#include <AuroraRuntime.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#define TO_PROVE_A_POINT
|
||||
#include <shared_mutex>
|
||||
#include <windows.h>
|
||||
#include <semaphore>
|
||||
#endif
|
||||
|
||||
TEST(Allocationless, SOO)
|
||||
{
|
||||
AuThreadPrimitives::ConditionMutexSOO condMutex;
|
||||
AuThreadPrimitives::ConditionVariableSOO condVariable(AuUnsafeRaiiToShared(condMutex.AsPointer()));
|
||||
AuThreadPrimitives::MutexSOO mutex;
|
||||
AuThreadPrimitives::EventSOO event(false, true, false);
|
||||
AuThreadPrimitives::SemaphoreSOO semaphore;
|
||||
AuThreadPrimitives::CriticalSectionSOO cs;
|
||||
AuThreadPrimitives::RWLockSOO rwLock;
|
||||
AuThreadPrimitives::RWRenterableLockSOO rwLock2;
|
||||
|
||||
#if defined(TO_PROVE_A_POINT)
|
||||
|
||||
static_assert(sizeof(AuThreadPrimitives::MutexSOO) < sizeof(std::mutex));
|
||||
static_assert(sizeof(AuThreadPrimitives::MutexSOO) <= sizeof(std::mutex) / 5); // to really prove a point
|
||||
// we can be up-to 4x faster, usually at least a few ms at scale.
|
||||
|
||||
static_assert(sizeof(AuThreadPrimitives::RWLockSOO) < sizeof(std::shared_timed_mutex));
|
||||
static_assert(sizeof(AuThreadPrimitives::RWLockSOO) < (sizeof(std::shared_timed_mutex) / 2));
|
||||
|
||||
static_assert(230 < sizeof(std::shared_timed_mutex));
|
||||
static_assert(103 < sizeof(AuThreadPrimitives::RWLockSOO));
|
||||
|
||||
static_assert(sizeof(AuThreadPrimitives::MutexSOO) < sizeof(SRWLOCK) + sizeof(CONDITION_VARIABLE) + 4); // (SRWLOCKs are too dumb to used by themselves)
|
||||
static_assert(sizeof(AuThreadPrimitives::ConditionVariableSOO) < sizeof(std::condition_variable));
|
||||
static_assert(sizeof(AuThreadPrimitives::ConditionMutexSOO) < sizeof(std::mutex));
|
||||
static_assert(sizeof(AuThreadPrimitives::CriticalSectionSOO) < sizeof(CRITICAL_SECTION));
|
||||
static_assert(sizeof(AuThreadPrimitives::MutexSOO) <= sizeof(SRWLOCK) + 8 /*vtable*/); // should be more featureful than a SRWLock
|
||||
|
||||
// Optimized OS range given this SOO overhead: Windows NT 5.1 through Win 11.
|
||||
// AuRT could be dropped down to XP, if not for other subsystems and deps.
|
||||
|
||||
ASSERT_TRUE(AuSwInfo::IsWindowsXPOrGreater()); // ok this doesnt prove a point, but still
|
||||
ASSERT_FALSE(!AuSwInfo::IsWindowsXPOrGreater());
|
||||
|
||||
// 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
// here's some fails where you might be able optimize a bit if you cared so deeply about shaving a few bytes off for
|
||||
// less optimization, more slow compatibility layers, and lower res yielding, just to, i dont know, be forced into
|
||||
// "windows 8+ optimization?" "ucrt optimization?" to save like 8-16 bytes???
|
||||
#if 0
|
||||
static_assert(sizeof(AuThreadPrimitives::SemaphoreSOO) <= sizeof(SRWLOCK) + sizeof(CONDITION_VARIABLE) + 4);
|
||||
static_assert(sizeof(AuThreadPrimitives::MutexSOO) <= sizeof(SRWLOCK));
|
||||
static_assert(sizeof(AuThreadPrimitives::RWLockSOO) <= sizeof(std::shared_lock<std::shared_mutex>)); // optimized around winshit apis, not IWaitable
|
||||
// note: performance will suffer under the stl under older windows versions
|
||||
|
||||
static_assert(sizeof(AuThreadPrimitives::SemaphoreSOO) <= sizeof(std::counting_semaphore)); // once again, this is optimized for a win8+ interface, and will suffer under older oses
|
||||
// wont cuck our apis into being this small and intentionally bad. im not microsoft.
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Single threaded mutex lock test (rentrant mutexes are called critical sections in this subsystem)
|
||||
*/
|
||||
@ -18,12 +77,185 @@ TEST(Mutex, LockTest)
|
||||
ASSERT_FALSE(mutex->TryLock());
|
||||
mutex->Unlock();
|
||||
ASSERT_TRUE(mutex->TryLock());
|
||||
ASSERT_FALSE(mutex->Lock(10));
|
||||
ASSERT_FALSE(mutex->LockMS(10));
|
||||
mutex->Unlock();
|
||||
ASSERT_TRUE(mutex->TryLock());
|
||||
mutex->Unlock();
|
||||
}
|
||||
|
||||
TEST(Mutex, Benchmark)
|
||||
{
|
||||
{
|
||||
SysBenchmark("Mutex Benchmark 1'000'000");
|
||||
|
||||
for (AU_ITERATE_N(i, 1'000'000))
|
||||
{
|
||||
AuThreadPrimitives::MutexSOO mutex;
|
||||
AU_LOCK_GUARD(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
SysBenchmark("Mutex 2 Benchmark 1'000'000 [no-new]");
|
||||
|
||||
AuThreadPrimitives::MutexSOO mutex;
|
||||
for (AU_ITERATE_N(i, 1'000'000))
|
||||
{
|
||||
AU_LOCK_GUARD(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// Windows 7 users should see a 14-20ms deviation here!!!
|
||||
// Windows 8-11 users should see a 8ms deviation here!!!
|
||||
// (relative to Mutex 1 Benchmark)
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
{
|
||||
SysBenchmark("Mutex 3 Benchmark 1'000'000 [MS-STL]");
|
||||
|
||||
for (AU_ITERATE_N(i, 1'000'000))
|
||||
{
|
||||
std::mutex mutex;
|
||||
std::lock_guard gross(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// Windows 7 users should see a 8-15ms deviation here!!!
|
||||
// Windows 8-11 users should see a 8ms deviation here!!!
|
||||
// (relative to Mutex 2 Benchmark)
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
{
|
||||
SysBenchmark("Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL]");
|
||||
|
||||
std::mutex mutex;
|
||||
for (AU_ITERATE_N(i, 1'000'000))
|
||||
{
|
||||
std::lock_guard gross(mutex);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// Windows Vista through Windows 11 users should see a 2-3ms deviation here!!!
|
||||
// (relative to Mutex 1 Benchmark)
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
{
|
||||
SysBenchmark("Mutex 5 Benchmark 1'000'000 [SRW-Lock]");
|
||||
|
||||
for (AU_ITERATE_N(i, 1'000'000))
|
||||
{
|
||||
SRWLOCK lock;
|
||||
InitializeSRWLock(&lock);
|
||||
AcquireSRWLockExclusive(&lock);
|
||||
ReleaseSRWLockExclusive(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// Windows Vista through Windows 11 users should see a 4-5ms deviation here!!!
|
||||
// (relative to Mutex 2 Benchmark)
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
{
|
||||
SysBenchmark("Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock]");
|
||||
|
||||
SRWLOCK lock;
|
||||
InitializeSRWLock(&lock);
|
||||
|
||||
for (AU_ITERATE_N(i, 1'000'000))
|
||||
{
|
||||
AcquireSRWLockExclusive(&lock);
|
||||
ReleaseSRWLockExclusive(&lock);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
Windows 7, i9 9900k (Q4 2018) @ 5GHz under KVM (v5.16.16), modified OVMF/EDK II, and modified QEMU:
|
||||
08:13:17 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 10.23965ms
|
||||
08:13:17 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 8.14648ms
|
||||
08:13:17 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 22.51583ms
|
||||
08:13:17 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 18.39793ms
|
||||
08:13:17 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 12.35815ms
|
||||
08:13:17 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 11.59034ms
|
||||
|
||||
08:13:47 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 10.36226ms
|
||||
08:13:47 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 8.37862ms
|
||||
08:13:47 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 21.23885ms
|
||||
08:13:47 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 19.33754ms
|
||||
08:13:47 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 12.31698ms
|
||||
08:13:47 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 11.25236ms
|
||||
|
||||
08:14:45 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 10.64171ms
|
||||
08:14:45 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 8.151ms
|
||||
08:14:45 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 26.10599ms
|
||||
08:14:45 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 20.5948ms
|
||||
08:14:45 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 13.47083ms
|
||||
08:14:45 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 12.53163ms
|
||||
|
||||
08:15:21 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 10.10466ms
|
||||
08:15:21 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 8.74967ms
|
||||
08:15:21 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 24.1452ms
|
||||
08:15:21 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 17.68036ms
|
||||
08:15:21 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 12.21169ms
|
||||
08:15:21 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 11.26151ms
|
||||
|
||||
08:18:35 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 12.05167ms
|
||||
08:18:35 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 8.80412ms
|
||||
08:18:35 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 27.12312ms
|
||||
08:18:35 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 20.42462ms
|
||||
08:18:35 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 12.6167ms
|
||||
08:18:35 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 12.41549ms
|
||||
|
||||
08:28:07 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 12.85569ms
|
||||
08:28:07 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 9.33194ms
|
||||
08:28:07 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 21.12753ms
|
||||
08:28:07 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 20.86612ms
|
||||
08:28:07 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 12.4472ms
|
||||
08:28:07 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 11.39755ms|
|
||||
|
||||
Windows 11, i9 9900k (Q4 2018) @ 5GHz under KVM (v5.16.16) and stock OVMF/EDK II bootstrapped by stock QEMU (v7.1.) via libvirtd:
|
||||
TBD
|
||||
|
||||
Windows 11, i7 12700kf (Q4 2021) @ Turbo 5 GHz:
|
||||
13:37:43 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 8.4802ms
|
||||
13:37:43 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 7.2406ms
|
||||
13:37:43 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 15.6057ms
|
||||
13:37:43 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 12.0535ms
|
||||
13:37:44 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 14.4723ms
|
||||
13:37:44 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 11.7877ms
|
||||
|
||||
13:38:54 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 8.3546ms
|
||||
13:38:54 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 7.0924ms
|
||||
13:38:54 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 15.6814ms
|
||||
13:38:54 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 11.9347ms
|
||||
13:38:54 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 14.4644ms
|
||||
13:38:54 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 11.7549ms
|
||||
|
||||
13:39:37 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 8.3741ms
|
||||
13:39:37 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 7.105ms
|
||||
13:39:37 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 15.4845ms
|
||||
13:39:37 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 11.9213ms
|
||||
13:39:37 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 14.432ms
|
||||
13:39:37 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 11.759ms
|
||||
|
||||
13:40:14 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 8.3792ms
|
||||
13:40:14 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 7.1186ms
|
||||
13:40:14 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 16.3227ms
|
||||
13:40:14 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 11.7837ms
|
||||
13:40:14 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 15.9249ms
|
||||
13:40:14 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 11.4668ms
|
||||
|
||||
13:40:47 [Debug] | [Benchmark] Mutex Benchmark 1'000'000 took 8.3893ms
|
||||
13:40:47 [Debug] | [Benchmark] Mutex 2 Benchmark 1'000'000 [no-new] took 7.0334ms
|
||||
13:40:47 [Debug] | [Benchmark] Mutex 3 Benchmark 1'000'000 [MS-STL] took 16.3345ms
|
||||
13:40:47 [Debug] | [Benchmark] Mutex 4 Benchmark 1'000'000 [no-new] [MS-STL] took 11.7077ms
|
||||
13:40:47 [Debug] | [Benchmark] Mutex 5 Benchmark 1'000'000 [SRW-Lock] took 16.5125ms
|
||||
13:40:47 [Debug] | [Benchmark] Mutex 6 Benchmark 1'000'000 [no-new] [SRW-Lock] took 11.148ms
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Spinlock lock test
|
||||
*/
|
||||
@ -34,7 +266,7 @@ TEST(Spinlock, LockTest)
|
||||
ASSERT_FALSE(mutex.TryLock());
|
||||
mutex.Unlock();
|
||||
ASSERT_TRUE(mutex.TryLock());
|
||||
ASSERT_FALSE(mutex.Lock(10));
|
||||
ASSERT_FALSE(mutex.LockMS(10));
|
||||
mutex.Unlock();
|
||||
ASSERT_TRUE(mutex.TryLock());
|
||||
mutex.Unlock();
|
||||
@ -49,7 +281,7 @@ TEST(Semaphore, LockTest)
|
||||
ASSERT_FALSE(semaphore->TryLock());
|
||||
semaphore->Unlock(1);
|
||||
ASSERT_TRUE(semaphore->TryLock());
|
||||
ASSERT_FALSE(semaphore->Lock(10));
|
||||
ASSERT_FALSE(semaphore->LockMS(10));
|
||||
semaphore->Unlock(2);
|
||||
ASSERT_TRUE(semaphore->TryLock());
|
||||
ASSERT_TRUE(semaphore->TryLock());
|
||||
@ -118,7 +350,7 @@ TEST(RWLocks, GodMode2)
|
||||
|
||||
// Test write-entrancy
|
||||
{
|
||||
AU_LOCK_GUARD(rwlock->AsWritable())
|
||||
AU_LOCK_GUARD(rwlock->AsWritable());
|
||||
|
||||
// Enter read routines
|
||||
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
|
||||
@ -135,7 +367,6 @@ TEST(RWLocks, GodMode2)
|
||||
rwlock->AsReadable()->Unlock();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Test write-entrant read-routines w/ write-mode escalation
|
||||
*
|
||||
@ -172,7 +403,214 @@ TEST(RWLocks, SlashGod)
|
||||
rwlock->AsReadable()->Unlock();
|
||||
}
|
||||
|
||||
// Test RWLocks in critical section mode
|
||||
TEST(RWLocks, DoubleReentrant)
|
||||
{
|
||||
AuThreadPrimitives::RWRenterableLockSOO rwlock;
|
||||
|
||||
// Test exclusive ownership
|
||||
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
|
||||
ASSERT_FALSE(rwlock->AsWritable()->TryLock());
|
||||
rwlock->AsReadable()->Unlock();
|
||||
|
||||
// Test write-entrancy
|
||||
{
|
||||
AU_LOCK_GUARD(rwlock->AsWritable());
|
||||
|
||||
// test thread-local write-entrancy
|
||||
AU_LOCK_GUARD(rwlock->AsWritable());
|
||||
|
||||
// Enter read routines
|
||||
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
|
||||
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
|
||||
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
|
||||
|
||||
rwlock->AsReadable()->Unlock(); // NOP
|
||||
rwlock->AsReadable()->Unlock(); // NOP
|
||||
rwlock->AsReadable()->Unlock(); // NOP
|
||||
}
|
||||
|
||||
// Confirm release
|
||||
ASSERT_TRUE(rwlock->AsReadable()->TryLock());
|
||||
rwlock->AsReadable()->Unlock();
|
||||
}
|
||||
|
||||
TEST(WakeOnAddress, WaitOnConstantForTimeout5Milliseconds)
|
||||
{
|
||||
ASSERT_TRUE(AuSwInfo::IsWindowsXPOrGreater() || AuBuild::kIsLinuxDerived || true); // heres your forced thy must upgrade to windows 8+ "limitation"
|
||||
|
||||
AuUInt32 uAtomic {};
|
||||
AuUInt32 uExpect { 0 };
|
||||
|
||||
ASSERT_FALSE(AuThreading::WaitOnAddress(&uAtomic, &uExpect, sizeof(AuUInt32), AuMSToNS<AuUInt32>(5)));
|
||||
}
|
||||
|
||||
TEST(WakeOnAddress, WaitOnConstantForTimeout5Seconds)
|
||||
{
|
||||
ASSERT_TRUE(AuSwInfo::IsWindowsXPOrGreater() || AuBuild::kIsLinuxDerived || true);
|
||||
|
||||
AuUInt32 uAtomic {};
|
||||
AuUInt32 uExpect { 0 };
|
||||
|
||||
ASSERT_FALSE(AuThreading::WaitOnAddress(&uAtomic, &uExpect, sizeof(AuUInt32), AuMSToNS<AuUInt64>(AuSToMS<AuUInt32>(5))));
|
||||
}
|
||||
|
||||
TEST(WakeOnAddress, WaitOnUnexpectedConstantForTimeout5Seconds)
|
||||
{
|
||||
ASSERT_TRUE(AuSwInfo::IsWindowsXPOrGreater() || AuBuild::kIsLinuxDerived || true);
|
||||
|
||||
AuUInt32 uAtomic { 0 };
|
||||
AuUInt32 uExpect { 1 };
|
||||
|
||||
ASSERT_TRUE(AuThreading::WaitOnAddress(&uAtomic, &uExpect, sizeof(AuUInt32), AuMSToNS<AuUInt64>(AuSToMS<AuUInt32>(5))));
|
||||
}
|
||||
|
||||
TEST(WaitOnAddress, WaitOnConstantForTimeout20SecondsUpdateAfter5)
|
||||
{
|
||||
ASSERT_TRUE(AuSwInfo::IsWindowsXPOrGreater() || AuBuild::kIsLinuxDerived || true);
|
||||
|
||||
AuUInt32 uAtomic { 0 };
|
||||
AuUInt32 uExpect { 0 };
|
||||
AuUInt32 uUpdate { 1 };
|
||||
AuUInt64 uEndTime { AuTime::SteadyClockNS() + AuMSToNS<AuUInt64>(AuSToMS<AuUInt64>(5)) };
|
||||
AuUInt64 uTimeFromAlert {};
|
||||
AuUInt64 uTimeToAlert {};
|
||||
|
||||
auto thread = AuThreads::ThreadUnique(AuThreads::ThreadInfo(
|
||||
AuMakeShared<AuThreads::IThreadVectorsFunctional>(
|
||||
[&](AuThreads::IAuroraThread *pThread)
|
||||
{
|
||||
while (uEndTime > AuTime::SteadyClockNS()) AuThreading::ContextYield();
|
||||
uAtomic = uUpdate;
|
||||
uTimeFromAlert = AuTime::SteadyClockNS();
|
||||
AuThreading::WakeOnAddress(&uAtomic);
|
||||
},
|
||||
AuThreads::IThreadVectorsFunctional::OnExit_t {}),
|
||||
"PokeWaitAddress"
|
||||
));
|
||||
|
||||
ASSERT_TRUE(bool(thread));
|
||||
|
||||
ASSERT_TRUE(thread->Run());
|
||||
|
||||
ASSERT_TRUE(AuThreading::WaitOnAddress(&uAtomic, &uExpect, sizeof(AuUInt32), AuMSToNS<AuUInt64>(AuSToMS<AuUInt32>(20))));
|
||||
|
||||
uTimeToAlert = AuTime::SteadyClockNS();
|
||||
AuLogDbg("[WaitOnAddress, WaitOnConstantForTimeout20SecondsUpdateAfter5] Time to alert: {}", uTimeToAlert - uTimeFromAlert);
|
||||
}
|
||||
|
||||
|
||||
TEST(WaitOnAddress, WaitOnConstantForTimeout20SecondsUpdateAfter50ms)
|
||||
{
|
||||
ASSERT_TRUE(AuSwInfo::IsWindowsXPOrGreater() || AuBuild::kIsLinuxDerived || true);
|
||||
|
||||
AuUInt32 uAtomic { 0 };
|
||||
AuUInt32 uExpect { 0 };
|
||||
AuUInt32 uUpdate { 1 };
|
||||
AuUInt64 uEndTime { };
|
||||
AuUInt64 uTimeFromAlert {};
|
||||
AuUInt64 uTimeToAlert {};
|
||||
AuThreadPrimitives::SemaphoreSOO semaphore;
|
||||
AuThreadPrimitives::SemaphoreSOO semaphore2;
|
||||
|
||||
auto thread = AuThreads::ThreadUnique(AuThreads::ThreadInfo(
|
||||
AuMakeShared<AuThreads::IThreadVectorsFunctional>(
|
||||
[&](AuThreads::IAuroraThread *pThread)
|
||||
{
|
||||
semaphore2->Unlock(1);
|
||||
semaphore->Lock();
|
||||
while (uEndTime > AuTime::SteadyClockNS()) AuThreading::ContextYield();
|
||||
uAtomic = uUpdate;
|
||||
uTimeFromAlert = AuTime::SteadyClockNS();
|
||||
AuThreading::WakeOnAddress(&uAtomic);
|
||||
},
|
||||
AuThreads::IThreadVectorsFunctional::OnExit_t {}),
|
||||
"PokeWaitAddress"
|
||||
));
|
||||
|
||||
ASSERT_TRUE(bool(thread));
|
||||
|
||||
ASSERT_TRUE(thread->Run());
|
||||
semaphore2->Lock();
|
||||
|
||||
{
|
||||
uEndTime = { AuTime::SteadyClockNS() + AuMSToNS<AuUInt64>(50) };
|
||||
semaphore->Unlock(1);
|
||||
|
||||
{
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// Windows 7 users as compared to Windows 8.1+/11 users should see a 0.02-0.05ms deviation here!!!
|
||||
// (Win7: ~24'000 - ~30'000 nanosecond overshoot from expected wakeup time)
|
||||
// (Win11: ~1'000 - 5'100 nanosecond overshoot from expected wakeup time)
|
||||
// (native windows 11 support blows us out of the water, but at least vista + 7 and/or installations
|
||||
// of legacy hardware arent left behind. even xp has an unoptimized implementation of the underlying
|
||||
// keyedevent primitive. though, you would be at the point of wanting an nt 4 fork to run well. )
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
SysBenchmark("WaitOnAddress/WakeOnAddress remote poke in 50ms");
|
||||
ASSERT_TRUE(AuThreading::WaitOnAddress(&uAtomic, &uExpect, sizeof(AuUInt32), AuMSToNS<AuUInt64>(AuSToMS<AuUInt32>(20))));
|
||||
uTimeToAlert = AuTime::SteadyClockNS();
|
||||
}
|
||||
|
||||
// ...Windows 7 again: expect to see a factor of 4-6x slowdown in time to wake
|
||||
// trust me bro numbers i9 9900k @ 5Ghz (emulated):
|
||||
// * rare undershoots: ~23'000
|
||||
// * more often than not ~24'700 - 38'000
|
||||
// * worst case peaks: ~55'000
|
||||
// * very very rarely: ~70'000
|
||||
// and Windows 11 (8+ native), i7 12700KF @ 5Ghz:
|
||||
// * rare undershoots: ~4'800
|
||||
// * more often than not ~5'100
|
||||
// * worst case peaks: ~30'000
|
||||
// and Windows 11 (8+ native), i7 12700KF @ 5Ghz (emulated - patched to force it):
|
||||
// * around: ~7'500
|
||||
// and Microsofts game developer docs state:
|
||||
// * expect 5,000 nanosecond switches on the Xbox
|
||||
// * target 1,000 switches per second (seems low?)
|
||||
//
|
||||
// " Use this topic to learn how to find threads that are frequently context switching—degrading your title's performance.
|
||||
// " Context switching is the process of storing the state of a thread so that it can be restored to resume execution at a later point in time.
|
||||
// " Rapid context switching between threads is expensive in terms of CPU utilization. Each context switch takes the kernel about 5 μs (on average) to process.
|
||||
// " However, the resulting Cache misses add additional execution time that is difficult to quantify.
|
||||
// " The more frequent the context switches, the more your CPU utilization degrades.
|
||||
// " Each title is different, but a reasonable goal is to have fewer than 1,000 context switches per second, per core. "
|
||||
// - GDK docs
|
||||
//
|
||||
// Tick-based kernels with out improved chipset drivers are indisputably 4-6 slower, yet its not in the ball park of mattering
|
||||
// Considering worst case of 0.05ms overshoots @ 144 hz using Microsofts suggested target switch rate of 1'000:
|
||||
// > (1000 - (0.005 * 1000 * 0)) / 144 (Best case)
|
||||
// 6.944444444444445
|
||||
//
|
||||
// > (1000 - (0.005 * 1000 * 1)) / 144 (Win11 best case)
|
||||
// 6.909722222222222
|
||||
//
|
||||
// > (1000 - (0.05 * 1000 * 1)) / 144 (Win 7 average ballpark)
|
||||
// 6.597222222222222
|
||||
//
|
||||
// > (1000 - (0.02 * 1000 * 1)) / 144 (Win 7 average ballpark)
|
||||
// 6.805555555555555
|
||||
//
|
||||
// > (1000 - (0.02 * 10000 * 1)) / 144 (0.02ms optimistic but reasonable, 10'000 iterations)
|
||||
// 5.555555555555555
|
||||
// ~= 1.4ms for 10'000 switches (?)
|
||||
//
|
||||
// > (1000 - (0.005 * 10000 * 1)) / 144 (Windows 11 worst case at 10'000 iterations)
|
||||
// 6.597222222222222
|
||||
// ~= 0.347ms for 10'000 switches (?)
|
||||
// ~4x slower in emulation mode UNDER a crippled kernel. Win10+ can be forced into emu mode and achieve much faster results.
|
||||
// ...implying the 4x slowdown is the improvement between os generations? not the sync interface?
|
||||
// ...maybe hardware?
|
||||
//
|
||||
// -> No real game-breaking difference in CPU time allocation for any given 144 Hhz frame. Even an order of magnitude increase wouldn't make a difference.
|
||||
// Two orders, maybe so; just don't target hundreds of thousands of switches per second. It should be possible to still get ok performance out of Windows 7.
|
||||
// Saving ~1ms in a frame allocation would be nice, but i'll take that trade-off for a sync primitive that doesnt exist.
|
||||
//
|
||||
// Note: Windows 7s best case, assuming atomics are always being followed and preemptive fast-paths are considered, should always match other unsupported
|
||||
// Operating Systems with comparable hardware. Specifically platforms without a known or stable futex interface.
|
||||
// That above mucho-texto is more representative of switch speeds in the worst case. Windows 11 under emulation mode will perform much much faster than 7.
|
||||
// Best and average cases (respecters of the smt backoff value - `uSpinLoopPowerA`) should be more comparable between emulated WaitOnAddress platforms.
|
||||
AuLogDbg("[WaitOnAddress, WaitOnConstantForTimeout20SecondsUpdateAfter50ms] Time to alert: {}", uTimeToAlert - uTimeFromAlert);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allocates a new thread, dispatches the ep, destroys the thread, and waits a reasonable amount of time
|
||||
@ -311,5 +749,8 @@ void RunTests()
|
||||
{
|
||||
Aurora::RuntimeStartInfo info;
|
||||
info.console.fio.enableLogging = false;
|
||||
info.threadingConfig.uSpinLoopPowerA = 7;
|
||||
Aurora::RuntimeStart(info);
|
||||
|
||||
AuThreads::GetThread()->SetPriority(AuThreads::EThreadPriority::ePrioRT);
|
||||
}
|
@ -147,6 +147,13 @@ TEST(Map, IPC)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Unmodified Windows 7 Runtimes will start to fail here.
|
||||
// It is possible to get this to run with the help of a driver.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(Reserve, HasInterface)
|
||||
{
|
||||
ASSERT_TRUE(bool(AuProcess::ReserveAddressSpace(4096 * 2)));
|
||||
|
@ -49,11 +49,15 @@ TEST(FS, WriteRead)
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
inputblob.writePtr = inputblob.base;
|
||||
|
||||
// Write and read back the RNG blob from a read/writable CWD
|
||||
ASSERT_TRUE(AuIOFS::WriteFile("./test_rng_blob", rngbuffer));
|
||||
ASSERT_TRUE(AuIOFS::ReadFile("./test_rng_blob", inputblob));
|
||||
ASSERT_EQ(inputblob, rngbuffer);
|
||||
|
||||
inputblob.writePtr = inputblob.base;
|
||||
|
||||
// Write and read back the RNG blob from a user specific application directory
|
||||
// Defer to brand: Aurora::RuntimeStartInfo#fio.defaultBrand
|
||||
ASSERT_TRUE(AuIOFS::WriteFile("~/my_app_rng_blob", rngbuffer));
|
||||
@ -359,6 +363,62 @@ static void PrintSystemRoot()
|
||||
// * file stream objects
|
||||
// * stat
|
||||
|
||||
|
||||
TEST(FS, TestBlock)
|
||||
{
|
||||
if (AuCmdLine::HasValue("block"))
|
||||
{
|
||||
AuLogDbg("Blocking file...");
|
||||
ASSERT_TRUE(AuFS::BlockFile(AuCmdLine::GetValue("block")));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FS, TestUnblock)
|
||||
{
|
||||
if (AuCmdLine::HasValue("unblock"))
|
||||
{
|
||||
AuLogDbg("Unblocking file...");
|
||||
ASSERT_TRUE(AuFS::UnblockFile(AuCmdLine::GetValue("unblock")));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FS, TestTrust)
|
||||
{
|
||||
if (AuCmdLine::HasValue("trust"))
|
||||
{
|
||||
AuLogDbg("Trusting file...");
|
||||
ASSERT_TRUE(AuFS::TrustFile(AuCmdLine::GetValue("trust")));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(FS, TestCompress)
|
||||
{
|
||||
if (AuCmdLine::HasValue("compress"))
|
||||
{
|
||||
AuLogDbg("Compressing file...");
|
||||
ASSERT_TRUE(AuFS::Compress(AuCmdLine::GetValue("compress")));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FS, TestDecompress)
|
||||
{
|
||||
if (AuCmdLine::HasValue("decompress"))
|
||||
{
|
||||
AuLogDbg("Decompressing file...");
|
||||
ASSERT_TRUE(AuFS::Decompress(AuCmdLine::GetValue("decompress")));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FS, TestListAttr)
|
||||
{
|
||||
if (AuCmdLine::HasValue("attrs"))
|
||||
{
|
||||
auto list = AuFS::FileAttrsList(AuCmdLine::GetValue("attrs"));
|
||||
AuLogDbg("Found attrs: {}", list);
|
||||
}
|
||||
}
|
||||
|
||||
void RunTests()
|
||||
{
|
||||
Aurora::RuntimeStartInfo info;
|
||||
|
@ -251,7 +251,7 @@ TEST(BasicCompression, algorithm) \
|
||||
|
||||
#define ADD_TESTS(...) AU_FOR_EACH(ADD_TESTS_BASIC, __VA_ARGS__)
|
||||
|
||||
ADD_TESTS(LZ4, ZSTD, BZIP2, Deflate, Zip, GZip);
|
||||
ADD_TESTS(LZ4, ZSTD, BZIP2, Deflate, Zip, GZip, Brotli);
|
||||
|
||||
void RunTests()
|
||||
{
|
||||
|
@ -12,6 +12,7 @@ static void TestPath(const AuString &handleString)
|
||||
auto pipeImported = AuIPC::ImportPipe(handleString);
|
||||
SysAssert(bool(pipeImported));
|
||||
new decltype(pipeImported)(pipeImported); // Leak :S
|
||||
// // If we dont call any dtors and the server recovers, theres no client-side pipe trickery going on
|
||||
|
||||
//SysAssert(pipeImported->AsReadChannelIsOpen()->IsSignaled());
|
||||
|
||||
@ -33,10 +34,10 @@ static void TestPath(const AuString &handleString)
|
||||
|
||||
SysAssert(transactionB->StartWrite(0, AuUnsafeRaiiToShared(&writeView)));
|
||||
|
||||
// Create loop to sync against the two outstanding IO requests
|
||||
// Create loop to sync against the outstanding IO requests
|
||||
auto loop = AuLoop::NewLoopQueue();
|
||||
|
||||
// Add initial loop sources
|
||||
// Add initial loop source[s]
|
||||
SysAssert(loop->SourceAdd(transactionB->NewLoopSource()));
|
||||
|
||||
SysAssert(loop->Commit());
|
||||
|
@ -130,10 +130,10 @@ TEST(Net, TLSGoogle)
|
||||
tlsMeta.bIsClient = true;
|
||||
tlsMeta.client.sSNIServerName = "google.com";
|
||||
tlsMeta.pCertPin = AuMakeSharedThrow<AuIO::TLS::IPinCertificateFunctional>([]
|
||||
(const AuSPtr<AuIO::TLS::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate) -> bool
|
||||
(const AuSPtr<AuIO::TLS::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate) -> bool
|
||||
{
|
||||
AuLogDbg("Incoming handshake...");
|
||||
AuLogDbg("Incoming 2 handshake...");
|
||||
for (AuUInt32 i = 0; i < pChain->GetCertificateCount(); i++)
|
||||
{
|
||||
auto details = pChain->GetCertificateDetails(i);
|
||||
@ -199,6 +199,105 @@ TEST(Net, TLSGoogle)
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Net, DnsTLSGoogle)
|
||||
{
|
||||
auto pIoProcessor = AuIO::NewIOProcessorNoQueue(false);
|
||||
ASSERT_TRUE(bool(pIoProcessor));
|
||||
|
||||
auto pNetProcessor = AuNet::NewNetworkInterface();
|
||||
ASSERT_TRUE(bool(pNetProcessor));
|
||||
|
||||
auto pNetWorker = pNetProcessor->GetWorkersService()->Attach(pIoProcessor);
|
||||
ASSERT_TRUE(bool(pNetWorker));
|
||||
|
||||
auto pStats = AuMakeShared<DriverStat>();
|
||||
ASSERT_TRUE(bool(pStats));
|
||||
|
||||
auto pDriver = NewTestSocketDriver(pStats);
|
||||
ASSERT_TRUE(bool(pDriver));
|
||||
|
||||
auto pRealDriver = AuMakeShared<AuNet::ISocketDriverFunctional>();
|
||||
|
||||
static AuSPtr<AuNet::ISocket> gDriverSocket;
|
||||
pRealDriver->OnPreestablishFunctional = [&](const AuSPtr<AuNet::ISocket> &socket) -> bool
|
||||
{
|
||||
#define ENABLE_TLS
|
||||
#if defined(ENABLE_TLS)
|
||||
Aurora::IO::TLS::TLSMeta tlsMeta;
|
||||
tlsMeta.bIsClient = true;
|
||||
tlsMeta.client.sSNIServerName = "google.com";
|
||||
tlsMeta.pCertPin = AuMakeSharedThrow<AuIO::TLS::IPinCertificateFunctional>([]
|
||||
(const AuSPtr<AuIO::TLS::ICertificateChain> &pChain,
|
||||
const AuMemoryViewRead &derCertificate) -> bool
|
||||
{
|
||||
AuLogDbg("Incoming handshake...");
|
||||
for (AuUInt32 i = 0; i < pChain->GetCertificateCount(); i++)
|
||||
{
|
||||
auto details = pChain->GetCertificateDetails(i);
|
||||
auto cert = pChain->GetCertificate(i);
|
||||
|
||||
AuLogDbg("{}: {} (from {})", i, details.subject.commonName, details.issuer.commonName);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
auto pContext = Aurora::IO::TLS::NewTLSContextEx(socket->ToChannel()->NewProtocolSendStack(),
|
||||
socket->ToChannel()->NewProtocolRecvStack(),
|
||||
tlsMeta);
|
||||
pContext->Attach(socket);
|
||||
pContext->StartHandshake();
|
||||
#endif
|
||||
|
||||
gDriverSocket = socket;
|
||||
return true;
|
||||
};
|
||||
|
||||
pRealDriver->OnEstablishFunctional = [&]()
|
||||
{
|
||||
auto pChannel = gDriverSocket->ToChannel();
|
||||
pChannel->AsStreamWriter()->Write(AuMemoryViewRead("GET / HTTP/1.1\r\nConnection: close\r\n\r\n", 37));
|
||||
};
|
||||
|
||||
pRealDriver->OnFatalErrorReportedFunctional = [&](const AuNet::NetError &error)
|
||||
{
|
||||
AuLogDbg("[3] On error: {}", NetErrorToExtendedString(error));
|
||||
};
|
||||
|
||||
pRealDriver->OnStreamUpdatedFunctional = [&]()
|
||||
{
|
||||
auto pChannel = gDriverSocket->ToChannel();
|
||||
auto pReader = pChannel->AsReadableByteBuffer();
|
||||
|
||||
AuString message;
|
||||
message.resize(pReader->RemainingBytes());
|
||||
pReader->Read(message.data(), message.size());
|
||||
|
||||
AuLogDbg("Stream updated: {}", message);
|
||||
};
|
||||
|
||||
pRealDriver->OnFinalizeFunctional = [&]()
|
||||
{
|
||||
AuLogDbg("[3] On finalize");
|
||||
};
|
||||
|
||||
pDriver->pProxy = pRealDriver;
|
||||
|
||||
AuNet::NetSocketConnect nsConnect;
|
||||
nsConnect.pDriver = pDriver;
|
||||
nsConnect.byHost.netHostname = AuNet::NetHostname("google.com");
|
||||
nsConnect.byHost.uPort = 443;
|
||||
nsConnect.byHost.protocol = AuNet::ETransportProtocol::eProtocolTCP;
|
||||
|
||||
auto pSocket = pNetProcessor->GetSocketService()->Connect(nsConnect);
|
||||
ASSERT_TRUE(bool(pSocket));
|
||||
|
||||
while (pIoProcessor->HasItems())
|
||||
{
|
||||
pIoProcessor->RunTick();
|
||||
}
|
||||
}
|
||||
|
||||
void RunTests()
|
||||
{
|
||||
Aurora::RuntimeStartInfo info;
|
||||
|
112
Tests/Public/Net. Telnet TCP TLS Server/Main.cpp
Normal file
112
Tests/Public/Net. Telnet TCP TLS Server/Main.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/***
|
||||
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: Main.cpp
|
||||
Date: 2022-2-18
|
||||
Author: Reece
|
||||
***/
|
||||
#include <AuroraRuntime.hpp>
|
||||
#include <Aurora/IO/IOExperimental.hpp>
|
||||
#include <Aurora/IO/Net/NetExperimental.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(Net, ServerDemo)
|
||||
{
|
||||
auto pIoProcessor = AuIO::NewIOProcessorNoQueue(false);
|
||||
ASSERT_TRUE(bool(pIoProcessor));
|
||||
|
||||
auto pNetProcessor = AuNet::NewNetworkInterface();
|
||||
ASSERT_TRUE(bool(pNetProcessor));
|
||||
|
||||
auto pNetWorker = pNetProcessor->GetWorkersService()->Attach(pIoProcessor);
|
||||
ASSERT_TRUE(bool(pNetWorker));
|
||||
|
||||
auto pSocketFactory = AuMakeShared<AuNet::ISocketDriverFactoryFunctional>();
|
||||
ASSERT_TRUE(bool(pSocketFactory));
|
||||
|
||||
pSocketFactory->NewSocketDriverFunctional = []() -> AuSPtr<AuNet::ISocketDriver>
|
||||
{
|
||||
struct TempDriver : AuNet::ISocketDriverFunctional
|
||||
{
|
||||
AuSPtr<AuNet::ISocket> pDriverSocket;
|
||||
};
|
||||
auto pRealDriver = AuMakeShared<TempDriver>();
|
||||
|
||||
pRealDriver->OnPreestablishFunctional = [=](const AuSPtr<AuNet::ISocket> &socket) -> bool
|
||||
{
|
||||
pRealDriver->pDriverSocket = socket;
|
||||
return true;
|
||||
};
|
||||
|
||||
pRealDriver->OnEstablishFunctional = [=]()
|
||||
{
|
||||
auto pChannel = pRealDriver->pDriverSocket->ToChannel();
|
||||
pChannel->AsStreamWriter()->Write(AuMemoryViewRead("Hello World", 11));
|
||||
};
|
||||
|
||||
pRealDriver->OnFatalErrorReportedFunctional = [=](const AuNet::NetError &error)
|
||||
{
|
||||
AuLogDbg("[2] On error: {}", NetErrorToExtendedString(error));
|
||||
};
|
||||
|
||||
pRealDriver->OnStreamUpdatedFunctional = [=]()
|
||||
{
|
||||
auto pChannel = pRealDriver->pDriverSocket->ToChannel();
|
||||
auto pReader = pChannel->AsReadableByteBuffer();
|
||||
|
||||
AuString message;
|
||||
message.resize(pReader->RemainingBytes());
|
||||
pReader->Read(message.data(), message.size());
|
||||
|
||||
AuLogDbg("[2] Got: {}", message);
|
||||
};
|
||||
|
||||
pRealDriver->OnFinalizeFunctional = [=]()
|
||||
{
|
||||
AuResetMember(*pRealDriver.get()); // reset circular dependence on captured pRealDriver
|
||||
AuLogDbg("[2] Finalize");
|
||||
};
|
||||
|
||||
return pRealDriver;
|
||||
};
|
||||
|
||||
auto pServerDriver = AuMakeShared<AuNet::ISocketServerDriverFunctional>();
|
||||
ASSERT_TRUE(bool(pServerDriver));
|
||||
|
||||
pServerDriver->OnBindFunctional = [&]()
|
||||
{
|
||||
AuLogDbg("[1] On bind");
|
||||
};
|
||||
|
||||
pServerDriver->OnFatalErrorReportedFunctional = [&](const AuNet::NetError &error)
|
||||
{
|
||||
AuLogDbg("[1] On error: {}", NetErrorToExtendedString(error));
|
||||
};
|
||||
|
||||
pServerDriver->OnFinalizeFunctional = [&]()
|
||||
{
|
||||
AuLogDbg("[1] On finalize");
|
||||
};
|
||||
|
||||
AuNet::NetSocketBind nsSocketBind;
|
||||
nsSocketBind.pDriver = pServerDriver;
|
||||
nsSocketBind.ip = AuNet::IPAddress("127.0.0.1");
|
||||
nsSocketBind.protocol = AuNet::ETransportProtocol::eProtocolTCP;
|
||||
nsSocketBind.uPort = 8087;
|
||||
nsSocketBind.pFactory = pSocketFactory;
|
||||
|
||||
auto pSocket = pNetProcessor->GetSocketService()->NewServer(nsSocketBind);
|
||||
ASSERT_TRUE(bool(pSocket));
|
||||
|
||||
while (pIoProcessor->HasItems())
|
||||
{
|
||||
pIoProcessor->RunTick();
|
||||
}
|
||||
}
|
||||
|
||||
void RunTests()
|
||||
{
|
||||
Aurora::RuntimeStartInfo info;
|
||||
info.console.fio.enableLogging = false;
|
||||
Aurora::RuntimeStart(info);
|
||||
}
|
@ -1 +1 @@
|
||||
Subproject commit 9c332145b71c36a5bad9688312c79184f98601ff
|
||||
Subproject commit 783d00fd19865fcbc3065e3fb3e17144761fcf5a
|
2
Vendor/nlohmannjson
vendored
2
Vendor/nlohmannjson
vendored
@ -1 +1 @@
|
||||
Subproject commit a3e6e26dc83a726b292f5be0492fcc408663ce55
|
||||
Subproject commit 6af826d0bdb55e4b69e3ad817576745335f243ca
|
Loading…
Reference in New Issue
Block a user