Skip to content

Commit df885d5

Browse files
committed
Collect network statistics and make it available for the user applications. (#8310)
* Make Remote provider collect wire statistics. New info items to query wire stats counters. * New ISQL commands to show wire statistics. * Remove requirement to not mix local and remote handled items in the same info request. * Follow @asfernandes suggestion about class members initialization. * Make ctor explicit, as @sim1984 suggested * Put isc_info_end into response buffer despite of its presence in info items.
1 parent 8ca2314 commit df885d5

File tree

12 files changed

+514
-21
lines changed

12 files changed

+514
-21
lines changed

doc/README.isql_enhancements.txt

Lines changed: 121 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,10 +327,129 @@ SQL> SET PER_TAB OFF;
327327

328328

329329

330+
12) SET WIRE_STATS option.
331+
332+
Author: Vladyslav Khorsun <hvlad at users sourceforge net>
333+
334+
When set to ON shows wire (network) statistics after query execution.
335+
It is set to OFF by default. The name WIRE_STATS could be shortened up to WIRE.
336+
337+
The statistics counters shown in two groups: 'logical' and 'physical':
338+
- logical counters show numbers of packets in terms of Firebird wire protocol
339+
and number of bytes send before compression and received after decompression;
340+
- physical counters show number of physical packets and bytes send and
341+
received over the wire, number of bytes could be affected by wire compression,
342+
if present. Also, number of network roundtrips is shown: it is number of
343+
changes of IO direction from 'send' to 'receive'.
344+
345+
Note, wire statistics is gathered by Remote provider only, i.e. it is always
346+
zero for embedded connections. Also, it is collected by client and IO direction
347+
(send, receive) is shown from client point of view.
348+
349+
Examples:
350+
351+
1. INET protocol with wire compression.
352+
Set WireCompression = true in firebird.conf
353+
354+
>isql inet://employee
355+
356+
SQL> SET;
357+
Print statistics: OFF
358+
Print per-table stats: OFF
359+
Print wire stats: OFF
360+
...
361+
362+
SQL> SET WIRE;
363+
SQL>
364+
SQL> SELECT COUNT(*) FROM RDB$RELATIONS;
365+
366+
COUNT
367+
=====================
368+
67
369+
370+
Wire logical statistics:
371+
send packets = 6
372+
recv packets = 5
373+
send bytes = 184
374+
recv bytes = 224
375+
Wire physical statistics:
376+
send packets = 3
377+
recv packets = 2
378+
send bytes = 123
379+
recv bytes = 88
380+
roundtrips = 2
381+
382+
Note difference due to wire compression in send/recv bytes for logical and
383+
physical stats.
384+
385+
386+
2. XNET protocol (wire compression is not used).
387+
388+
>isql xnet://employee
389+
390+
SQL> SET WIRE;
391+
SQL>
392+
SQL> SELECT COUNT(*) FROM RDB$RELATIONS;
393+
394+
COUNT
395+
=====================
396+
67
397+
398+
Wire logical statistics:
399+
send packets = 5
400+
recv packets = 6
401+
send bytes = 176
402+
recv bytes = 256
403+
Wire physical statistics:
404+
send packets = 5
405+
recv packets = 5
406+
send bytes = 176
407+
recv bytes = 256
408+
roundtrips = 5
409+
410+
Note, send/recv bytes for logical and physical stats are equal.
411+
412+
413+
3. Embedded connection (wire statistics is absent).
414+
415+
SQL> SET WIRE;
416+
SQL>
417+
SQL> select count(*) from rdb$relations;
418+
419+
COUNT
420+
=====================
421+
67
422+
423+
Wire logical statistics:
424+
send packets = 0
425+
recv packets = 0
426+
send bytes = 0
427+
recv bytes = 0
428+
Wire physical statistics:
429+
send packets = 0
430+
recv packets = 0
431+
send bytes = 0
432+
recv bytes = 0
433+
roundtrips = 0
434+
435+
436+
437+
13) SHOW WIRE_STATISTICS command.
438+
439+
Author: Vladyslav Khorsun <hvlad at users sourceforge net>
440+
441+
New ISQL command that shows accumulated wire statistics. There is also
442+
shortened alias WIRE_STATS.
443+
444+
The command show values of wire statistics counters, accumulated since the
445+
connection start time. Format is the same as of SET STATS above.
446+
447+
448+
330449
Isql enhancements in Firebird v6.
331450
---------------------------------
332451

333-
12) EXPLAIN statement.
452+
14) EXPLAIN statement.
334453

335454
Author: Adriano dos Santos Fernandes
336455

@@ -355,7 +474,7 @@ SQL>
355474
SQL> set term ;!
356475

357476

358-
13) SET AUTOTERM ON/OFF
477+
15) SET AUTOTERM ON/OFF
359478

360479
Author: Adriano dos Santos Fernandes
361480

src/include/firebird/impl/inf_pub.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,17 @@ enum db_info_types
178178

179179
fb_info_parallel_workers = 149,
180180

181+
// Wire stats items, implemented by Remote provider only
182+
fb_info_wire_out_packets = 150,
183+
fb_info_wire_in_packets = 151,
184+
fb_info_wire_out_bytes = 152,
185+
fb_info_wire_in_bytes = 153,
186+
fb_info_wire_snd_packets = 154,
187+
fb_info_wire_rcv_packets = 155,
188+
fb_info_wire_snd_bytes = 156,
189+
fb_info_wire_rcv_bytes = 157,
190+
fb_info_wire_roundtrips = 158,
191+
181192
isc_info_db_last_value /* Leave this LAST! */
182193
};
183194

src/include/gen/Firebird.pas

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4507,6 +4507,15 @@ IProfilerStatsImpl = class(IProfilerStats)
45074507
fb_info_username = byte(147);
45084508
fb_info_sqlrole = byte(148);
45094509
fb_info_parallel_workers = byte(149);
4510+
fb_info_wire_out_packets = byte(150);
4511+
fb_info_wire_in_packets = byte(151);
4512+
fb_info_wire_out_bytes = byte(152);
4513+
fb_info_wire_in_bytes = byte(153);
4514+
fb_info_wire_snd_packets = byte(154);
4515+
fb_info_wire_rcv_packets = byte(155);
4516+
fb_info_wire_snd_bytes = byte(156);
4517+
fb_info_wire_rcv_bytes = byte(157);
4518+
fb_info_wire_roundtrips = byte(158);
45104519
fb_info_crypt_encrypted = $01;
45114520
fb_info_crypt_process = $02;
45124521
fb_feature_multi_statements = byte(1);

src/isql/isql.epp

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ public:
577577
KeepTranParams = true;
578578
TranParams->assign(DEFAULT_DML_TRANS_SQL);
579579
PerTableStats = false;
580+
WireStats = false;
580581
ExplainCommand = false;
581582
}
582583

@@ -603,6 +604,7 @@ public:
603604
SCHAR ISQL_charset[MAXCHARSET_SIZE];
604605
bool KeepTranParams;
605606
bool PerTableStats;
607+
bool WireStats;
606608
bool ExplainCommand;
607609
};
608610

@@ -5453,7 +5455,7 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
54535455
exec_path_display,
54545456
sql, warning, sqlCont, heading, bail,
54555457
bulk_insert, maxrows, stmtTimeout,
5456-
keepTranParams, perTableStats,
5458+
keepTranParams, perTableStats, wireStats,
54575459
wrong
54585460
};
54595461
SetOptions(const optionsMap* inmap, size_t insize, int wrongval)
@@ -5495,7 +5497,8 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
54955497
{SetOptions::stmtTimeout, "LOCAL_TIMEOUT", 0},
54965498
{SetOptions::sqlCont, "DECFLOAT", 0},
54975499
{SetOptions::keepTranParams, "KEEP_TRAN_PARAMS", 9},
5498-
{SetOptions::perTableStats, "PER_TABLE_STATS", 7}
5500+
{SetOptions::perTableStats, "PER_TABLE_STATS", 7},
5501+
{SetOptions::wireStats, "WIRE_STATS", 4}
54995502
};
55005503

55015504
// Display current set options
@@ -5746,6 +5749,10 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
57465749
ret = do_set_command(parms[2], &setValues.PerTableStats);
57475750
break;
57485751

5752+
case SetOptions::wireStats:
5753+
ret = do_set_command(parms[2], &setValues.WireStats);
5754+
break;
5755+
57495756
default:
57505757
//{
57515758
// TEXT msg_string[MSG_LENGTH];
@@ -6372,6 +6379,7 @@ static processing_state print_sets()
63726379

63736380
print_set("Print statistics:", setValues.Stats);
63746381
print_set("Print per-table stats:", setValues.PerTableStats);
6382+
print_set("Print wire stats:", setValues.WireStats);
63756383
print_set("Echo commands:", setValues.Echo);
63766384
print_set("List format:", setValues.List);
63776385
print_set("Show Row Count:", setValues.Docount);
@@ -8950,6 +8958,10 @@ static processing_state process_statement(const std::string& str)
89508958
if (setValues.PerTableStats)
89518959
perTableStats->getStats(DB, true);
89528960

8961+
IsqlWireStats wireStats(DB);
8962+
if (setValues.WireStats)
8963+
wireStats.get(true);
8964+
89538965
// Prepare the dynamic query stored in string.
89548966
// But put this on the DDL transaction to get maximum visibility of
89558967
// metadata.
@@ -9137,6 +9149,9 @@ static processing_state process_statement(const std::string& str)
91379149
if (setValues.PerTableStats)
91389150
perTableStats->getStats(DB, false);
91399151

9152+
if (setValues.WireStats)
9153+
wireStats.print(false);
9154+
91409155
return ret;
91419156
}
91429157

@@ -9156,6 +9171,9 @@ static processing_state process_statement(const std::string& str)
91569171
if (setValues.PerTableStats)
91579172
perTableStats->getStats(DB, false);
91589173

9174+
if (setValues.WireStats)
9175+
wireStats.print(false);
9176+
91599177
return ret;
91609178
}
91619179

@@ -9203,6 +9221,9 @@ static processing_state process_statement(const std::string& str)
92039221
if (setValues.PerTableStats)
92049222
perTableStats->getStats(DB, false);
92059223

9224+
if (setValues.WireStats)
9225+
wireStats.print(false);
9226+
92069227
return ret;
92079228
}
92089229

@@ -9398,6 +9419,9 @@ static processing_state process_statement(const std::string& str)
93989419
if (setValues.PerTableStats)
93999420
perTableStats->getStats(DB, false);
94009421

9422+
if (setValues.WireStats)
9423+
wireStats.print(false);
9424+
94019425
if (pad)
94029426
ISQL_FREE(pad);
94039427
if (line)
@@ -9895,3 +9919,112 @@ unsigned PerTableStats::loadRelNames(Firebird::IAttachment* att)
98959919

98969920
return maxLen;
98979921
}
9922+
9923+
/// class IsqlWireStats
9924+
9925+
bool IsqlWireStats::get(bool initial)
9926+
{
9927+
if (!m_att)
9928+
return false;
9929+
9930+
const UCHAR info[] = {
9931+
fb_info_wire_snd_packets, fb_info_wire_rcv_packets,
9932+
fb_info_wire_out_packets, fb_info_wire_in_packets,
9933+
fb_info_wire_snd_bytes, fb_info_wire_rcv_bytes,
9934+
fb_info_wire_out_bytes, fb_info_wire_in_bytes,
9935+
fb_info_wire_roundtrips,
9936+
isc_info_end
9937+
};
9938+
9939+
UCHAR buffer[128];
9940+
9941+
m_att->getInfo(fbStatus, sizeof(info), info, sizeof(buffer), buffer);
9942+
9943+
if (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS)
9944+
return false;
9945+
9946+
Firebird::ClumpletReader p(Firebird::ClumpletReader::InfoResponse, buffer, sizeof(buffer));
9947+
for (; !p.isEof(); p.moveNext())
9948+
{
9949+
FB_UINT64* pField = nullptr;
9950+
switch (p.getClumpTag())
9951+
{
9952+
case fb_info_wire_snd_packets:
9953+
pField = &m_snd_packets;
9954+
break;
9955+
case fb_info_wire_rcv_packets:
9956+
pField = &m_rcv_packets;
9957+
break;
9958+
case fb_info_wire_out_packets:
9959+
pField = &m_out_packets;
9960+
break;
9961+
case fb_info_wire_in_packets:
9962+
pField = &m_in_packets;
9963+
break;
9964+
case fb_info_wire_snd_bytes:
9965+
pField = &m_snd_bytes;
9966+
break;
9967+
case fb_info_wire_rcv_bytes:
9968+
pField = &m_rcv_bytes;
9969+
break;
9970+
case fb_info_wire_out_bytes:
9971+
pField = &m_out_bytes;
9972+
break;
9973+
case fb_info_wire_in_bytes:
9974+
pField = &m_in_bytes;
9975+
break;
9976+
case fb_info_wire_roundtrips:
9977+
pField = &m_roundtrips;
9978+
break;
9979+
case isc_info_end:
9980+
break;
9981+
case isc_info_error:
9982+
// don't return false here, as we not put error into status
9983+
return true;
9984+
/* uncomment to show error (isc_infunk) instead
9985+
{
9986+
ISC_STATUS errs[3] = { isc_arg_gds, 0, isc_arg_end };
9987+
auto b = p.getBytes();
9988+
errs[1] = isc_portable_integer(b + 1, p.getClumpLength() - 1);
9989+
fbStatus->setErrors(errs);
9990+
return false;
9991+
}*/
9992+
9993+
default:
9994+
fb_assert(false);
9995+
break;
9996+
}
9997+
9998+
if (pField)
9999+
{
10000+
const FB_UINT64 val = p.getBigInt();
10001+
*pField = initial ? val : val - *pField;
10002+
}
10003+
}
10004+
10005+
return true;
10006+
}
10007+
10008+
bool IsqlWireStats::print(bool initial)
10009+
{
10010+
if (!get(initial))
10011+
{
10012+
ISQL_errmsg(fbStatus);
10013+
return false;
10014+
}
10015+
10016+
IUTILS_printf2(Diag, "Wire logical statistics:%s", NEWLINE);
10017+
IUTILS_printf2(Diag, " send packets = %8" SQUADFORMAT "%s", m_out_packets, NEWLINE);
10018+
IUTILS_printf2(Diag, " recv packets = %8" SQUADFORMAT "%s", m_in_packets, NEWLINE);
10019+
IUTILS_printf2(Diag, " send bytes = %8" SQUADFORMAT "%s", m_out_bytes, NEWLINE);
10020+
IUTILS_printf2(Diag, " recv bytes = %8" SQUADFORMAT "%s", m_in_bytes, NEWLINE);
10021+
10022+
IUTILS_printf2(Diag, "Wire physical statistics:%s", NEWLINE);
10023+
IUTILS_printf2(Diag, " send packets = %8" SQUADFORMAT "%s", m_snd_packets, NEWLINE);
10024+
IUTILS_printf2(Diag, " recv packets = %8" SQUADFORMAT "%s", m_rcv_packets, NEWLINE);
10025+
IUTILS_printf2(Diag, " send bytes = %8" SQUADFORMAT "%s", m_snd_bytes, NEWLINE);
10026+
IUTILS_printf2(Diag, " recv bytes = %8" SQUADFORMAT "%s", m_rcv_bytes, NEWLINE);
10027+
IUTILS_printf2(Diag, " roundtrips = %8" SQUADFORMAT "%s", m_roundtrips, NEWLINE);
10028+
10029+
return true;
10030+
}

0 commit comments

Comments
 (0)