aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2023-07-26 21:33:36 -0700
committerMike Buland <eichlan@xagasoft.com>2023-07-26 21:33:36 -0700
commite43a2cac32cb773994b11a3d964ec4acc372d273 (patch)
tree9e281be52f9dd8b80855c7d3cb9ec3df9cdd0ad3
parentb544779d5b759d4ab2b82654e3f53b82ea41bac7 (diff)
downloadlibbu++-e43a2cac32cb773994b11a3d964ec4acc372d273.tar.gz
libbu++-e43a2cac32cb773994b11a3d964ec4acc372d273.tar.bz2
libbu++-e43a2cac32cb773994b11a3d964ec4acc372d273.tar.xz
libbu++-e43a2cac32cb773994b11a3d964ec4acc372d273.zip
Added a profiler and investageted Server.
-rw-r--r--src/stable/client.cpp11
-rw-r--r--src/stable/client.h10
-rw-r--r--src/stable/server.cpp22
-rw-r--r--src/stable/server.h8
-rw-r--r--src/unstable/profiler.cpp184
-rw-r--r--src/unstable/profiler.h54
6 files changed, 288 insertions, 1 deletions
diff --git a/src/stable/client.cpp b/src/stable/client.cpp
index f6feb7c..56c5094 100644
--- a/src/stable/client.cpp
+++ b/src/stable/client.cpp
@@ -16,6 +16,13 @@
16 16
17/** Read buffer size. */ 17/** Read buffer size. */
18#define RBS (2000) // 1500 is the nominal MTU for ethernet, it's a good guess 18#define RBS (2000) // 1500 is the nominal MTU for ethernet, it's a good guess
19#ifdef PROFILE_BU_SERVER
20#define BU_PROFILE_START( x ) Bu::Profiler::getInstance().startEvent( x )
21#define BU_PROFILE_END( x ) Bu::Profiler::getInstance().endEvent( x )
22#else
23#define BU_PROFILE_START( x ) (void)0
24#define BU_PROFILE_END( x ) (void)0
25#endif
19 26
20Bu::Client::Client( Bu::TcpSocket *pSocket, 27Bu::Client::Client( Bu::TcpSocket *pSocket,
21 class Bu::ClientLinkFactory *pfLink ) : 28 class Bu::ClientLinkFactory *pfLink ) :
@@ -47,6 +54,7 @@ void Bu::Client::processInput()
47 char buf[RBS]; 54 char buf[RBS];
48 Bu::size nRead, nTotal=0; 55 Bu::size nRead, nTotal=0;
49 56
57 BU_PROFILE_START("client.read");
50 for(;;) 58 for(;;)
51 { 59 {
52 try 60 try
@@ -72,6 +80,7 @@ void Bu::Client::processInput()
72 break; 80 break;
73 } 81 }
74 } 82 }
83 BU_PROFILE_END("client.read");
75 mRead.unlock(); 84 mRead.unlock();
76 85
77 if( nTotal == 0 ) 86 if( nTotal == 0 )
@@ -82,7 +91,9 @@ void Bu::Client::processInput()
82 91
83 if( pProto && nTotal ) 92 if( pProto && nTotal )
84 { 93 {
94 BU_PROFILE_START("client.process");
85 pProto->onNewData( this ); 95 pProto->onNewData( this );
96 BU_PROFILE_END("client.process");
86 } 97 }
87} 98}
88 99
diff --git a/src/stable/client.h b/src/stable/client.h
index 119e2f7..abde682 100644
--- a/src/stable/client.h
+++ b/src/stable/client.h
@@ -16,6 +16,14 @@
16#include "bu/mutex.h" 16#include "bu/mutex.h"
17#include "bu/readwritemutex.h" 17#include "bu/readwritemutex.h"
18 18
19#ifndef PROFILE_BU_SERVER
20// #define PROFILE_BU_SERVER 1
21#endif
22
23#ifdef PROFILE_BU_SERVER
24#include "bu/profiler.h"
25#endif
26
19namespace Bu 27namespace Bu
20{ 28{
21 class Protocol; 29 class Protocol;
@@ -29,7 +37,7 @@ namespace Bu
29 class Client : public Bu::Stream 37 class Client : public Bu::Stream
30 { 38 {
31 public: 39 public:
32 Client( Bu::TcpSocket *pSocket, Bu::ClientLinkFactory *pfLink ); 40 Client( Bu::TcpSocket *pSocket, Bu::ClientLinkFactory *pfLink);
33 virtual ~Client(); 41 virtual ~Client();
34 42
35 void processInput(); 43 void processInput();
diff --git a/src/stable/server.cpp b/src/stable/server.cpp
index 3c42bf4..0552510 100644
--- a/src/stable/server.cpp
+++ b/src/stable/server.cpp
@@ -13,17 +13,27 @@
13#include "bu/tcpsocket.h" 13#include "bu/tcpsocket.h"
14#include "bu/config.h" 14#include "bu/config.h"
15 15
16#ifdef PROFILE_BU_SERVER
17#define BU_PROFILE_START( x ) Bu::Profiler::getInstance().startEvent( x )
18#define BU_PROFILE_END( x ) Bu::Profiler::getInstance().endEvent( x )
19#else
20#define BU_PROFILE_START( x ) (void)0
21#define BU_PROFILE_END( x ) (void)0
22#endif
23
16Bu::Server::Server() : 24Bu::Server::Server() :
17 nTimeoutSec( 0 ), 25 nTimeoutSec( 0 ),
18 nTimeoutUSec( 0 ), 26 nTimeoutUSec( 0 ),
19 bAutoTick( false ) 27 bAutoTick( false )
20{ 28{
29 BU_PROFILE_START("server");
21 FD_ZERO( &fdActive ); 30 FD_ZERO( &fdActive );
22} 31}
23 32
24Bu::Server::~Server() 33Bu::Server::~Server()
25{ 34{
26 shutdown(); 35 shutdown();
36 BU_PROFILE_START("server");
27} 37}
28 38
29void Bu::Server::addPort( int nPort, int nPoolSize ) 39void Bu::Server::addPort( int nPort, int nPoolSize )
@@ -50,6 +60,7 @@ void Bu::Server::setTimeout( int nTimeoutSec, int nTimeoutUSec )
50 60
51void Bu::Server::scan() 61void Bu::Server::scan()
52{ 62{
63 BU_PROFILE_START("scan");
53 struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec }; 64 struct timeval xTimeout = { nTimeoutSec, nTimeoutUSec };
54 65
55 fd_set fdRead = fdActive; 66 fd_set fdRead = fdActive;
@@ -68,6 +79,7 @@ void Bu::Server::scan()
68 { 79 {
69 char buf[1024]; 80 char buf[1024];
70 strerror_r( errno, buf, 1024 ); 81 strerror_r( errno, buf, 1024 );
82 BU_PROFILE_END("scan");
71 throw ExceptionBase( 83 throw ExceptionBase(
72 Bu::String("Error attempting to scan open connections: %1: %2").arg( errno ).arg( buf ).end().getStr() 84 Bu::String("Error attempting to scan open connections: %1: %2").arg( errno ).arg( buf ).end().getStr()
73 ); 85 );
@@ -85,7 +97,9 @@ void Bu::Server::scan()
85 else 97 else
86 { 98 {
87 Client *pClient = hClients.get( j ); 99 Client *pClient = hClients.get( j );
100 BU_PROFILE_START("processInput");
88 pClient->processInput(); 101 pClient->processInput();
102 BU_PROFILE_END("processInput");
89 if( !pClient->isOpen() ) 103 if( !pClient->isOpen() )
90 { 104 {
91 closeClient( j ); 105 closeClient( j );
@@ -99,7 +113,9 @@ void Bu::Server::scan()
99 Client *pClient = hClients.get( j ); 113 Client *pClient = hClients.get( j );
100 try 114 try
101 { 115 {
116 BU_PROFILE_START("processOutput");
102 pClient->processOutput(); 117 pClient->processOutput();
118 BU_PROFILE_END("processOutput");
103 } 119 }
104 catch( Bu::TcpSocketException &e ) 120 catch( Bu::TcpSocketException &e )
105 { 121 {
@@ -133,10 +149,13 @@ void Bu::Server::scan()
133 149
134 if( bAutoTick ) 150 if( bAutoTick )
135 tick(); 151 tick();
152
153 BU_PROFILE_END("scan");
136} 154}
137 155
138void Bu::Server::addClient( socket_t nSocket, int nPort ) 156void Bu::Server::addClient( socket_t nSocket, int nPort )
139{ 157{
158 BU_PROFILE_START("addClient");
140 FD_SET( nSocket, &fdActive ); 159 FD_SET( nSocket, &fdActive );
141 160
142 Client *c = new Client( 161 Client *c = new Client(
@@ -146,6 +165,7 @@ void Bu::Server::addClient( socket_t nSocket, int nPort )
146 hClients.insert( nSocket, c ); 165 hClients.insert( nSocket, c );
147 166
148 onNewConnection( c, nPort ); 167 onNewConnection( c, nPort );
168 BU_PROFILE_END("addClient");
149} 169}
150 170
151Bu::Server::SrvClientLink::SrvClientLink( Bu::Client *pClient ) : 171Bu::Server::SrvClientLink::SrvClientLink( Bu::Client *pClient ) :
@@ -208,11 +228,13 @@ void Bu::Server::shutdown()
208 228
209void Bu::Server::closeClient( socket_t iSocket ) 229void Bu::Server::closeClient( socket_t iSocket )
210{ 230{
231 BU_PROFILE_START("closeClient");
211 Bu::Client *pClient = hClients.get( iSocket ); 232 Bu::Client *pClient = hClients.get( iSocket );
212 onClosedConnection( pClient ); 233 onClosedConnection( pClient );
213 pClient->close(); 234 pClient->close();
214 hClients.erase( iSocket ); 235 hClients.erase( iSocket );
215 FD_CLR( iSocket, &fdActive ); 236 FD_CLR( iSocket, &fdActive );
216 delete pClient; 237 delete pClient;
238 BU_PROFILE_END("closeClient");
217} 239}
218 240
diff --git a/src/stable/server.h b/src/stable/server.h
index ee76fd2..d3f0903 100644
--- a/src/stable/server.h
+++ b/src/stable/server.h
@@ -23,6 +23,14 @@
23 23
24#include "bu/config.h" 24#include "bu/config.h"
25 25
26#ifndef PROFILE_BU_SERVER
27// #define PROFILE_BU_SERVER 1
28#endif
29
30#ifdef PROFILE_BU_SERVER
31#include "bu/profiler.h"
32#endif
33
26namespace Bu 34namespace Bu
27{ 35{
28 class TcpServerSocket; 36 class TcpServerSocket;
diff --git a/src/unstable/profiler.cpp b/src/unstable/profiler.cpp
new file mode 100644
index 0000000..1b176b9
--- /dev/null
+++ b/src/unstable/profiler.cpp
@@ -0,0 +1,184 @@
1#include "bu/profiler.h"
2#include "bu/mutexlocker.h"
3#include "bu/sio.h"
4
5#include <sys/time.h>
6
7Bu::Profiler::Profiler()
8{
9}
10
11Bu::Profiler::~Profiler()
12{
13 printReport();
14}
15
16uint64_t Bu::Profiler::getMicroTime()
17{
18 struct timeval tv;
19 gettimeofday( &tv, NULL );
20 return ((uint64_t)tv.tv_sec)*1000000 + ((uint64_t)tv.tv_usec);
21}
22
23void Bu::Profiler::startEvent( const Bu::Blob &bName )
24{
25 Bu::MutexLocker l( mLock );
26 if( hEvent.has( bName ) )
27 {
28 hEvent.get( bName ).append( Event() );
29 }
30 else
31 {
32 hEvent.insert( bName, EventList( Event() ) );
33 }
34}
35
36void Bu::Profiler::endEvent( const Bu::Blob &bName )
37{
38 Bu::MutexLocker l( mLock );
39 if( !hEvent.has( bName ) )
40 return;
41
42 if( hEvent.get( bName ).isEmpty() )
43 return;
44
45 hEvent.get( bName ).last().end();
46}
47
48void Bu::Profiler::printReport() const
49{
50 class Breakdown
51 {
52 public:
53 Breakdown( const Bu::Blob &bName ) :
54 bName( bName ), uCount( 0 ), uTotal( 0 ), uMin( 0 ), uMax( 0 ) { }
55 Breakdown( const Breakdown &rSrc ) :
56 bName( rSrc.bName ), uCount( rSrc.uCount ), uTotal( rSrc.uTotal ),
57 uMin( rSrc.uMin ), uMax( rSrc.uMax ) { }
58 ~Breakdown() { }
59
60 bool operator<( const Breakdown &rhs ) const
61 {
62 return uTotal > rhs.uTotal;
63 }
64 Breakdown &operator=( const Breakdown &rhs )
65 {
66 bName = rhs.bName;
67 uCount = rhs.uCount;
68 uTotal = rhs.uTotal;
69 uMin = rhs.uMin;
70 uMax = rhs.uMax;
71 return *this;
72 }
73
74 void add( uint64_t uSpan )
75 {
76 if( uCount == 0 )
77 {
78 uMin = uMax = uSpan;
79 }
80 else
81 {
82 if( uMin > uSpan )
83 uMin = uSpan;
84 if( uMax < uSpan )
85 uMax = uSpan;
86
87 }
88 uCount++;
89 uTotal += uSpan;
90 }
91
92 Bu::Blob bName;
93 uint64_t uCount;
94 uint64_t uTotal;
95 uint64_t uMin;
96 uint64_t uMax;
97 };
98 Bu::MutexLocker l( mLock );
99
100 int iTitleLen = 0;
101 Bu::List<Breakdown> lBreakdown;
102 for( EventListHash::const_iterator iType = hEvent.begin(); iType; iType++ )
103 {
104 Breakdown b( iType.getKey() );
105 if( iTitleLen < b.bName.getSize() )
106 iTitleLen = b.bName.getSize();
107 for( EventList::const_iterator iEv = iType.getValue().begin();
108 iEv; iEv++ )
109 {
110 b.add( (*iEv).getSpan() );
111 }
112 lBreakdown.append( b );
113 }
114
115 lBreakdown.sort();
116
117 Bu::println("%1 %2 %3 %4 %5 %6")
118 .arg("Title", Bu::Fmt(iTitleLen) )
119 .arg("Cnt", Bu::Fmt(5) )
120 .arg("Total", Bu::Fmt(9) )
121 .arg("Avg", Bu::Fmt(9) )
122 .arg("Max", Bu::Fmt(9) )
123 .arg("Min", Bu::Fmt(9) );
124 for( Bu::List<Breakdown>::iterator i = lBreakdown.begin(); i; i++ )
125 {
126 Bu::println("%1 %2 %3.%4 %5.%6 %7.%8 %9.%10")
127 .arg( (*i).bName.getData(), Bu::Fmt(iTitleLen) )
128 .arg( (*i).uCount, Bu::Fmt(5) )
129 .arg( ((*i).uTotal/1000000), Bu::Fmt(5).right() )
130 .arg( ((*i).uTotal/1000)%1000, Bu::Fmt(3).fill('0').right() )
131 .arg( ((*i).uTotal/(*i).uCount)/1000000, Bu::Fmt(5).right() )
132 .arg( (((*i).uTotal/(*i).uCount)/1000)%1000, Bu::Fmt(3).right().fill('0') )
133 .arg( (*i).uMax/1000000, Bu::Fmt(5).right() )
134 .arg( ((*i).uMax/1000)%1000, Bu::Fmt(3).right().fill('0') )
135 .arg( (*i).uMin/1000000, Bu::Fmt(5).right() )
136 .arg( ((*i).uMin/1000)%1000, Bu::Fmt(3).right().fill('0') )
137 ;
138 }
139}
140
141Bu::Profiler::Event::Event() :
142 iStart( Bu::Profiler::getMicroTime() ),
143 iStop( 0 )
144{
145}
146
147Bu::Profiler::Event::Event( const Event &rSrc ) :
148 iStart( rSrc.iStart ),
149 iStop( rSrc.iStop )
150{
151}
152
153Bu::Profiler::Event::~Event()
154{
155}
156
157void Bu::Profiler::Event::end()
158{
159 if( iStop == 0 )
160 iStop = Bu::Profiler::getMicroTime();
161}
162
163bool Bu::Profiler::Event::hasEnded() const
164{
165 return iStop != 0;
166}
167
168uint64_t Bu::Profiler::Event::getStart() const
169{
170 return iStart;
171}
172
173uint64_t Bu::Profiler::Event::getEnd() const
174{
175 return iStop;
176}
177
178uint64_t Bu::Profiler::Event::getSpan() const
179{
180 if( iStop < iStart )
181 return 0;
182 return iStop-iStart;
183}
184
diff --git a/src/unstable/profiler.h b/src/unstable/profiler.h
new file mode 100644
index 0000000..df05023
--- /dev/null
+++ b/src/unstable/profiler.h
@@ -0,0 +1,54 @@
1#ifndef BU_PROFILER_H
2#define BU_PROFILER_H
3
4#include "bu/blob.h"
5#include "bu/hash.h"
6#include "bu/list.h"
7#include "bu/mutex.h"
8#include "bu/singleton.h"
9
10namespace Bu
11{
12 class Profiler : public Bu::Singleton<Profiler>
13 {
14 friend class Bu::Singleton<Profiler>;
15 private:
16 Profiler();
17 virtual ~Profiler();
18
19 public:
20 static uint64_t getMicroTime();
21
22 void startEvent( const Bu::Blob &bName );
23 void endEvent( const Bu::Blob &bName );
24
25 void printReport() const;
26
27 private:
28 class Event
29 {
30 public:
31 Event();
32 Event( const Event &rSrc );
33 ~Event();
34
35 void end();
36 bool hasEnded() const;
37
38 uint64_t getStart() const;
39 uint64_t getEnd() const;
40 uint64_t getSpan() const;
41
42 private:
43 uint64_t iStart;
44 uint64_t iStop;
45 };
46
47 typedef Bu::List<Event> EventList;
48 typedef Bu::Hash<Bu::Blob, EventList> EventListHash;
49 EventListHash hEvent;
50 mutable Bu::Mutex mLock;
51 };
52};
53
54#endif