diff options
| author | Qiuwen Lu <[email protected]> | 2017-09-04 14:00:40 +0800 |
|---|---|---|
| committer | Qiuwen Lu <[email protected]> | 2017-09-04 14:00:40 +0800 |
| commit | 89818554f1460f95469feeeffa3103fa935ef71c (patch) | |
| tree | 26770ff943f5bd6d3c65c02233df9d63f2a2206e | |
| parent | f9da59d59c1455957383733b3d9452435568ea6b (diff) | |
增加应用处理报文字节数统计,增加应用统计工具分组显示统计数据功能。v4.2.16-20170915
- 增加应用处理报文字节数统计,显示应用处理的报文字节数;
- 增加应用统计工具分组显示统计数据功能,支持显示视图、分线程视图、收、发、快速发送视图显示功能。
| -rw-r--r-- | app/src/monit.c | 19 | ||||
| -rw-r--r-- | include/external/marsio.h | 16 | ||||
| -rw-r--r-- | include/internal/vdev_define.h | 3 | ||||
| -rw-r--r-- | infra/include/vnode.h | 8 | ||||
| -rw-r--r-- | infra/src/vnode_mirror.c | 8 | ||||
| -rw-r--r-- | service/src/monit.c | 10 | ||||
| -rw-r--r-- | service/src/vdata.c | 9 | ||||
| -rw-r--r-- | service/src/vloop.c | 11 | ||||
| -rw-r--r-- | tools/monit_stream/monit_stream.py | 103 |
9 files changed, 157 insertions, 30 deletions
diff --git a/app/src/monit.c b/app/src/monit.c index a4dc2f8..46fc515 100644 --- a/app/src/monit.c +++ b/app/src/monit.c @@ -20,19 +20,22 @@ int vdev_instance_stats_get(struct vdev_instance * vdi, struct vdev_stat_info * for (int i = 0; i < vdi->nr_rxstream; i++) { stat_info->rx_on_line[i] = rte_atomic64_read(&st_cons_rx[i].on_line); - stat_info->rx_deliver[i] = rte_atomic64_read(&st_cons_rx[i].recieved); + stat_info->rx_deliver[i] = rte_atomic64_read(&st_cons_rx[i].deliver); stat_info->rx_missed[i] = rte_atomic64_read(&st_cons_rx[i].missed); + stat_info->rx_total_len[i] = rte_atomic64_read(&st_cons_rx[i].total_len); } for (int i = 0; i < vdi->nr_txstream; i++) { stat_info->tx_on_line[i] = rte_atomic64_read(&st_prod_tx[i].on_line); - stat_info->tx_deliver[i] = rte_atomic64_read(&st_prod_tx[i].sent); + stat_info->tx_deliver[i] = rte_atomic64_read(&st_prod_tx[i].deliver); stat_info->tx_missed[i] = rte_atomic64_read(&st_prod_tx[i].missed); + stat_info->tx_total_len[i] = rte_atomic16_read(&st_prod_tx[i].total_len); stat_info->ftx_on_line[i] = rte_atomic64_read(&st_prod_ftx[i].on_line); - stat_info->ftx_deliver[i] = rte_atomic64_read(&st_prod_ftx[i].sent); + stat_info->ftx_deliver[i] = rte_atomic64_read(&st_prod_ftx[i].deliver); stat_info->ftx_missed[i] = rte_atomic64_read(&st_prod_ftx[i].missed); + stat_info->ftx_total_len[i] = rte_atomic64_read(&st_prod_ftx[i].total_len); } return 0; @@ -96,12 +99,17 @@ static cJSON * __create_vdev_stats(struct vdev_instance * vdi) __JOIN_VDEV_VALUE_STATS_ITEM(rx_on_line, nr_rx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(rx_deliver, nr_rx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(rx_missed, nr_rx_stream); + __JOIN_VDEV_VALUE_STATS_ITEM(rx_total_len, nr_rx_stream); + __JOIN_VDEV_VALUE_STATS_ITEM(tx_on_line, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(tx_deliver, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(tx_missed, nr_tx_stream); + __JOIN_VDEV_VALUE_STATS_ITEM(tx_total_len, nr_tx_stream); + __JOIN_VDEV_VALUE_STATS_ITEM(ftx_on_line, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(ftx_deliver, nr_tx_stream); __JOIN_VDEV_VALUE_STATS_ITEM(ftx_missed, nr_tx_stream); + __JOIN_VDEV_VALUE_STATS_ITEM(ftx_total_len, nr_tx_stream); #define __JOIN_VDEV_SPEED_STATS_ITEM(item, streams) do { \ cJSON_AddItemToObject(j_vdev_speed, #item, \ @@ -112,12 +120,17 @@ static cJSON * __create_vdev_stats(struct vdev_instance * vdi) __JOIN_VDEV_SPEED_STATS_ITEM(rx_on_line, nr_rx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(rx_deliver, nr_rx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(rx_missed, nr_rx_stream); + __JOIN_VDEV_SPEED_STATS_ITEM(rx_total_len, nr_rx_stream); + __JOIN_VDEV_SPEED_STATS_ITEM(tx_on_line, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(tx_deliver, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(tx_missed, nr_tx_stream); + __JOIN_VDEV_SPEED_STATS_ITEM(tx_total_len, nr_tx_stream); + __JOIN_VDEV_SPEED_STATS_ITEM(ftx_on_line, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(ftx_deliver, nr_tx_stream); __JOIN_VDEV_SPEED_STATS_ITEM(ftx_missed, nr_tx_stream); + __JOIN_VDEV_SPEED_STATS_ITEM(ftx_total_len, nr_tx_stream); cJSON_AddItemToObject(j_vdev_stats, "accumulative", j_vdev_value); cJSON_AddItemToObject(j_vdev_stats, "speed", j_vdev_speed); diff --git a/include/external/marsio.h b/include/external/marsio.h index bb1fa9e..eddca7e 100644 --- a/include/external/marsio.h +++ b/include/external/marsio.h @@ -19,7 +19,11 @@ typedef enum * 设置该掩码后,数据面线程数选项将被忽略。 */ MARSIO_OPT_THREAD_MASK, - /* 处理SIG信号,缺省值:类型:uint32_t,关闭(0) + /* 线程绑定模式,类型:uint32_t + */ + MARSIO_OPT_THREAD_AFFINITY_MODE, + + /* 处理SIG信号,缺省值:类型:uint32_t,关闭(0) * 启用该选项后,将自动处理SIGINT、SIGTERM信号 */ MARSIO_OPT_EXIT_WHEN_ERR, @@ -75,6 +79,16 @@ enum mr_clone_options MR_BUFF_CLONE_CTRLZONE = 1 << 2, }; +enum mr_thread_affinity_mode +{ + /* 禁用线程亲和性设置 */ + MR_THREAD_AFFINITY_DISABLE = 0, + /* 自动线程亲和性设置 */ + MR_THREAD_AFFINITY_AUTO = 1, + /* 自定义线程亲和性设置 */ + MR_THREAD_AFFINITY_USER = 255 +}; + #ifdef __cplusplus extern "C" { #endif diff --git a/include/internal/vdev_define.h b/include/internal/vdev_define.h index 20e43f1..4bbfafd 100644 --- a/include/internal/vdev_define.h +++ b/include/internal/vdev_define.h @@ -26,16 +26,19 @@ struct vdev_stat_info uint64_t rx_on_line[MR_SID_MAX]; uint64_t rx_deliver[MR_SID_MAX]; uint64_t rx_missed[MR_SID_MAX]; + uint64_t rx_total_len[MR_SID_MAX]; /* TX: from app to service */ uint64_t tx_on_line[MR_SID_MAX]; uint64_t tx_deliver[MR_SID_MAX]; uint64_t tx_missed[MR_SID_MAX]; + uint64_t tx_total_len[MR_SID_MAX]; /* FTX: fast tunnel from app to serivce */ uint64_t ftx_on_line[MR_SID_MAX]; uint64_t ftx_deliver[MR_SID_MAX]; uint64_t ftx_missed[MR_SID_MAX]; + uint64_t ftx_total_len[MR_SID_MAX]; }; /* 虚拟设备信息 */ diff --git a/infra/include/vnode.h b/infra/include/vnode.h index 79f0061..9734117 100644 --- a/infra/include/vnode.h +++ b/infra/include/vnode.h @@ -40,18 +40,18 @@ int vnode_##_type##_delete_cons(struct vnode_cons * cons); struct vnode_cons_stat { rte_atomic64_t on_line; - rte_atomic64_t recieved; + rte_atomic64_t deliver; rte_atomic64_t missed; - rte_atomic64_t recieved_len; + rte_atomic64_t total_len; } __rte_cache_aligned; struct vnode_prod_stat { rte_atomic64_t on_line; - rte_atomic64_t sent; + rte_atomic64_t deliver; rte_atomic64_t missed; - rte_atomic64_t sent_len; + rte_atomic64_t total_len; /* clone used */ rte_atomic64_t cloned; diff --git a/infra/src/vnode_mirror.c b/infra/src/vnode_mirror.c index 7ce74d2..a1a0deb 100644 --- a/infra/src/vnode_mirror.c +++ b/infra/src/vnode_mirror.c @@ -51,15 +51,15 @@ static inline void dist_tunnel_flush(struct vnode_prod * prod, struct vnode_cons out: // 更新生产者统计计数 VNODE_STAT_UPDATE(prod, prodq, on_line, n_to_send); - VNODE_STAT_UPDATE(prod, prodq, sent, n_send); + VNODE_STAT_UPDATE(prod, prodq, deliver, n_send); VNODE_STAT_UPDATE(prod, prodq, missed, n_to_send - n_send); - VNODE_STAT_UPDATE(prod, prodq, sent_len, n_send_len); + VNODE_STAT_UPDATE(prod, prodq, total_len, n_send_len); // 更新消费者统计计数 VNODE_STAT_UPDATE(cons, consq, on_line, n_to_send); - VNODE_STAT_UPDATE(cons, consq, recieved, n_send); + VNODE_STAT_UPDATE(cons, consq, deliver, n_send); VNODE_STAT_UPDATE(cons, consq, missed, n_to_send - n_send); - VNODE_STAT_UPDATE(cons, consq, recieved_len, n_send_len); + VNODE_STAT_UPDATE(cons, consq, total_len, n_send_len); // 清空缓冲区 desc->sz_en_buffer_used = 0; diff --git a/service/src/monit.c b/service/src/monit.c index c606666..620191c 100644 --- a/service/src/monit.c +++ b/service/src/monit.c @@ -62,12 +62,17 @@ static cJSON * __create_vdev_stats(struct vdev * vdev, unsigned int nr_serv_thre __JOIN_VDEV_VALUE_STATS_ITEM(rx_on_line); __JOIN_VDEV_VALUE_STATS_ITEM(rx_deliver); __JOIN_VDEV_VALUE_STATS_ITEM(rx_missed); + __JOIN_VDEV_VALUE_STATS_ITEM(rx_total_len); + __JOIN_VDEV_VALUE_STATS_ITEM(tx_on_line); __JOIN_VDEV_VALUE_STATS_ITEM(tx_deliver); __JOIN_VDEV_VALUE_STATS_ITEM(tx_missed); + __JOIN_VDEV_VALUE_STATS_ITEM(tx_total_len); + __JOIN_VDEV_VALUE_STATS_ITEM(ftx_on_line); __JOIN_VDEV_VALUE_STATS_ITEM(ftx_deliver); __JOIN_VDEV_VALUE_STATS_ITEM(ftx_missed); + __JOIN_VDEV_VALUE_STATS_ITEM(ftx_total_len); #define __JOIN_VDEV_SPEED_STATS_ITEM(item) do { \ cJSON_AddItemToObject(j_vdev_speed, #item, \ @@ -78,12 +83,17 @@ static cJSON * __create_vdev_stats(struct vdev * vdev, unsigned int nr_serv_thre __JOIN_VDEV_SPEED_STATS_ITEM(rx_on_line); __JOIN_VDEV_SPEED_STATS_ITEM(rx_deliver); __JOIN_VDEV_SPEED_STATS_ITEM(rx_missed); + __JOIN_VDEV_SPEED_STATS_ITEM(rx_total_len); + __JOIN_VDEV_SPEED_STATS_ITEM(tx_on_line); __JOIN_VDEV_SPEED_STATS_ITEM(tx_deliver); __JOIN_VDEV_SPEED_STATS_ITEM(tx_missed); + __JOIN_VDEV_SPEED_STATS_ITEM(tx_total_len); + __JOIN_VDEV_SPEED_STATS_ITEM(ftx_on_line); __JOIN_VDEV_SPEED_STATS_ITEM(ftx_deliver); __JOIN_VDEV_SPEED_STATS_ITEM(ftx_missed); + __JOIN_VDEV_SPEED_STATS_ITEM(ftx_total_len); cJSON_AddItemToObject(j_vdev_stats, "accumulative", j_vdev_value); cJSON_AddItemToObject(j_vdev_stats, "speed", j_vdev_speed); diff --git a/service/src/vdata.c b/service/src/vdata.c index 45c6726..bbe4dc6 100644 --- a/service/src/vdata.c +++ b/service/src/vdata.c @@ -102,19 +102,22 @@ static int vdev_data_stats_get(struct _vdev * _vdev, struct vdev_stat_info * sta for (int i = 0; i < _vdev->nr_rxstream; i++) { stat_info->rx_on_line[i] = rte_atomic64_read(&st_prod_rx[i].on_line); - stat_info->rx_deliver[i] = rte_atomic64_read(&st_prod_rx[i].sent); + stat_info->rx_deliver[i] = rte_atomic64_read(&st_prod_rx[i].deliver); stat_info->rx_missed[i] = rte_atomic64_read(&st_prod_rx[i].missed); + stat_info->rx_total_len[i] = rte_atomic64_read(&st_prod_rx[i].on_line); } for (int i = 0; i < _vdev->nr_txstream; i++) { stat_info->tx_on_line[i] = rte_atomic64_read(&st_cons_tx[i].on_line); - stat_info->tx_deliver[i] = rte_atomic64_read(&st_cons_tx[i].recieved); + stat_info->tx_deliver[i] = rte_atomic64_read(&st_cons_tx[i].deliver); stat_info->tx_missed[i] = rte_atomic64_read(&st_cons_tx[i].missed); + stat_info->tx_total_len[i] = rte_atomic64_read(&st_cons_tx[i].total_len); stat_info->ftx_on_line[i] = rte_atomic64_read(&st_cons_ftx[i].on_line); - stat_info->ftx_deliver[i] = rte_atomic64_read(&st_cons_ftx[i].recieved); + stat_info->ftx_deliver[i] = rte_atomic64_read(&st_cons_ftx[i].deliver); stat_info->ftx_missed[i] = rte_atomic64_read(&st_cons_ftx[i].missed); + stat_info->ftx_total_len[i] = rte_atomic64_read(&st_cons_ftx[i].total_len); } return 0; diff --git a/service/src/vloop.c b/service/src/vloop.c index b64f0be..50d46a0 100644 --- a/service/src/vloop.c +++ b/service/src/vloop.c @@ -40,19 +40,22 @@ static int vdev_loop_stats_get(struct _vdev * _vdev, struct vdev_stat_info * sta for (int i = 0; i < _vdev->nr_rxstream; i++) { stat_info->rx_on_line[i] = rte_atomic64_read(&st_prod_rx[i].on_line); - stat_info->rx_deliver[i] = rte_atomic64_read(&st_prod_rx[i].sent); + stat_info->rx_deliver[i] = rte_atomic64_read(&st_prod_rx[i].deliver); stat_info->rx_missed[i] = rte_atomic64_read(&st_prod_rx[i].missed); + stat_info->rx_total_len[i] = rte_atomic64_read(&st_prod_rx[i].total_len); } for (int i = 0; i < _vdev->nr_txstream; i++) { stat_info->tx_on_line[i] = rte_atomic64_read(&st_cons_tx[i].on_line); - stat_info->tx_deliver[i] = rte_atomic64_read(&st_cons_tx[i].recieved); + stat_info->tx_deliver[i] = rte_atomic64_read(&st_cons_tx[i].deliver); stat_info->tx_missed[i] = rte_atomic64_read(&st_cons_tx[i].missed); + stat_info->tx_total_len[i] = rte_atomic64_read(&st_cons_tx[i].total_len); stat_info->ftx_on_line[i] = rte_atomic64_read(&st_cons_ftx[i].on_line); - stat_info->ftx_deliver[i] = rte_atomic64_read(&st_cons_ftx[i].recieved); - stat_info->ftx_missed[i] = rte_atomic64_read(&st_cons_ftx[i].missed); + stat_info->ftx_deliver[i] = rte_atomic64_read(&st_cons_ftx[i].deliver); + stat_info->ftx_missed[i] = rte_atomic64_read(&st_cons_ftx[i].missed); + stat_info->ftx_total_len[i] = rte_atomic64_read(&st_cons_ftx[i].total_len); } return 0; diff --git a/tools/monit_stream/monit_stream.py b/tools/monit_stream/monit_stream.py index 1dad5de..6c3fea0 100644 --- a/tools/monit_stream/monit_stream.py +++ b/tools/monit_stream/monit_stream.py @@ -16,18 +16,22 @@ KBPS = (1 * 1000) G_JSON_PATH = '/var/run/mrzcpd/mrmonit.daemon' G_APP_JSON_PATH = '/var/run/mrzcpd/mrmonit.app.%s' -TITLE_VECTOR_RX = ['RxOnline', 'RxDeliver', 'RxMissed'] -TITLE_VECTOR_TX = ['TxOnline', 'TxDeliver', 'TxMissed', 'FTXOnline', 'FTXDeliver', 'FTXMissed'] +TITLE_VECTOR_RX = ['RxOnline', 'RxDeliver', 'RxMissed', 'RxBits'] +TITLE_VECTOR_TX = ['TxOnline', 'TxDeliver', 'TxMissed', 'TxBits'] +TITLE_VECTOR_FTX = ['FTXOnline', 'FTXDeliver', 'FTXMissed', 'FTXBits'] TITLE_MAP = { 'RxOnline' : 'rx_on_line', 'RxDeliver' : 'rx_deliver', 'RxMissed' : 'rx_missed', + 'RxBits' : 'rx_total_len', 'TxOnline' : 'tx_on_line', 'TxDeliver' : 'tx_deliver', 'TxMissed' : 'tx_missed', + 'TxBits' : 'tx_total_len', 'FTXOnline' : 'ftx_on_line', 'FTXDeliver' : 'ftx_deliver', - 'FTXMissed' : 'ftx_missed' + 'FTXMissed' : 'ftx_missed', + 'FTXBits' : 'ftx_total_len' } def locate_vector_by_symbol(vector, symbol): @@ -68,30 +72,85 @@ def vec_trans_to_human_readable(vec): return r_vector -def dump_human_table(json_fp, appsym, devsym, is_human_number = 0, speed = 0): +def dump_summary_table(json_fp, appsym, devsym, title_vector_rx, title_vector_tx, + is_human_number = 0, speed = 0): + + def __dump_one_device(json_fp, devsym, title_vector_rx, title_vector_tx, speed): + + __rd_function = vdev_value_read if speed == 0 else vdev_speed_read + + ValueListSum = [0] * len(title_vector_rx + title_vector_tx) + nr_rxstream, nr_txstream = vdev_streams_read(json_fp, devsym) + + for stream_id in range(max(nr_rxstream, nr_txstream)): + ValueList = [] + + for item in title_vector_rx: + value = __rd_function(json_fp, devsym, TITLE_MAP[item])[stream_id] \ + if stream_id < nr_rxstream else 0 + ValueList.append(value) + + for item in title_vector_tx: + value = __rd_function(json_fp, devsym, TITLE_MAP[item])[stream_id] \ + if stream_id < nr_txstream else 0 + ValueList.append(value) + + for i,v in enumerate(ValueList): + ValueListSum[i] += v + + return ValueListSum + + print('\nTime: %s, App: %s' % (time.strftime('%c'), appsym)) + table_phydev = prettytable.PrettyTable([' '] + title_vector_rx + title_vector_tx, + vertical_char=' ',horizontal_char = '-', junction_char=' ') + + for item in[' '] + title_vector_rx + title_vector_tx: + table_phydev.align[item] = 'r' + + ValueListTotal = [0] * len(title_vector_rx + title_vector_tx) + + for dev in devsym: + ValueListSum = __dump_one_device(json_fp, dev, title_vector_rx, title_vector_tx, speed) + for i,v in enumerate(ValueListSum): + ValueListTotal[i] += v + + if is_human_number: + table_phydev.add_row([dev] + vec_trans_to_human_readable(ValueListSum)) + else: + table_phydev.add_row([dev] + ValueListSum) + + if is_human_number: + table_phydev.add_row(['Total'] + vec_trans_to_human_readable(ValueListTotal)) + else: + table_phydev.add_row(['Total'] + ValueListTotal) + + print(table_phydev) + +def dump_human_table(json_fp, appsym, devsym, title_vector_rx, title_vector_tx, + is_human_number = 0, speed = 0): print('\nTime: %s, App: %s, Device: %s ' % (time.strftime('%c'), appsym, devsym)) - table_phydev = prettytable.PrettyTable([' '] + TITLE_VECTOR_RX + TITLE_VECTOR_TX, + table_phydev = prettytable.PrettyTable([' '] + title_vector_rx + title_vector_tx, vertical_char=' ',horizontal_char = '-', junction_char=' ') __rd_function = vdev_value_read if speed == 0 else vdev_speed_read - for item in[' '] + TITLE_VECTOR_RX + TITLE_VECTOR_TX: + for item in[' '] + title_vector_rx + title_vector_tx: table_phydev.align[item] = 'r' - ValueListSum = [0] * len(TITLE_VECTOR_RX + TITLE_VECTOR_TX) + ValueListSum = [0] * len(title_vector_rx + title_vector_tx) nr_rxstream, nr_txstream = vdev_streams_read(json_fp, devsym) for stream_id in range(max(nr_rxstream, nr_txstream)): ValueList = [] - for item in TITLE_VECTOR_RX: + for item in title_vector_rx: value = __rd_function(json_fp, devsym, TITLE_MAP[item])[stream_id] \ if stream_id < nr_rxstream else 0 ValueList.append(value) - for item in TITLE_VECTOR_TX: + for item in title_vector_tx: value = __rd_function(json_fp, devsym, TITLE_MAP[item])[stream_id] \ if stream_id < nr_txstream else 0 ValueList.append(value) @@ -131,8 +190,12 @@ def setup_argv_parser(): action = 'store_true', default = 0) parser.add_argument('-i', '--interface', help = 'the name of network interface', action = 'append') + parser.add_argument('-m', '--metrics', help = 'group of metrics', choices=['rx','tx','ftx'], + default = ['rx','tx']) parser.add_argument('--clear-screen', help = 'clear screen at start of loop', action='store_true', default = 0) + parser.add_argument('--per-stream', help = 'print per thread/stream value', + action='store_true', default = 0) parser.add_argument('app', metavar='APP', help = 'the name of slave application', nargs ='+') return parser.parse_args() @@ -172,6 +235,19 @@ def main(): print("%s, program %s is not running." % (str(err), appsym)) sys.exit(1) + title_vector_rx = [] + title_vector_tx = [] + + if 'rx' in r_option.metrics: + title_vector_rx.extend(TITLE_VECTOR_RX) + if 'tx' in r_option.metrics: + title_vector_tx.extend(TITLE_VECTOR_TX) + if 'ftx' in r_option.metrics: + title_vector_tx.extend(TITLE_VECTOR_FTX) + + print title_vector_rx + print title_vector_tx + try: while True: @@ -183,8 +259,13 @@ def main(): check_vdev_options(json_fp, r_option) user_interface = r_option.interface if r_option.interface != None else list_all_vdev(json_fp) - for devsym in user_interface: - dump_human_table(json_fp, appsym, devsym, r_option.human_readable, r_option.speed) + if not r_option.per_stream: + dump_summary_table(json_fp, appsym, user_interface, title_vector_rx, title_vector_tx, + r_option.human_readable, r_option.speed) + else: + for devsym in user_interface: + dump_human_table(json_fp, appsym, devsym, title_vector_rx, title_vector_tx, + r_option.human_readable, r_option.speed) if not r_option.loop: break |
