Skip to content

Commit 88febf4

Browse files
committed
New ISQL commands to show wire statistics.
1 parent 21dfb33 commit 88febf4

File tree

4 files changed

+315
-4
lines changed

4 files changed

+315
-4
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/isql/isql.epp

Lines changed: 149 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,126 @@ unsigned PerTableStats::loadRelNames(Firebird::IAttachment* att)
99309954

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

src/isql/isql.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,4 +311,26 @@ struct IsqlVar
311311
TypeMix value;
312312
};
313313

314+
class IsqlWireStats
315+
{
316+
public:
317+
IsqlWireStats(Firebird::IAttachment* att);
318+
319+
bool print(bool initial);
320+
bool get(bool initial);
321+
322+
private:
323+
324+
Firebird::IAttachment* m_att;
325+
FB_UINT64 m_snd_packets;
326+
FB_UINT64 m_rcv_packets;
327+
FB_UINT64 m_out_packets;
328+
FB_UINT64 m_in_packets;
329+
FB_UINT64 m_snd_bytes;
330+
FB_UINT64 m_rcv_bytes;
331+
FB_UINT64 m_out_bytes;
332+
FB_UINT64 m_in_bytes;
333+
FB_UINT64 m_roundtrips;
334+
};
335+
314336
#endif // ISQL_ISQL_H

0 commit comments

Comments
 (0)