From 7e46119759b7099c38f543bd38d0186b9806542f Mon Sep 17 00:00:00 2001 From: danieldg Date: Mon, 18 Jan 2010 19:36:41 +0000 Subject: Remove excessive gettimeofday system calls git-svn-id: http://svn.inspircd.org/repository/trunk/inspircd@12293 e03df62e-2008-0410-955e-edbf42e46eb7 --- src/configreader.cpp | 2 +- src/dns.cpp | 19 +++++++--- src/inspircd.cpp | 61 +++++++++++++++---------------- src/modules/m_spanningtree/main.cpp | 4 +- src/modules/m_spanningtree/pong.cpp | 8 +--- src/modules/m_spanningtree/treeserver.cpp | 8 +--- src/modules/m_spanningtree/treeserver.h | 2 +- src/socketengines/socketengine_epoll.cpp | 1 + src/socketengines/socketengine_kqueue.cpp | 1 + src/socketengines/socketengine_poll.cpp | 1 + src/socketengines/socketengine_ports.cpp | 1 + src/socketengines/socketengine_select.cpp | 1 + src/stats.cpp | 5 +-- src/userprocess.cpp | 8 ++-- 14 files changed, 62 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/configreader.cpp b/src/configreader.cpp index c62973c89..156168bbe 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -872,7 +872,7 @@ void ConfigReaderThread::Finish() ServerInstance->Res->Rehash(); ServerInstance->ResetMaxBans(); Config->ApplyDisabledCommands(Config->DisabledCommands); - User* user = TheUserUID.empty() ? ServerInstance->FindNick(TheUserUID) : NULL; + User* user = ServerInstance->FindNick(TheUserUID); FOREACH_MOD(I_OnRehash, OnRehash(user)); ServerInstance->BuildISupport(); diff --git a/src/dns.cpp b/src/dns.cpp index ba1e8f2a4..dee83d3ac 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -147,6 +147,17 @@ class RequestTimeout : public Timer } }; +CachedQuery::CachedQuery(const std::string &res, unsigned int ttl) : data(res) +{ + expires = ServerInstance->Time() + ttl; +} + +int CachedQuery::CalcTTLRemaining() +{ + int n = expires - ServerInstance->Time(); + return (n < 0 ? 0 : n); +} + /* Allocate the processing buffer */ DNSRequest::DNSRequest(DNS* dns, int rid, const std::string &original) : dnsobj(dns) { @@ -1035,11 +1046,9 @@ void DNS::CleanResolvers(Module* module) unsigned long DNS::PRNG() { unsigned long val = 0; - timeval n; serverstats* s = ServerInstance->stats; - gettimeofday(&n,NULL); - val = (n.tv_usec ^ (getpid() ^ geteuid()) ^ ((this->currid++)) ^ s->statsAccept) + n.tv_sec; - val = val + (s->statsCollisions ^ s->statsDnsGood) - s->statsDnsBad; - val += (s->statsConnects ^ (unsigned long)s->statsSent ^ (unsigned long)s->statsRecv) - ServerInstance->ports.size(); + val = (rand() ^ this->currid++ ^ s->statsAccept) + ServerInstance->Time_ns(); + val += (s->statsCollisions ^ s->statsDnsGood) * s->statsDnsBad; + val += (s->statsConnects ^ (unsigned long)s->statsSent ^ (unsigned long)s->statsRecv); return val; } diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 8cead1c87..47f743df2 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -340,7 +340,8 @@ InspIRCd::InspIRCd(int argc, char** argv) : this->ConfigThread = NULL; // Initialise TIME - this->TIME = this->OLDTIME = this->startup_time = time(NULL); + clock_gettime(CLOCK_REALTIME, &TIME); + this->startup_time = TIME.tv_sec; // This must be created first, so other parts of Insp can use it while starting up this->Logs = new LogManager; @@ -375,7 +376,7 @@ InspIRCd::InspIRCd(int argc, char** argv) : this->Config->cmdline.argv = argv; this->Config->cmdline.argc = argc; - srand(this->TIME); + srand(TIME.tv_nsec ^ TIME.tv_sec); struct option longopts[] = { @@ -685,6 +686,11 @@ InspIRCd::InspIRCd(int argc, char** argv) : this->WritePID(Config->PID); } +void InspIRCd::UpdateTime() +{ + clock_gettime(CLOCK_REALTIME, &TIME); +} + int InspIRCd::Run() { /* See if we're supposed to be running the test suite rather than entering the mainloop */ @@ -695,6 +701,9 @@ int InspIRCd::Run() Exit(0); } + UpdateTime(); + time_t OLDTIME = TIME.tv_sec; + while (true) { #ifndef WIN32 @@ -718,53 +727,48 @@ int InspIRCd::Run() ConfigThread = NULL; } - /* time() seems to be a pretty expensive syscall, so avoid calling it too much. - * Once per loop iteration is pleanty. - */ - OLDTIME = TIME; - TIME = time(NULL); + UpdateTime(); /* Run background module timers every few seconds * (the docs say modules shouldnt rely on accurate * timing using this event, so we dont have to * time this exactly). */ - if (TIME != OLDTIME) + if (TIME.tv_sec != OLDTIME) { + OLDTIME = TIME.tv_sec; +#ifndef WIN32 + getrusage(RUSAGE_SELF, &ru); + stats->LastSampled = TIME; + stats->LastCPU = ru.ru_utime; +#else + WindowsIPC->Check(); +#endif + /* Allow a buffer of two seconds drift on this so that ntpdate etc dont harass admins */ - if (TIME < OLDTIME - 2) + if (TIME.tv_sec < OLDTIME - 2) { - SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is flowing BACKWARDS in this dimension! Clock drifted backwards %lu secs.", (unsigned long)OLDTIME-TIME); + SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is flowing BACKWARDS in this dimension! Clock drifted backwards %lu secs.", (unsigned long)OLDTIME-TIME.tv_sec); } - else if (TIME > OLDTIME + 2) + else if (TIME.tv_sec > OLDTIME + 2) { - SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is jumping FORWARDS! Clock skipped %lu secs.", (unsigned long)TIME - OLDTIME); + SNO->WriteToSnoMask('d', "\002EH?!\002 -- Time is jumping FORWARDS! Clock skipped %lu secs.", (unsigned long)TIME.tv_sec - OLDTIME); } - if ((TIME % 3600) == 0) + if ((TIME.tv_sec % 3600) == 0) { this->RehashUsersAndChans(); FOREACH_MOD(I_OnGarbageCollect, OnGarbageCollect()); } - Timers->TickTimers(TIME); + Timers->TickTimers(TIME.tv_sec); this->DoBackgroundUserStuff(); - if ((TIME % 5) == 0) + if ((TIME.tv_sec % 5) == 0) { - FOREACH_MOD(I_OnBackgroundTimer,OnBackgroundTimer(TIME)); + FOREACH_MOD(I_OnBackgroundTimer,OnBackgroundTimer(TIME.tv_sec)); SNO->FlushSnotices(); } -#ifndef WIN32 - /* Same change as in cmd_stats.cpp, use RUSAGE_SELF rather than '0' -- Om */ - if (!getrusage(RUSAGE_SELF, &ru)) - { - gettimeofday(&this->stats->LastSampled, NULL); - this->stats->LastCPU = ru.ru_utime; - } -#else - WindowsIPC->Check(); -#endif } /* Call the socket engine to wait on the active @@ -808,11 +812,6 @@ bool InspIRCd::AllModulesReportReady(LocalUser* user) return (res == MOD_RES_PASSTHRU); } -time_t InspIRCd::Time() -{ - return TIME; -} - void InspIRCd::SetSignal(int signal) { *mysig = signal; diff --git a/src/modules/m_spanningtree/main.cpp b/src/modules/m_spanningtree/main.cpp index 4961d724b..18f399bbf 100644 --- a/src/modules/m_spanningtree/main.cpp +++ b/src/modules/m_spanningtree/main.cpp @@ -128,9 +128,7 @@ void ModuleSpanningTree::DoPingChecks(time_t curtime) * Cancel remote burst mode on any servers which still have it enabled due to latency/lack of data. * This prevents lost REMOTECONNECT notices */ - timeval t; - gettimeofday(&t, NULL); - long ts = (t.tv_sec * 1000) + (t.tv_usec / 1000); + long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000); for (server_hash::iterator i = Utils->serverlist.begin(); i != Utils->serverlist.end(); i++) { diff --git a/src/modules/m_spanningtree/pong.cpp b/src/modules/m_spanningtree/pong.cpp index dd82f7d86..9627da8c0 100644 --- a/src/modules/m_spanningtree/pong.cpp +++ b/src/modules/m_spanningtree/pong.cpp @@ -34,9 +34,7 @@ bool TreeSocket::LocalPong(const std::string &prefix, parameterlist ¶ms) if (ServerSource) { ServerSource->SetPingFlag(); - timeval t; - gettimeofday(&t, NULL); - long ts = (t.tv_sec * 1000) + (t.tv_usec / 1000); + long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000); ServerSource->rtt = ts - ServerSource->LastPingMsec; } } @@ -61,9 +59,7 @@ bool TreeSocket::LocalPong(const std::string &prefix, parameterlist ¶ms) if (ServerSource) { - timeval t; - gettimeofday(&t, NULL); - long ts = (t.tv_sec * 1000) + (t.tv_usec / 1000); + long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000); ServerSource->rtt = ts - ServerSource->LastPingMsec; ServerSource->SetPingFlag(); } diff --git a/src/modules/m_spanningtree/treeserver.cpp b/src/modules/m_spanningtree/treeserver.cpp index d5c3927f9..00799aa8e 100644 --- a/src/modules/m_spanningtree/treeserver.cpp +++ b/src/modules/m_spanningtree/treeserver.cpp @@ -59,9 +59,7 @@ TreeServer::TreeServer(SpanningTreeUtilities* Util, std::string Name, std::strin Warned = false; rtt = 0; - timeval t; - gettimeofday(&t, NULL); - long ts = (t.tv_sec * 1000) + (t.tv_usec / 1000); + long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000); this->StartBurst = ts; ServerInstance->Logs->Log("m_spanningtree",DEBUG, "Started bursting at time %lu", ts); @@ -142,9 +140,7 @@ void TreeServer::FinishBurst() { FinishBurstInternal(); ServerInstance->XLines->ApplyLines(); - timeval t; - gettimeofday(&t, NULL); - long ts = (t.tv_sec * 1000) + (t.tv_usec / 1000); + long ts = ServerInstance->Time() * 1000 + (ServerInstance->Time_ns() / 1000000); unsigned long bursttime = ts - this->StartBurst; ServerInstance->SNO->WriteToSnoMask(Parent == Utils->TreeRoot ? 'l' : 'L', "Received end of netburst from \2%s\2 (burst time: %lu %s)", ServerName.c_str(), (bursttime > 10000 ? bursttime / 1000 : bursttime), (bursttime > 10000 ? "secs" : "msecs")); diff --git a/src/modules/m_spanningtree/treeserver.h b/src/modules/m_spanningtree/treeserver.h index 9520506ae..079b6535e 100644 --- a/src/modules/m_spanningtree/treeserver.h +++ b/src/modules/m_spanningtree/treeserver.h @@ -109,7 +109,7 @@ class TreeServer : public classbase */ time_t NextPingTime(); - /** Last ping time in microseconds, used to calculate round trip time + /** Last ping time in milliseconds, used to calculate round trip time */ unsigned long LastPingMsec; diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp index 11fa72072..96c3922f9 100644 --- a/src/socketengines/socketengine_epoll.cpp +++ b/src/socketengines/socketengine_epoll.cpp @@ -187,6 +187,7 @@ int EPollEngine::DispatchEvents() socklen_t codesize = sizeof(int); int errcode; int i = epoll_wait(EngineHandle, events, GetMaxFds() - 1, 1000); + ServerInstance->UpdateTime(); TotalEvents += i; diff --git a/src/socketengines/socketengine_kqueue.cpp b/src/socketengines/socketengine_kqueue.cpp index ca909ce3e..e7d7e4283 100644 --- a/src/socketengines/socketengine_kqueue.cpp +++ b/src/socketengines/socketengine_kqueue.cpp @@ -217,6 +217,7 @@ int KQueueEngine::DispatchEvents() ts.tv_sec = 1; int i = kevent(EngineHandle, NULL, 0, &ke_list[0], GetMaxFds(), &ts); + ServerInstance->UpdateTime(); TotalEvents += i; diff --git a/src/socketengines/socketengine_poll.cpp b/src/socketengines/socketengine_poll.cpp index f30cd1fed..93463aea7 100644 --- a/src/socketengines/socketengine_poll.cpp +++ b/src/socketengines/socketengine_poll.cpp @@ -235,6 +235,7 @@ int PollEngine::DispatchEvents() socklen_t codesize = sizeof(int); int errcode; int processed = 0; + ServerInstance->UpdateTime(); if (i > 0) { diff --git a/src/socketengines/socketengine_ports.cpp b/src/socketengines/socketengine_ports.cpp index 43d958173..23a3c3a45 100644 --- a/src/socketengines/socketengine_ports.cpp +++ b/src/socketengines/socketengine_ports.cpp @@ -167,6 +167,7 @@ int PortsEngine::DispatchEvents() unsigned int nget = 1; // used to denote a retrieve request. int i = port_getn(EngineHandle, this->events, GetMaxFds() - 1, &nget, &poll_time); + ServerInstance->UpdateTime(); // first handle an error condition if (i == -1) diff --git a/src/socketengines/socketengine_select.cpp b/src/socketengines/socketengine_select.cpp index 7bff4ff6d..795e844e6 100644 --- a/src/socketengines/socketengine_select.cpp +++ b/src/socketengines/socketengine_select.cpp @@ -119,6 +119,7 @@ int SelectEngine::DispatchEvents() tval.tv_usec = 0; sresult = select(FD_SETSIZE, &rfdset, &wfdset, &errfdset, &tval); + ServerInstance->UpdateTime(); /* Nothing to process this time around */ if (sresult < 1) diff --git a/src/stats.cpp b/src/stats.cpp index b295db4a5..b272e0b6b 100644 --- a/src/stats.cpp +++ b/src/stats.cpp @@ -194,11 +194,10 @@ void InspIRCd::DoStats(char statschar, User* user, string_list &results) results.push_back(sn+" 249 "+user->nick+" :Swaps: "+ConvToStr(R.ru_nswap)); results.push_back(sn+" 249 "+user->nick+" :Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw)); - timeval tv; char percent[30]; - gettimeofday(&tv, NULL); - float n_elapsed = ((tv.tv_sec - this->stats->LastSampled.tv_sec) * 1000000 + tv.tv_usec - this->stats->LastSampled.tv_usec); + float n_elapsed = (ServerInstance->Time() - this->stats->LastSampled.tv_sec) * 1000000 + + (ServerInstance->Time_ns() - this->stats->LastSampled.tv_nsec) / 1000; float n_eaten = ((R.ru_utime.tv_sec - this->stats->LastCPU.tv_sec) * 1000000 + R.ru_utime.tv_usec - this->stats->LastCPU.tv_usec); float per = (n_eaten / n_elapsed) * 100; diff --git a/src/userprocess.cpp b/src/userprocess.cpp index 75cd8634a..ee9c75bc0 100644 --- a/src/userprocess.cpp +++ b/src/userprocess.cpp @@ -68,7 +68,7 @@ void InspIRCd::DoBackgroundUserStuff() switch (curr->registered) { case REG_ALL: - if (TIME > curr->nping) + if (Time() > curr->nping) { // This user didn't answer the last ping, remove them if (!curr->lastping) @@ -77,14 +77,14 @@ void InspIRCd::DoBackgroundUserStuff() char message[MAXBUF]; snprintf(message, MAXBUF, "Ping timeout: %ld second%s", (long)time, time > 1 ? "s" : ""); curr->lastping = 1; - curr->nping = TIME + curr->MyClass->GetPingTime(); + curr->nping = Time() + curr->MyClass->GetPingTime(); this->Users->QuitUser(curr, message); continue; } curr->Write("PING :%s",this->Config->ServerName.c_str()); curr->lastping = 0; - curr->nping = TIME +curr->MyClass->GetPingTime(); + curr->nping = Time() +curr->MyClass->GetPingTime(); } break; case REG_NICKUSER: @@ -97,7 +97,7 @@ void InspIRCd::DoBackgroundUserStuff() break; } - if (curr->registered != REG_ALL && (TIME > (curr->age + curr->MyClass->GetRegTimeout()))) + if (curr->registered != REG_ALL && (Time() > (curr->age + curr->MyClass->GetRegTimeout()))) { /* * registration timeout -- didnt send USER/NICK/HOST -- cgit v1.2.3