Skip to content

Commit 247cacc

Browse files
authored
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 ae88c78 commit 247cacc

File tree

12 files changed

+512
-19
lines changed

12 files changed

+512
-19
lines changed

doc/README.isql_enhancements.txt

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,3 +324,122 @@ RDB$RELATIONS | 59| | | |
324324

325325
-- turn per-table stats off, using shortened name
326326
SQL> SET PER_TAB OFF;
327+
328+
329+
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.

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
@@ -4496,6 +4496,15 @@ IProfilerStatsImpl = class(IProfilerStats)
44964496
fb_info_username = byte(147);
44974497
fb_info_sqlrole = byte(148);
44984498
fb_info_parallel_workers = byte(149);
4499+
fb_info_wire_out_packets = byte(150);
4500+
fb_info_wire_in_packets = byte(151);
4501+
fb_info_wire_out_bytes = byte(152);
4502+
fb_info_wire_in_bytes = byte(153);
4503+
fb_info_wire_snd_packets = byte(154);
4504+
fb_info_wire_rcv_packets = byte(155);
4505+
fb_info_wire_snd_bytes = byte(156);
4506+
fb_info_wire_rcv_bytes = byte(157);
4507+
fb_info_wire_roundtrips = byte(158);
44994508
fb_info_crypt_encrypted = $01;
45004509
fb_info_crypt_process = $02;
45014510
fb_feature_multi_statements = byte(1);

src/isql/isql.epp

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ public:
587587
KeepTranParams = true;
588588
TranParams->assign(DEFAULT_DML_TRANS_SQL);
589589
PerTableStats = false;
590+
WireStats = false;
590591
}
591592

592593
ColList global_Cols;
@@ -611,6 +612,7 @@ public:
611612
SCHAR ISQL_charset[MAXCHARSET_SIZE];
612613
bool KeepTranParams;
613614
bool PerTableStats;
615+
bool WireStats;
614616
};
615617

616618
static SetValues setValues;
@@ -5381,7 +5383,7 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
53815383
exec_path_display,
53825384
sql, warning, sqlCont, heading, bail,
53835385
bulk_insert, maxrows, stmtTimeout,
5384-
keepTranParams, perTableStats,
5386+
keepTranParams, perTableStats, wireStats,
53855387
wrong
53865388
};
53875389
SetOptions(const optionsMap* inmap, size_t insize, int wrongval)
@@ -5422,7 +5424,8 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
54225424
{SetOptions::stmtTimeout, "LOCAL_TIMEOUT", 0},
54235425
{SetOptions::sqlCont, "DECFLOAT", 0},
54245426
{SetOptions::keepTranParams, "KEEP_TRAN_PARAMS", 9},
5425-
{SetOptions::perTableStats, "PER_TABLE_STATS", 7}
5427+
{SetOptions::perTableStats, "PER_TABLE_STATS", 7},
5428+
{SetOptions::wireStats, "WIRE_STATS", 4}
54265429
};
54275430

54285431
// Display current set options
@@ -5662,6 +5665,10 @@ static processing_state frontend_set(const char* cmd, const char* const* parms,
56625665
ret = do_set_command(parms[2], &setValues.PerTableStats);
56635666
break;
56645667

5668+
case SetOptions::wireStats:
5669+
ret = do_set_command(parms[2], &setValues.WireStats);
5670+
break;
5671+
56655672
default:
56665673
//{
56675674
// TEXT msg_string[MSG_LENGTH];
@@ -6452,6 +6459,7 @@ static processing_state print_sets()
64526459

64536460
print_set("Print statistics:", setValues.Stats);
64546461
print_set("Print per-table stats:", setValues.PerTableStats);
6462+
print_set("Print wire stats:", setValues.WireStats);
64556463
print_set("Echo commands:", setValues.Echo);
64566464
print_set("List format:", setValues.List);
64576465
print_set("Show Row Count:", setValues.Docount);
@@ -9004,6 +9012,10 @@ static processing_state process_statement(const TEXT* str2)
90049012
if (setValues.PerTableStats)
90059013
perTableStats->getStats(DB, true);
90069014

9015+
IsqlWireStats wireStats(DB);
9016+
if (setValues.WireStats)
9017+
wireStats.get(true);
9018+
90079019
// Prepare the dynamic query stored in string.
90089020
// But put this on the DDL transaction to get maximum visibility of
90099021
// metadata.
@@ -9172,6 +9184,9 @@ static processing_state process_statement(const TEXT* str2)
91729184
if (setValues.PerTableStats)
91739185
perTableStats->getStats(DB, false);
91749186

9187+
if (setValues.WireStats)
9188+
wireStats.print(false);
9189+
91759190
return ret;
91769191
}
91779192

@@ -9191,6 +9206,9 @@ static processing_state process_statement(const TEXT* str2)
91919206
if (setValues.PerTableStats)
91929207
perTableStats->getStats(DB, false);
91939208

9209+
if (setValues.WireStats)
9210+
wireStats.print(false);
9211+
91949212
return ret;
91959213
}
91969214

@@ -9238,6 +9256,9 @@ static processing_state process_statement(const TEXT* str2)
92389256
if (setValues.PerTableStats)
92399257
perTableStats->getStats(DB, false);
92409258

9259+
if (setValues.WireStats)
9260+
wireStats.print(false);
9261+
92419262
return ret;
92429263
}
92439264

@@ -9433,6 +9454,9 @@ static processing_state process_statement(const TEXT* str2)
94339454
if (setValues.PerTableStats)
94349455
perTableStats->getStats(DB, false);
94359456

9457+
if (setValues.WireStats)
9458+
wireStats.print(false);
9459+
94369460
if (pad)
94379461
ISQL_FREE(pad);
94389462
if (line)
@@ -9930,3 +9954,112 @@ unsigned PerTableStats::loadRelNames(Firebird::IAttachment* att)
99309954

99319955
return maxLen;
99329956
}
9957+
9958+
/// class IsqlWireStats
9959+
9960+
bool IsqlWireStats::get(bool initial)
9961+
{
9962+
if (!m_att)
9963+
return false;
9964+
9965+
const UCHAR info[] = {
9966+
fb_info_wire_snd_packets, fb_info_wire_rcv_packets,
9967+
fb_info_wire_out_packets, fb_info_wire_in_packets,
9968+
fb_info_wire_snd_bytes, fb_info_wire_rcv_bytes,
9969+
fb_info_wire_out_bytes, fb_info_wire_in_bytes,
9970+
fb_info_wire_roundtrips,
9971+
isc_info_end
9972+
};
9973+
9974+
UCHAR buffer[128];
9975+
9976+
m_att->getInfo(fbStatus, sizeof(info), info, sizeof(buffer), buffer);
9977+
9978+
if (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS)
9979+
return false;
9980+
9981+
Firebird::ClumpletReader p(Firebird::ClumpletReader::InfoResponse, buffer, sizeof(buffer));
9982+
for (; !p.isEof(); p.moveNext())
9983+
{
9984+
FB_UINT64* pField = nullptr;
9985+
switch (p.getClumpTag())
9986+
{
9987+
case fb_info_wire_snd_packets:
9988+
pField = &m_snd_packets;
9989+
break;
9990+
case fb_info_wire_rcv_packets:
9991+
pField = &m_rcv_packets;
9992+
break;
9993+
case fb_info_wire_out_packets:
9994+
pField = &m_out_packets;
9995+
break;
9996+
case fb_info_wire_in_packets:
9997+
pField = &m_in_packets;
9998+
break;
9999+
case fb_info_wire_snd_bytes:
10000+
pField = &m_snd_bytes;
10001+
break;
10002+
case fb_info_wire_rcv_bytes:
10003+
pField = &m_rcv_bytes;
10004+
break;
10005+
case fb_info_wire_out_bytes:
10006+
pField = &m_out_bytes;
10007+
break;
10008+
case fb_info_wire_in_bytes:
10009+
pField = &m_in_bytes;
10010+
break;
10011+
case fb_info_wire_roundtrips:
10012+
pField = &m_roundtrips;
10013+
break;
10014+
case isc_info_end:
10015+
break;
10016+
case isc_info_error:
10017+
// don't return false here, as we not put error into status
10018+
return true;
10019+
/* uncomment to show error (isc_infunk) instead
10020+
{
10021+
ISC_STATUS errs[3] = { isc_arg_gds, 0, isc_arg_end };
10022+
auto b = p.getBytes();
10023+
errs[1] = isc_portable_integer(b + 1, p.getClumpLength() - 1);
10024+
fbStatus->setErrors(errs);
10025+
return false;
10026+
}*/
10027+
10028+
default:
10029+
fb_assert(false);
10030+
break;
10031+
}
10032+
10033+
if (pField)
10034+
{
10035+
const FB_UINT64 val = p.getBigInt();
10036+
*pField = initial ? val : val - *pField;
10037+
}
10038+
}
10039+
10040+
return true;
10041+
}
10042+
10043+
bool IsqlWireStats::print(bool initial)
10044+
{
10045+
if (!get(initial))
10046+
{
10047+
ISQL_errmsg(fbStatus);
10048+
return false;
10049+
}
10050+
10051+
IUTILS_printf2(Diag, "Wire logical statistics:%s", NEWLINE);
10052+
IUTILS_printf2(Diag, " send packets = %8" SQUADFORMAT "%s", m_out_packets, NEWLINE);
10053+
IUTILS_printf2(Diag, " recv packets = %8" SQUADFORMAT "%s", m_in_packets, NEWLINE);
10054+
IUTILS_printf2(Diag, " send bytes = %8" SQUADFORMAT "%s", m_out_bytes, NEWLINE);
10055+
IUTILS_printf2(Diag, " recv bytes = %8" SQUADFORMAT "%s", m_in_bytes, NEWLINE);
10056+
10057+
IUTILS_printf2(Diag, "Wire physical statistics:%s", NEWLINE);
10058+
IUTILS_printf2(Diag, " send packets = %8" SQUADFORMAT "%s", m_snd_packets, NEWLINE);
10059+
IUTILS_printf2(Diag, " recv packets = %8" SQUADFORMAT "%s", m_rcv_packets, NEWLINE);
10060+
IUTILS_printf2(Diag, " send bytes = %8" SQUADFORMAT "%s", m_snd_bytes, NEWLINE);
10061+
IUTILS_printf2(Diag, " recv bytes = %8" SQUADFORMAT "%s", m_rcv_bytes, NEWLINE);
10062+
IUTILS_printf2(Diag, " roundtrips = %8" SQUADFORMAT "%s", m_roundtrips, NEWLINE);
10063+
10064+
return true;
10065+
}

0 commit comments

Comments
 (0)