summaryrefslogtreecommitdiffstats
path: root/fnet
diff options
context:
space:
mode:
authorHåvard Pettersen <havardpe@oath.com>2019-11-18 14:29:21 +0000
committerHåvard Pettersen <havardpe@oath.com>2019-11-19 12:55:35 +0000
commit0e99acfd33930fc5180ac390718f4b20f2d4d7e2 (patch)
tree4e219f48f8900a84f46b3ee075ecc49624cdd678 /fnet
parent957a7cc70ba85568618fb2b5282d38f009c688ea (diff)
use chrono instead of fastos time
Diffstat (limited to 'fnet')
-rw-r--r--fnet/src/examples/frt/rpc/rpc_proxy.cpp15
-rw-r--r--fnet/src/examples/timeout/timeout.cpp20
-rw-r--r--fnet/src/tests/databuffer/databuffer.cpp37
-rw-r--r--fnet/src/tests/info/info.cpp7
-rw-r--r--fnet/src/tests/locking/castspeed.cpp74
-rw-r--r--fnet/src/tests/locking/drainpackets.cpp29
-rw-r--r--fnet/src/tests/locking/lockspeed.cpp62
-rw-r--r--fnet/src/tests/scheduling/schedule.cpp52
-rw-r--r--fnet/src/tests/scheduling/sloweventloop.cpp11
-rw-r--r--fnet/src/tests/time/timespeed.cpp73
-rw-r--r--fnet/src/vespa/fnet/iocomponent.cpp2
-rw-r--r--fnet/src/vespa/fnet/iocomponent.h7
-rw-r--r--fnet/src/vespa/fnet/packetqueue.cpp14
-rw-r--r--fnet/src/vespa/fnet/scheduler.cpp14
-rw-r--r--fnet/src/vespa/fnet/scheduler.h27
-rw-r--r--fnet/src/vespa/fnet/transport.h1
-rw-r--r--fnet/src/vespa/fnet/transport_thread.cpp51
-rw-r--r--fnet/src/vespa/fnet/transport_thread.h8
18 files changed, 213 insertions, 291 deletions
diff --git a/fnet/src/examples/frt/rpc/rpc_proxy.cpp b/fnet/src/examples/frt/rpc/rpc_proxy.cpp
index 1f1a3a80f2f..a61e2d37197 100644
--- a/fnet/src/examples/frt/rpc/rpc_proxy.cpp
+++ b/fnet/src/examples/frt/rpc/rpc_proxy.cpp
@@ -2,6 +2,7 @@
#include <vespa/fnet/frt/frt.h>
#include <vespa/fastos/app.h>
+#include <chrono>
#include <vespa/log/log.h>
LOG_SETUP("rpc_proxy");
@@ -83,13 +84,17 @@ ReqDone::RequestDone(FRT_RPCRequest *req)
const char *
RPCProxy::GetPrefix(FRT_RPCRequest *req)
{
- FastOS_Time t;
tm currTime;
tm *currTimePt;
- t.SetNow();
- time_t secs = t.Secs();
- currTimePt = localtime_r(&secs, &currTime);
+ using clock = std::chrono::system_clock;
+ auto now = clock::now();
+ auto since = now.time_since_epoch();
+ auto secs = std::chrono::duration_cast<std::chrono::seconds>(since);
+ auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(since - secs);
+ time_t my_time = clock::to_time_t(now);
+
+ currTimePt = localtime_r(&my_time, &currTime);
assert(currTimePt == &currTime);
(void) currTimePt;
@@ -107,7 +112,7 @@ RPCProxy::GetPrefix(FRT_RPCRequest *req)
currTime.tm_hour,
currTime.tm_min,
currTime.tm_sec,
- (int)(t.GetMicroSeconds() / 1000),
+ int(ms.count()),
GetSession(req)->id,
rid);
diff --git a/fnet/src/examples/timeout/timeout.cpp b/fnet/src/examples/timeout/timeout.cpp
index bba58faca55..1d6ecc11909 100644
--- a/fnet/src/examples/timeout/timeout.cpp
+++ b/fnet/src/examples/timeout/timeout.cpp
@@ -2,6 +2,7 @@
#include <vespa/fnet/fnet.h>
#include <vespa/fastos/app.h>
+#include <chrono>
#include <vespa/log/log.h>
LOG_SETUP("timeout");
@@ -42,8 +43,11 @@ public:
int
MyApp::Main()
{
- double ms;
- FastOS_Time t;
+ using clock = std::chrono::steady_clock;
+ using ms_double = std::chrono::duration<double,std::milli>;
+
+ ms_double ms;
+ clock::time_point t;
FNET_PacketQueue queue;
FastOS_ThreadPool pool(65000);
FNET_Transport transport;
@@ -57,28 +61,28 @@ MyApp::Main()
FNET_Context context;
fprintf(stderr, "scheduling timeout in 2 seconds...\n");
- t.SetNow();
+ t = clock::now();
timeout.Schedule(2.0); // timeout in 2 seconds
FastOS_Thread::Sleep(1000);
timeout.Unschedule(); // cancel timeout
- ms = t.MilliSecsToNow();
+ ms = (clock::now() - t);
if (queue.GetPacketCnt_NoLock() == 0)
fprintf(stderr, "timeout canceled; no timeout packet delivered\n");
- fprintf(stderr, "time since timeout was scheduled: %f ms\n", ms);
+ fprintf(stderr, "time since timeout was scheduled: %f ms\n", ms.count());
fprintf(stderr, "scheduling timeout in 2 seconds...\n");
- t.SetNow();
+ t = clock::now();
timeout.Schedule(2.0); // timeout in 2 seconds
packet = queue.DequeuePacket(&context); // wait for timeout
- ms = t.MilliSecsToNow();
+ ms = (clock::now() - t);
if (packet->IsTimeoutCMD())
fprintf(stderr, "got timeout packet\n");
- fprintf(stderr, "time since timeout was scheduled: %f ms\n", ms);
+ fprintf(stderr, "time since timeout was scheduled: %f ms\n", ms.count());
transport.ShutDown(true);
pool.Close();
diff --git a/fnet/src/tests/databuffer/databuffer.cpp b/fnet/src/tests/databuffer/databuffer.cpp
index 4bc3a6cb7a8..c5cfb544abd 100644
--- a/fnet/src/tests/databuffer/databuffer.cpp
+++ b/fnet/src/tests/databuffer/databuffer.cpp
@@ -1,7 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/fnet/databuffer.h>
-#include <vespa/fastos/time.h>
+#include <chrono>
TEST("test resetIfEmpty") {
FNET_DataBuffer buf(64);
@@ -53,11 +53,14 @@ TEST("testResize") {
}
TEST("testSpeed") {
+ using clock = std::chrono::steady_clock;
+ using ms_double = std::chrono::duration<double, std::milli>;
+
FNET_DataBuffer buf0(20000);
FNET_DataBuffer buf1(20000);
FNET_DataBuffer buf2(20000);
- FastOS_Time start;
- FastOS_Time stop;
+ clock::time_point start;
+ ms_double ms;
int i;
int k;
@@ -76,7 +79,7 @@ TEST("testSpeed") {
buf0.DeadToData(buf0.GetDeadLen());
// test encode/decode speed
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 5000; i++) {
buf2.Clear();
@@ -109,15 +112,14 @@ TEST("testSpeed") {
}
}
buf2.DeadToData(buf2.GetDeadLen());
- stop.SetNow();
- stop -= start;
- fprintf(stderr, "encode/decode time (~160MB): %1.2f\n", stop.MilliSecs());
+ ms = (clock::now() - start);
+ fprintf(stderr, "encode/decode time (~160MB): %1.2f\n", ms.count());
EXPECT_TRUE(buf0.Equals(&buf1) && buf0.Equals(&buf2));
// test encode[fast]/decode speed
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 5000; i++) {
buf2.Clear();
@@ -150,10 +152,9 @@ TEST("testSpeed") {
}
}
buf2.DeadToData(buf2.GetDeadLen());
- stop.SetNow();
- stop -= start;
- fprintf(stderr, "encode[fast]/decode time (~160MB): %1.2f\n", stop.MilliSecs());
+ ms = (clock::now() - start);
+ fprintf(stderr, "encode[fast]/decode time (~160MB): %1.2f\n", ms.count());
EXPECT_TRUE(buf0.Equals(&buf1) && buf0.Equals(&buf2));
@@ -164,7 +165,7 @@ TEST("testSpeed") {
}
// test byte-swap table encoding speed
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 10000; i++) {
buf1.Clear();
@@ -179,13 +180,12 @@ TEST("testSpeed") {
buf1.WriteInt32Fast(table[k + 7]);
}
}
- stop.SetNow();
- stop -= start;
+ ms = (clock::now() - start);
fprintf(stderr, "byte-swap array encoding[fast] (~160 MB): %1.2f ms\n",
- stop.MilliSecs());
+ ms.count());
// test direct-copy table encoding speed
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 10000; i++) {
buf2.Clear();
@@ -193,10 +193,9 @@ TEST("testSpeed") {
memcpy(buf2.GetFree(), table, 16000);
buf2.FreeToData(16000);
}
- stop.SetNow();
- stop -= start;
+ ms = (clock::now() - start);
fprintf(stderr, "direct-copy array encoding (~160 MB): %1.2f ms\n",
- stop.MilliSecs());
+ ms.count());
}
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/fnet/src/tests/info/info.cpp b/fnet/src/tests/info/info.cpp
index 938ea1b7f15..a86796f5599 100644
--- a/fnet/src/tests/info/info.cpp
+++ b/fnet/src/tests/info/info.cpp
@@ -8,7 +8,6 @@ struct RPC : public FRT_Invokable
{
void GetInfo(FRT_RPCRequest *req)
{
- req->GetReturn()->AddString("fastos X current");
req->GetReturn()->AddString(FNET_Info::GetFNETVersion());
const char *endian_str = "UNKNOWN";
if (FNET_Info::GetEndian() == FNET_Info::ENDIAN_LITTLE)
@@ -24,9 +23,8 @@ struct RPC : public FRT_Invokable
{
FRT_ReflectionBuilder rb(s);
//-------------------------------------------------------------------
- rb.DefineMethod("getInfo", "", "sssii",
+ rb.DefineMethod("getInfo", "", "ssii",
FRT_METHOD(RPC::GetInfo), this);
- // FastOS version
// FNET version
// endian
// FD_SETSIZE
@@ -56,7 +54,6 @@ TEST("info") {
FRT_Values &l = *local_info->GetReturn();
// FRT_Values &r = *remote_info->GetReturn();
- fprintf(stderr, "FastOS Version: %s\n", l[0]._string._str);
fprintf(stderr, "FNET Version: %s\n", l[1]._string._str);
fprintf(stderr, "Endian: %s\n", l[2]._string._str);
fprintf(stderr, "FD_SETSIZE: %d\n", l[3]._intval32);
@@ -80,9 +77,7 @@ TEST("size of important objects")
EXPECT_EQUAL(MUTEX_SIZE + 432u, sizeof(FNET_Connection));
EXPECT_EQUAL(48u, sizeof(std::condition_variable));
EXPECT_EQUAL(56u, sizeof(FNET_DataBuffer));
- EXPECT_EQUAL(24u, sizeof(FastOS_Time));
EXPECT_EQUAL(8u, sizeof(FNET_Context));
- EXPECT_EQUAL(8u, sizeof(fastos::TimeStamp));
EXPECT_EQUAL(MUTEX_SIZE, sizeof(std::mutex));
EXPECT_EQUAL(MUTEX_SIZE, sizeof(pthread_mutex_t));
EXPECT_EQUAL(48u, sizeof(pthread_cond_t));
diff --git a/fnet/src/tests/locking/castspeed.cpp b/fnet/src/tests/locking/castspeed.cpp
index 153987c5516..dc82073ea57 100644
--- a/fnet/src/tests/locking/castspeed.cpp
+++ b/fnet/src/tests/locking/castspeed.cpp
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/fnet/fnet.h>
+#include <chrono>
class B;
@@ -62,8 +63,11 @@ public:
#define LOOPCNT 30000000
TEST("cast speed") {
- FastOS_Time start;
- FastOS_Time stop;
+ using clock = std::chrono::steady_clock;
+ using ms_double = std::chrono::duration<double, std::milli>;
+
+ clock::time_point start;
+ ms_double ms;
CastTest casttest;
@@ -71,7 +75,7 @@ TEST("cast speed") {
uint32_t i;
taken = 0;
- start.SetNow();
+ start = clock::now();
for (i = 0; i < LOOPCNT; i++) {
takeB(casttest.DummyCast());
takeB(casttest.DummyCast());
@@ -84,17 +88,16 @@ TEST("cast speed") {
takeB(casttest.DummyCast());
takeB(casttest.DummyCast());
}
- stop.SetNow();
- stop -= start;
- actualTime = stop.MilliSecs();
+ ms = (clock::now() - start);
+ actualTime = ms.count();
fprintf(stderr,
"%d dummy cast calls: %f ms (%1.2f/us) [%f]\n",
- taken, stop.MilliSecs(),
- 0.001 * taken / stop.MilliSecs(),
+ taken, ms.count(),
+ 0.001 * taken / ms.count(),
actualTime);
taken = 0;
- start.SetNow();
+ start = clock::now();
for (i = 0; i < LOOPCNT; i++) {
takeB(casttest.DynamicCast());
takeB(casttest.DynamicCast());
@@ -107,17 +110,16 @@ TEST("cast speed") {
takeB(casttest.DynamicCast());
takeB(casttest.DynamicCast());
}
- stop.SetNow();
- stop -= start;
- actualTime = stop.MilliSecs();
+ ms = (clock::now() - start);
+ actualTime = ms.count();
fprintf(stderr,
"%d dynamic cast calls: %f ms (%1.2f/us) [%f]\n",
- taken, stop.MilliSecs(),
- 0.001 * taken / stop.MilliSecs(),
+ taken, ms.count(),
+ 0.001 * taken / ms.count(),
actualTime);
taken = 0;
- start.SetNow();
+ start = clock::now();
for (i = 0; i < LOOPCNT; i++) {
takeB(casttest.TypesafeCast());
takeB(casttest.TypesafeCast());
@@ -130,17 +132,16 @@ TEST("cast speed") {
takeB(casttest.TypesafeCast());
takeB(casttest.TypesafeCast());
}
- stop.SetNow();
- stop -= start;
- actualTime = stop.MilliSecs();
+ ms = (clock::now() - start);
+ actualTime = ms.count();
fprintf(stderr,
"%d typesafe cast calls: %f ms (%1.2f/us) [%f]\n",
- taken, stop.MilliSecs(),
- 0.001 * taken / stop.MilliSecs(),
+ taken, ms.count(),
+ 0.001 * taken / ms.count(),
actualTime);
taken = 0;
- start.SetNow();
+ start = clock::now();
for (i = 0; i < LOOPCNT; i++) {
takeB(casttest.StaticCast());
takeB(casttest.StaticCast());
@@ -153,17 +154,16 @@ TEST("cast speed") {
takeB(casttest.StaticCast());
takeB(casttest.StaticCast());
}
- stop.SetNow();
- stop -= start;
- actualTime = stop.MilliSecs();
+ ms = (clock::now() - start);
+ actualTime = ms.count();
fprintf(stderr,
"%d static cast calls: %f ms (%1.2f/us) [%f]\n",
- taken, stop.MilliSecs(),
- 0.001 * taken / stop.MilliSecs(),
+ taken, ms.count(),
+ 0.001 * taken / ms.count(),
actualTime);
taken = 0;
- start.SetNow();
+ start = clock::now();
for (i = 0; i < LOOPCNT; i++) {
takeB(casttest.UnsafeCast());
takeB(casttest.UnsafeCast());
@@ -176,17 +176,16 @@ TEST("cast speed") {
takeB(casttest.UnsafeCast());
takeB(casttest.UnsafeCast());
}
- stop.SetNow();
- stop -= start;
- actualTime = stop.MilliSecs();
+ ms = (clock::now() - start);
+ actualTime = ms.count();
fprintf(stderr,
"%d reinterpret_cast calls: %f ms (%1.2f/us) [%f]\n",
- taken, stop.MilliSecs(),
- 0.001 * taken / stop.MilliSecs(),
+ taken, ms.count(),
+ 0.001 * taken / ms.count(),
actualTime);
taken = 0;
- start.SetNow();
+ start = clock::now();
for (i = 0; i < LOOPCNT; i++) {
takeB(casttest.DummyCast());
takeB(casttest.DummyCast());
@@ -199,13 +198,12 @@ TEST("cast speed") {
takeB(casttest.DummyCast());
takeB(casttest.DummyCast());
}
- stop.SetNow();
- stop -= start;
- actualTime = stop.MilliSecs();
+ ms = (clock::now() - start);
+ actualTime = ms.count();
fprintf(stderr,
"%d dummy cast calls: %f ms (%1.2f/us) [%f]\n",
- taken, stop.MilliSecs(),
- 0.001 * taken / stop.MilliSecs(),
+ taken, ms.count(),
+ 0.001 * taken / ms.count(),
actualTime);
}
diff --git a/fnet/src/tests/locking/drainpackets.cpp b/fnet/src/tests/locking/drainpackets.cpp
index a2999f0bddc..9db43a5eb52 100644
--- a/fnet/src/tests/locking/drainpackets.cpp
+++ b/fnet/src/tests/locking/drainpackets.cpp
@@ -2,6 +2,7 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/fnet/fnet.h>
#include <mutex>
+#include <chrono>
class MyPacket : public FNET_Packet
{
@@ -14,8 +15,11 @@ public:
TEST("drain packets") {
- FastOS_Time start;
- FastOS_Time stop;
+ using clock = std::chrono::steady_clock;
+ using ms_double = std::chrono::duration<double, std::milli>;
+
+ clock::time_point start;
+ ms_double ms;
std::mutex lock;
@@ -33,7 +37,7 @@ TEST("drain packets") {
// drain packets directly with single lock interval
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 10000; i++) {
@@ -59,14 +63,13 @@ TEST("drain packets") {
}
}
- stop.SetNow();
- stop -= start;
+ ms = (clock::now() - start);
fprintf(stderr, "direct, single lock interval (10M packets): %1.2f ms\n",
- stop.MilliSecs());
+ ms.count());
// flush packets, then move without lock
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 10000; i++) {
@@ -96,13 +99,12 @@ TEST("drain packets") {
}
}
- stop.SetNow();
- stop -= start;
- fprintf(stderr, "indirect (10M packets): %1.2f ms\n", stop.MilliSecs());
+ ms = (clock::now() - start);
+ fprintf(stderr, "indirect (10M packets): %1.2f ms\n", ms.count());
// drain packets directly with multiple lock intervals
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 10000; i++) {
@@ -120,10 +122,9 @@ TEST("drain packets") {
}
}
- stop.SetNow();
- stop -= start;
+ ms = (clock::now() - start);
fprintf(stderr, "direct, multiple lock intervals (10M packets): %1.2f ms\n",
- stop.MilliSecs());
+ ms.count());
EXPECT_TRUE(q1.GetPacketCnt_NoLock() == 500 &&
q2.GetPacketCnt_NoLock() == 0 &&
diff --git a/fnet/src/tests/locking/lockspeed.cpp b/fnet/src/tests/locking/lockspeed.cpp
index 50c8d4eef1b..ae6b983d724 100644
--- a/fnet/src/tests/locking/lockspeed.cpp
+++ b/fnet/src/tests/locking/lockspeed.cpp
@@ -2,6 +2,7 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/fnet/fnet.h>
#include "dummy.h"
+#include <chrono>
class SpinLock {
private:
@@ -17,8 +18,12 @@ public:
};
TEST("lock speed") {
- FastOS_Time start;
- FastOS_Time stop;
+ using clock = std::chrono::steady_clock;
+ using ms_double = std::chrono::duration<double, std::milli>;
+
+ clock::time_point start;
+ ms_double ms;
+
DummyLock dummy;
std::mutex lock;
SpinLock spin;
@@ -29,7 +34,7 @@ TEST("lock speed") {
double spin_factor;
uint32_t i;
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 1000000; i++) {
dummy.Lock();
dummy.Unlock();
@@ -52,15 +57,14 @@ TEST("lock speed") {
dummy.Lock();
dummy.Unlock();
}
- stop.SetNow();
- stop -= start;
- dummyTime = stop.MilliSecs();
+ ms = (clock::now() - start);
+ dummyTime = ms.count();
fprintf(stderr,
"10M dummy lock/unlock: %f ms (%1.2f/ms)\n",
dummyTime, 10000000.0 / dummyTime);
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 1000000; i++) {
lock.lock();
lock.unlock();
@@ -83,17 +87,16 @@ TEST("lock speed") {
lock.lock();
lock.unlock();
}
- stop.SetNow();
- stop -= start;
- actualTime = stop.MilliSecs();
+ ms = (clock::now() - start);
+ actualTime = ms.count();
fprintf(stderr,
"10M actual lock/unlock: %f ms (%1.2f/ms)\n",
- stop.MilliSecs(), 10000000.0 / stop.MilliSecs());
+ ms.count(), 10000000.0 / ms.count());
overhead = (actualTime - dummyTime) / 10000.0;
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 1000000; i++) {
spin.lock();
spin.unlock();
@@ -116,13 +119,12 @@ TEST("lock speed") {
spin.lock();
spin.unlock();
}
- stop.SetNow();
- stop -= start;
- actualTime = stop.MilliSecs();
+ ms = (clock::now() - start);
+ actualTime = ms.count();
fprintf(stderr,
"10M actual (spin) lock/unlock: %f ms (%1.2f/ms)\n",
- stop.MilliSecs(), 10000000.0 / stop.MilliSecs());
+ ms.count(), 10000000.0 / ms.count());
spin_overhead = (actualTime - dummyTime) / 10000.0;
@@ -142,7 +144,7 @@ TEST("lock speed") {
//---------------------------------------------------------------------------
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 1000000; i++) {
[[maybe_unused]] std::mutex lock0;
[[maybe_unused]] std::mutex lock1;
@@ -155,14 +157,13 @@ TEST("lock speed") {
[[maybe_unused]] std::mutex lock8;
[[maybe_unused]] std::mutex lock9;
}
- stop.SetNow();
- stop -= start;
+ ms = (clock::now() - start);
fprintf(stderr, "10M mutex create/destroy %f ms (%1.2f/ms)\n",
- stop.MilliSecs(), 10000000.0 / stop.MilliSecs());
+ ms.count(), 10000000.0 / ms.count());
//---------------------------------------------------------------------------
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 1000000; i++) {
std::condition_variable cond0;
std::condition_variable cond1;
@@ -175,14 +176,13 @@ TEST("lock speed") {
std::condition_variable cond8;
std::condition_variable cond9;
}
- stop.SetNow();
- stop -= start;
+ ms = (clock::now() - start);
fprintf(stderr, "10M cond create/destroy %f ms (%1.2f/ms)\n",
- stop.MilliSecs(), 10000000.0 / stop.MilliSecs());
+ ms.count(), 10000000.0 / ms.count());
//---------------------------------------------------------------------------
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 1000000; i++) {
DummyObj dummy0;
DummyObj dummy1;
@@ -195,14 +195,13 @@ TEST("lock speed") {
DummyObj dummy8;
DummyObj dummy9;
}
- stop.SetNow();
- stop -= start;
+ ms = (clock::now() - start);
fprintf(stderr, "10M dummy create/destroy %f ms (%1.2f/ms)\n",
- stop.MilliSecs(), 10000000.0 / stop.MilliSecs());
+ ms.count(), 10000000.0 / ms.count());
//---------------------------------------------------------------------------
- start.SetNow();
+ start = clock::now();
for (i = 0; i < 1000000; i++) {
DummyObj *dummy0 = new DummyObj();
DummyObj *dummy1 = new DummyObj();
@@ -225,10 +224,9 @@ TEST("lock speed") {
delete dummy1;
delete dummy0;
}
- stop.SetNow();
- stop -= start;
+ ms = (clock::now() - start);
fprintf(stderr, "10M dummy new/delete %f ms (%1.2f/ms)\n",
- stop.MilliSecs(), 10000000.0 / stop.MilliSecs());
+ ms.count(), 10000000.0 / ms.count());
//---------------------------------------------------------------------------
}
diff --git a/fnet/src/tests/scheduling/schedule.cpp b/fnet/src/tests/scheduling/schedule.cpp
index 4ae4a2e07de..a1b02a688bf 100644
--- a/fnet/src/tests/scheduling/schedule.cpp
+++ b/fnet/src/tests/scheduling/schedule.cpp
@@ -2,14 +2,27 @@
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/fnet/fnet.h>
-FastOS_Time _time;
-FNET_Scheduler *_scheduler;
+using my_clock = FNET_Scheduler::clock;
+using time_point = my_clock::time_point;
+using ms_double = std::chrono::duration<double, std::milli>;
+time_point _time;
+FNET_Scheduler *_scheduler;
+
+template <class Rep, class Period>
+int as_ms(std::chrono::duration<Rep,Period> duration) {
+ return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
+}
+
+template <class Clock, class Duration>
+int as_ms(std::chrono::time_point<Clock,Duration> time) {
+ return as_ms(time.time_since_epoch());
+}
class MyTask : public FNET_Task
{
public:
- FastOS_Time _time;
+ time_point _time;
int _target;
bool _done;
@@ -24,7 +37,7 @@ public:
bool Check() const
{
int a = _target;
- int b = (int)_time.MilliSecs();
+ int b = as_ms(_time);
if (!_done)
return false;
@@ -32,7 +45,7 @@ public:
if (b < a)
return false;
- if ((b - a) > (3 * FNET_Scheduler::SLOT_TICK))
+ if ((b - a) > (3 * FNET_Scheduler::tick_ms.count()))
return false;
return true;
@@ -66,7 +79,7 @@ public:
TEST("schedule") {
- _time.SetMilliSecs(0);
+ _time = time_point(std::chrono::milliseconds(0));
_scheduler = new FNET_Scheduler(&_time, &_time);
RealTimeTask rt_task1;
@@ -84,35 +97,32 @@ TEST("schedule") {
assert(tasks[i] != nullptr);
}
- FastOS_Time start;
- FastOS_Time stop;
+ time_point start;
+ ms_double ms;
- start.SetNow();
+ start = my_clock::now();
for (uint32_t j = 0; j < taskCnt; j++) {
tasks[j]->Schedule(tasks[j]->GetTarget() / 1000.0);
}
- stop.SetNow();
- stop -= start;
- double scheduleTime = stop.MilliSecs() / (double)taskCnt;
+ ms = (my_clock::now() - start);
+ double scheduleTime = ms.count() / (double)taskCnt;
fprintf(stderr, "scheduling cost: %1.2f microseconds\n", scheduleTime * 1000.0);
- start.SetNow();
+ start = my_clock::now();
uint32_t tickCnt = 0;
- while (_time.MilliSecs() < 135000.0) {
- _time.AddMilliSecs(FNET_Scheduler::SLOT_TICK);
+ while (as_ms(_time) < 135000.0) {
+ _time += FNET_Scheduler::tick_ms;
_scheduler->CheckTasks();
tickCnt++;
}
- stop.SetNow();
- stop -= start;
- double runTime = stop.MilliSecs();
+ ms = (my_clock::now() - start);
fprintf(stderr, "3 RT tasks + %d one-shot tasks over 135s\n", taskCnt);
- fprintf(stderr, "%1.2f seconds actual run time\n", runTime / 1000.0);
+ fprintf(stderr, "%1.2f seconds actual run time\n", ms.count() / 1000.0);
fprintf(stderr, "%1.2f tasks per simulated second\n", (double)taskCnt / (double)135);
fprintf(stderr, "%d ticks\n", tickCnt);
- fprintf(stderr, "%1.2f %% simulated CPU usage\n", 100 * (runTime / 135000.0));
+ fprintf(stderr, "%1.2f %% simulated CPU usage\n", 100 * (ms.count() / 135000.0));
fprintf(stderr, "%1.2f microseconds per performed task\n",
- 1000.0 * (runTime / (taskCnt + tickCnt * 3.0)));
+ 1000.0 * (ms.count() / (taskCnt + tickCnt * 3.0)));
for (uint32_t k = 0; k < taskCnt; k++) {
EXPECT_TRUE(tasks[k]->Check());
diff --git a/fnet/src/tests/scheduling/sloweventloop.cpp b/fnet/src/tests/scheduling/sloweventloop.cpp
index 6c218e25da5..5ddc9b1502c 100644
--- a/fnet/src/tests/scheduling/sloweventloop.cpp
+++ b/fnet/src/tests/scheduling/sloweventloop.cpp
@@ -17,15 +17,14 @@ public:
TEST("slow event loop") {
- FastOS_Time t;
- t.SetMilliSecs(0);
+ FNET_Scheduler::time_point t(std::chrono::milliseconds(0));
FNET_Scheduler scheduler(&t, &t);
MyTask task(scheduler);
MyTask task2(scheduler);
scheduler.CheckTasks();
- t.AddMilliSecs(10000);
+ t += std::chrono::milliseconds(10000);
task.Schedule(5.0);
uint32_t cnt = 0;
@@ -35,7 +34,7 @@ TEST("slow event loop") {
break;
}
++cnt;
- t.AddMilliSecs(1);
+ t += std::chrono::milliseconds(1);
}
if (!EXPECT_TRUE(cnt > 4700 && cnt < 4800)) {
@@ -43,7 +42,7 @@ TEST("slow event loop") {
}
scheduler.CheckTasks();
- t.AddMilliSecs(10000);
+ t += std::chrono::milliseconds(10000);
task2.Schedule(5.0);
uint32_t cnt2 = 0;
@@ -53,7 +52,7 @@ TEST("slow event loop") {
break;
}
++cnt2;
- t.AddMilliSecs(10000);
+ t += std::chrono::milliseconds(10000);
}
if (!EXPECT_TRUE(cnt2 > 15 && cnt2 < 25)) {
diff --git a/fnet/src/tests/time/timespeed.cpp b/fnet/src/tests/time/timespeed.cpp
index 2b43bc6c35a..1204b0ff334 100644
--- a/fnet/src/tests/time/timespeed.cpp
+++ b/fnet/src/tests/time/timespeed.cpp
@@ -1,68 +1,23 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/fnet/fnet.h>
+#include <vespa/vespalib/util/benchmark_timer.h>
+#include <chrono>
+using vespalib::BenchmarkTimer;
-class DummyTime
-{
-public:
- void SetNow() {}
-};
-
-
-TEST("time speed") {
- FastOS_Time start;
- FastOS_Time stop;
- DummyTime dummy;
- FastOS_Time now;
- double dummyTime;
- double actualTime;
- double overhead;
- uint32_t i;
-
- start.SetNow();
- for (i = 0; i < 100000; i++) {
- dummy.SetNow();
- dummy.SetNow();
- dummy.SetNow();
- dummy.SetNow();
- dummy.SetNow();
- dummy.SetNow();
- dummy.SetNow();
- dummy.SetNow();
- dummy.SetNow();
- dummy.SetNow();
- }
- stop.SetNow();
- stop -= start;
- dummyTime = stop.MilliSecs();
-
- fprintf(stderr, "1M dummy SetNow: %f ms (%1.2f/ms)\n",
- dummyTime, 1000000.0 / dummyTime);
-
- start.SetNow();
- for (i = 0; i < 100000; i++) {
- now.SetNow();
- now.SetNow();
- now.SetNow();
- now.SetNow();
- now.SetNow();
- now.SetNow();
- now.SetNow();
- now.SetNow();
- now.SetNow();
- now.SetNow();
- }
- stop.SetNow();
- stop -= start;
- actualTime = stop.MilliSecs();
-
- fprintf(stderr, "1M actual SetNow: %f ms (%1.2f/ms)\n",
- stop.MilliSecs(), 1000000.0 / stop.MilliSecs());
-
- overhead = (actualTime - dummyTime) / 1000.0;
+TEST("steady clock speed") {
+ using clock = std::chrono::steady_clock;
+ clock::time_point t;
+ double min_time_us = BenchmarkTimer::benchmark([&t](){t = clock::now();}, 1.0) * 1000000.0;
+ fprintf(stderr, "approx overhead per sample (steady clock): %f us\n", min_time_us);
+}
- fprintf(stderr, "approx overhead per SetNow: %f microseconds\n", overhead);
+TEST("system clock speed") {
+ using clock = std::chrono::system_clock;
+ clock::time_point t;
+ double min_time_us = BenchmarkTimer::benchmark([&t](){t = clock::now();}, 1.0) * 1000000.0;
+ fprintf(stderr, "approx overhead per sample (system clock): %f us\n", min_time_us);
}
TEST_MAIN() { TEST_RUN_ALL(); }
diff --git a/fnet/src/vespa/fnet/iocomponent.cpp b/fnet/src/vespa/fnet/iocomponent.cpp
index 0ecf63ea642..81d1bf47567 100644
--- a/fnet/src/vespa/fnet/iocomponent.cpp
+++ b/fnet/src/vespa/fnet/iocomponent.cpp
@@ -16,7 +16,7 @@ FNET_IOComponent::FNET_IOComponent(FNET_TransportThread *owner,
_ioc_selector(nullptr),
_ioc_spec(nullptr),
_flags(shouldTimeOut),
- _ioc_timestamp(fastos::ClockSystem::now()),
+ _ioc_timestamp(clock::now()),
_ioc_lock(),
_ioc_cond(),
_ioc_refcnt(1)
diff --git a/fnet/src/vespa/fnet/iocomponent.h b/fnet/src/vespa/fnet/iocomponent.h
index a6a9e77ec99..84e3c8bd412 100644
--- a/fnet/src/vespa/fnet/iocomponent.h
+++ b/fnet/src/vespa/fnet/iocomponent.h
@@ -2,10 +2,11 @@
#pragma once
-#include <vespa/fastos/timestamp.h>
+#include "scheduler.h"
#include <vespa/vespalib/net/selector.h>
#include <mutex>
#include <condition_variable>
+#include <chrono>
class FNET_TransportThread;
class FNET_Config;
@@ -24,6 +25,8 @@ class FNET_IOComponent
FNET_IOComponent &operator=(const FNET_IOComponent &);
using Selector = vespalib::Selector<FNET_IOComponent>;
+ using clock = FNET_Scheduler::clock;
+ using time_point = clock::time_point;
struct Flags {
Flags(bool shouldTimeout) :
@@ -47,7 +50,7 @@ protected:
Selector *_ioc_selector; // attached event selector
char *_ioc_spec; // connect/listen spec
Flags _flags; // Compressed representation of boolean flags;
- fastos::UTCTimeStamp _ioc_timestamp; // last I/O activity
+ time_point _ioc_timestamp; // last I/O activity
std::mutex _ioc_lock; // synchronization
std::condition_variable _ioc_cond; // synchronization
uint32_t _ioc_refcnt; // reference counter
diff --git a/fnet/src/vespa/fnet/packetqueue.cpp b/fnet/src/vespa/fnet/packetqueue.cpp
index 44647d730ed..e17d5360537 100644
--- a/fnet/src/vespa/fnet/packetqueue.cpp
+++ b/fnet/src/vespa/fnet/packetqueue.cpp
@@ -2,7 +2,6 @@
#include "packetqueue.h"
#include "packet.h"
-#include <vespa/fastos/time.h>
#include <cassert>
#include <chrono>
@@ -226,19 +225,20 @@ FNET_PacketQueue::DequeuePacket(FNET_Context *context)
FNET_Packet*
FNET_PacketQueue::DequeuePacket(uint32_t maxwait, FNET_Context *context)
{
+ using clock = std::chrono::steady_clock;
FNET_Packet *packet = nullptr;
- FastOS_Time startTime;
- int waitTime;
+ clock::time_point end_time;
- if (maxwait > 0)
- startTime.SetNow();
+ if (maxwait > 0) {
+ end_time = (clock::now() + std::chrono::milliseconds(maxwait));
+ }
std::unique_lock<std::mutex> guard(_lock);
if (maxwait > 0) {
bool timeout = false;
_waitCnt++;
- while ((_bufused == 0) && !timeout && (waitTime = (int)(maxwait - startTime.MilliSecsToNow())) > 0) {
- timeout = _cond.wait_for(guard, std::chrono::milliseconds(waitTime)) == std::cv_status::timeout;
+ while ((_bufused == 0) && !timeout) {
+ timeout = _cond.wait_until(guard, end_time) == std::cv_status::timeout;
}
_waitCnt--;
}
diff --git a/fnet/src/vespa/fnet/scheduler.cpp b/fnet/src/vespa/fnet/scheduler.cpp
index 4569aaf61c4..d37b5487162 100644
--- a/fnet/src/vespa/fnet/scheduler.cpp
+++ b/fnet/src/vespa/fnet/scheduler.cpp
@@ -9,8 +9,8 @@
LOG_SETUP(".fnet.scheduler");
-FNET_Scheduler::FNET_Scheduler(FastOS_Time *sampler,
- FastOS_Time *now)
+FNET_Scheduler::FNET_Scheduler(time_point *sampler,
+ time_point *now)
: _cond(),
_next(),
_now(),
@@ -29,9 +29,9 @@ FNET_Scheduler::FNET_Scheduler(FastOS_Time *sampler,
if (now != nullptr) {
_next = *now;
} else {
- _next.SetNow();
+ _next = clock::now();
}
- _next.AddMilliSecs(SLOT_TICK);
+ _next += tick_ms;
}
@@ -69,7 +69,7 @@ FNET_Scheduler::~FNET_Scheduler()
void
FNET_Scheduler::Schedule(FNET_Task *task, double seconds)
{
- uint32_t ticks = 2 + (uint32_t) std::ceil(seconds * (1000.0 / SLOT_TICK));
+ uint32_t ticks = 2 + (uint32_t) std::ceil(seconds * (1000.0 / tick_ms.count()));
std::lock_guard<std::mutex> guard(_lock);
if (!task->_killed) {
@@ -144,7 +144,7 @@ FNET_Scheduler::CheckTasks()
if (_sampler != nullptr) {
_now = *_sampler;
} else {
- _now.SetNow();
+ _now = clock::now();
}
// assume timely value propagation
@@ -160,7 +160,7 @@ FNET_Scheduler::CheckTasks()
// handle bucket timeout(s)
- for (int i = 0; _now >= _next; ++i, _next.AddMilliSecs(SLOT_TICK)) {
+ for (int i = 0; _now >= _next; ++i, _next += tick_ms) {
if (i < 25) {
if (++_currSlot >= NUM_SLOTS) {
_currSlot = 0;
diff --git a/fnet/src/vespa/fnet/scheduler.h b/fnet/src/vespa/fnet/scheduler.h
index 82f0de068c1..81ff8977f89 100644
--- a/fnet/src/vespa/fnet/scheduler.h
+++ b/fnet/src/vespa/fnet/scheduler.h
@@ -2,9 +2,9 @@
#pragma once
-#include <vespa/fastos/time.h>
#include <mutex>
#include <condition_variable>
+#include <chrono>
class FNET_Task;
@@ -19,9 +19,11 @@ class FNET_Task;
class FNET_Scheduler
{
public:
+ using clock = std::chrono::steady_clock;
+ using time_point = clock::time_point;
+ static constexpr auto tick_ms = std::chrono::milliseconds(10);
enum scheduler_constants {
- SLOT_TICK = 10,
NUM_SLOTS = 4096,
SLOTS_MASK = 4095,
SLOTS_SHIFT = 12
@@ -31,9 +33,9 @@ private:
std::mutex _lock;
std::condition_variable _cond;
FNET_Task *_slots[NUM_SLOTS + 1];
- FastOS_Time _next;
- FastOS_Time _now;
- FastOS_Time *_sampler;
+ time_point _next;
+ time_point _now;
+ time_point *_sampler;
uint32_t _currIter;
uint32_t _currSlot;
FNET_Task *_currPt;
@@ -71,8 +73,8 @@ public:
* @param now if given, indicates the current time. This value is
* used by the constructor to init internal variables.
**/
- FNET_Scheduler(FastOS_Time *sampler = nullptr,
- FastOS_Time *now = nullptr);
+ FNET_Scheduler(time_point *sampler = nullptr,
+ time_point *now = nullptr);
virtual ~FNET_Scheduler();
@@ -123,17 +125,6 @@ public:
/**
- * Obtain a pointer to the current time sampler used by this
- * scheduler. The returned object may only be used in the thread
- * servicing this scheduler; this includes all tasks performed by
- * this scheduler.
- *
- * @return pointer to current time sampler.
- **/
- FastOS_Time *GetTimeSampler() { return _sampler; }
-
-
- /**
* Perform pending tasks. This method should be invoked regularly.
**/
void CheckTasks();
diff --git a/fnet/src/vespa/fnet/transport.h b/fnet/src/vespa/fnet/transport.h
index 6c2aff5ec90..8d1ba48c1b0 100644
--- a/fnet/src/vespa/fnet/transport.h
+++ b/fnet/src/vespa/fnet/transport.h
@@ -9,7 +9,6 @@
#include <vespa/vespalib/net/crypto_engine.h>
#include <vespa/vespalib/util/threadstackexecutor.h>
-class FastOS_TimeInterface;
class FNET_TransportThread;
class FastOS_ThreadPool;
class FNET_Connector;
diff --git a/fnet/src/vespa/fnet/transport_thread.cpp b/fnet/src/vespa/fnet/transport_thread.cpp
index b850bd6a8c2..158524d1214 100644
--- a/fnet/src/vespa/fnet/transport_thread.cpp
+++ b/fnet/src/vespa/fnet/transport_thread.cpp
@@ -80,7 +80,7 @@ FNET_TransportThread::RemoveComponent(FNET_IOComponent *comp)
void
FNET_TransportThread::UpdateTimeOut(FNET_IOComponent *comp)
{
- comp->_ioc_timestamp = fastos::UTCTimeStamp(_now);
+ comp->_ioc_timestamp = _now;
RemoveComponent(comp);
AddComponent(comp);
}
@@ -206,8 +206,7 @@ extern "C" {
FNET_TransportThread::FNET_TransportThread(FNET_Transport &owner_in)
: _owner(owner_in),
- _startTime(),
- _now(),
+ _now(clock::now()),
_scheduler(&_now),
_config(),
_componentsHead(nullptr),
@@ -224,10 +223,8 @@ FNET_TransportThread::FNET_TransportThread(FNET_Transport &owner_in)
_started(false),
_shutdown(false),
_finished(false),
- _waitFinished(false),
- _deleted(false)
+ _waitFinished(false)
{
- _now.SetNow();
trapsigpipe();
}
@@ -236,7 +233,6 @@ FNET_TransportThread::~FNET_TransportThread()
{
{
std::lock_guard<std::mutex> guard(_lock);
- _deleted = true;
}
if (_started && !_finished) {
LOG(error, "Transport: delete called on active object!");
@@ -386,12 +382,10 @@ bool
FNET_TransportThread::InitEventLoop()
{
bool wasStarted;
- bool wasDeleted;
{
std::lock_guard<std::mutex> guard(_lock);
wasStarted = _started;
- wasDeleted = _deleted;
- if (!_started && !_deleted) {
+ if (!_started) {
_started = true;
}
}
@@ -399,12 +393,7 @@ FNET_TransportThread::InitEventLoop()
LOG(error, "Transport: InitEventLoop: object already active!");
return false;
}
- if (wasDeleted) {
- LOG(error, "Transport: InitEventLoop: object was deleted!");
- return false;
- }
- _now.SetNow();
- _startTime = _now;
+ _now = clock::now();
return true;
}
@@ -482,45 +471,21 @@ bool
FNET_TransportThread::EventLoopIteration()
{
FNET_IOComponent *component = nullptr;
- int msTimeout = FNET_Scheduler::SLOT_TICK;
-
-#ifdef FNET_SANITY_CHECKS
- FastOS_Time beforeGetEvents;
-#endif
+ int msTimeout = FNET_Scheduler::tick_ms.count();
if (!IsShutDown()) {
-
-#ifdef FNET_SANITY_CHECKS
- // Warn if event loop takes more than 250ms
- beforeGetEvents.SetNow();
- double loopTime = beforeGetEvents.MilliSecs() - _now.MilliSecs();
- if (loopTime > 250.0)
- LOG(warning, "SANITY: Transport loop time: %.2f ms", loopTime);
-#endif
-
// obtain I/O events
_selector.poll(msTimeout);
// sample current time (performed once per event loop iteration)
- _now.SetNow();
-
-#ifdef FNET_SANITY_CHECKS
- // Warn if event extraction takes more than timeout + 100ms
- double extractTime = _now.MilliSecs() - beforeGetEvents.MilliSecs();
- if (extractTime > (double) msTimeout + 100.0)
- LOG(warning, "SANITY: Event extraction time: %.2f ms (timeout: %d ms)",
- extractTime, msTimeout);
-#endif
+ _now = clock::now();
// handle wakeup and io-events
_selector.dispatch(*this);
// handle IOC time-outs
if (_config._iocTimeOut > 0) {
-
- FastOS_Time t = _now;
- t.SubtractMilliSecs((double)_config._iocTimeOut);
- fastos::UTCTimeStamp oldest(t);
+ time_point oldest = (_now - std::chrono::milliseconds(_config._iocTimeOut));
while (_timeOutHead != nullptr &&
oldest > _timeOutHead->_ioc_timestamp) {
diff --git a/fnet/src/vespa/fnet/transport_thread.h b/fnet/src/vespa/fnet/transport_thread.h
index 4fc4c58107d..8bced290962 100644
--- a/fnet/src/vespa/fnet/transport_thread.h
+++ b/fnet/src/vespa/fnet/transport_thread.h
@@ -7,12 +7,12 @@
#include "task.h"
#include "packetqueue.h"
#include <vespa/fastos/thread.h>
-#include <vespa/fastos/time.h>
#include <vespa/vespalib/net/socket_handle.h>
#include <vespa/vespalib/net/selector.h>
#include <atomic>
#include <mutex>
#include <condition_variable>
+#include <chrono>
class FNET_Transport;
class FNET_ControlPacket;
@@ -30,11 +30,12 @@ class FNET_TransportThread : public FastOS_Runnable
public:
using Selector = vespalib::Selector<FNET_IOComponent>;
+ using clock = FNET_Scheduler::clock;
+ using time_point = clock::time_point;
private:
FNET_Transport &_owner; // owning transport layer
- FastOS_Time _startTime; // when event loop started
- FastOS_Time _now; // current time sampler
+ time_point _now; // current time sampler
FNET_Scheduler _scheduler; // transport thread scheduler
FNET_Config _config; // FNET configuration [static]
FNET_IOComponent *_componentsHead; // I/O component list head
@@ -52,7 +53,6 @@ private:
std::atomic<bool> _shutdown; // should stop event loop ?
bool _finished; // event loop stopped ?
bool _waitFinished; // someone is waiting for _finished
- bool _deleted; // destructor called ?
FNET_TransportThread(const FNET_TransportThread &);
FNET_TransportThread &operator=(const FNET_TransportThread &);