如何可靠地测量进程使用的网络带宽

问题描述 投票:0回答:5

我开发了一个应用程序,我想测量它在一些典型测试用例中消耗了多少网络带宽。

我发现了一些应用程序,如 nethog 等,但我不确定它的报告有多准确!

我想要某种方法来非常准确地测量结果,就像将结果写入会议报告一样。

如果有人指导我如何做,我愿意为此编写定制的解决方案!

我想要一些可以运行监控程序和目标应用程序来获取网络使用统计信息 - 发送/接收的累积字节数的东西。 ..最大使用量和平均使用量 等等

linux performance networking bandwidth
5个回答
4
投票

应用程序可以隔离在单机上吗?
系统上还需要运行其他东西吗?

如果系统可以以这种方式专用,请定期抓取

/proc/net/netstat
中的最后一行,并减去
InOctets
OutOctets
的相应值。

此系统 Fedora 15 在正常运行 23 天后显示:

TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed EmbryonicRsts PruneCalled RcvPruned OfoPruned OutOfWindowIcmps LockDroppedIcmps ArpFilter TW TWRecycled TWKilled PAWSPassive PAWSActive PAWSEstab DelayedACKs DelayedACKLocked DelayedACKLost ListenOverflows ListenDrops TCPPrequeued TCPDirectCopyFromBacklog TCPDirectCopyFromPrequeue TCPPrequeueDropped TCPHPHits TCPHPHitsToUser TCPPureAcks TCPHPAcks TCPRenoRecovery TCPSackRecovery TCPSACKReneging TCPFACKReorder TCPSACKReorder TCPRenoReorder TCPTSReorder TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo TCPLoss TCPLostRetransmit TCPRenoFailures TCPSackFailures TCPLossFailures TCPFastRetrans TCPForwardRetrans TCPSlowStartRetrans TCPTimeouts TCPRenoRecoveryFail TCPSackRecoveryFail TCPSchedulerFailed TCPRcvCollapsed TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv TCPAbortOnSyn TCPAbortOnData TCPAbortOnClose TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger TCPAbortFailed TCPMemoryPressures TCPSACKDiscard TCPDSACKIgnoredOld TCPDSACKIgnoredNoUndo TCPSpuriousRTOs TCPMD6NotFound TCPMD5Unexpected TCPSackShifted TCPSackMerged TCPSackShiftFallback TCPBacklogDrop TCPMinTTLDrop TCPDeferAcceptDrop IPReversePathFilter TCPTimeWaitOverflow TCPReqQFullDoCookies TCPReqQFullDrop
TcpExt: 0 0 0 0 0 0 0 0 10 0 67116 0 0 0 0 8 117271 53 18860 0 0 102295 23352211 87967244 0 16861098 118195 893786 881659 0 29 10 0 0 0 9 10 16 12 2321 21 0 1 156 39 940 13 921 8015 0 1 2 0 18461 22 941 0 0 2974 15422 0 709 0 0 0 1 8 119 3 0 0 0 0 25231 0 0 0 4 0 0 0
IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts OutBcastPkts InOctets OutOctets InMcastOctets OutMcastOctets InBcastOctets OutBcastOctets
IpExt: 0 0 25308 48 725 1 24434248973 4218365129 2181277 13241 365505 65

当然,这种格式在这里并不友好,但对于脚本语言来说相当好处理。你可以看到信息的深度和多样性!最后一行显示该系统已读取 24,434,248,973 字节并写入 4,218,365,129。 (这是抓取大型网站的第九天。)


0
投票

再仔细查看一下,我发现 procfs 包含似乎是 每个进程 的网络 i/o 统计信息。

[wally@lenovotower ~]$ cat /proc/32089/net/dev
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
    lo:  622834    6102    0    0    0     0          0         0   622834    6102    0    0    0     0       0          0
  eth0: 3290609241 20752766    0    0    0     0          0         0 161708339 16831446    0    0    0     0       0          0
virbr0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0

如果这是一个长时间运行的过程,那么这可以用于计算使用的带宽。

--- 编辑--- 尽管有路径,正如其他人指出的那样,这些对于所有进程都是相同的,因此显然不是每个进程的网络 i/o 统计信息。


0
投票

获取每个任务网络 io 统计信息的唯一方法是使用某种 taskstats 接口(基于 netlink)。不幸的是,它考虑了你能想象到的一切,但不包括网络信息。我已经为套接字写入/读取上的会计字节和任务统计上的两个条目(用于 tx/rx)做了一个小补丁,以从我的系统中获取此类信息。

包括:

Signed-off-by: Rafael David Tinoco <[email protected]>
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h
index 341dddb..b0c5990 100644
--- a/include/linux/taskstats.h
+++ b/include/linux/taskstats.h
@@ -163,6 +163,10 @@ struct taskstats {
    /* Delay waiting for memory reclaim */
    __u64   freepages_count;
    __u64   freepages_delay_total;
+
+   /* Per-task network I/O accounting */
+   __u64   read_net_bytes;         /* bytes of socket read I/O */
+   __u64   write_net_bytes;        /* bytes of socket write I/O */
 };

和源代码:

Signed-off-by: Rafael David Tinoco <[email protected]>
diff --git a/include/linux/task_io_accounting.h b/include/linux/task_io_accounting.h
index bdf855c..bd45b92 100644
--- a/include/linux/task_io_accounting.h
+++ b/include/linux/task_io_accounting.h
@@ -41,5 +41,12 @@ struct task_io_accounting {
     * information loss in doing that.
     */
    u64 cancelled_write_bytes;
+
+   /* The number of bytes which this task has read from a socket */
+   u64 read_net_bytes;
+
+   /* The number of bytes which this task has written to a socket */
+   u64 write_net_bytes;
+
 #endif /* CONFIG_TASK_IO_ACCOUNTING */
 };
diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h
index 4d090f9..ee8416f 100644
--- a/include/linux/task_io_accounting_ops.h
+++ b/include/linux/task_io_accounting_ops.h
@@ -12,6 +12,11 @@ static inline void task_io_account_read(size_t bytes)
    current->ioac.read_bytes += bytes;
 }

+static inline void task_io_account_read_net(size_t bytes)
+{
+   current->ioac.read_net_bytes += bytes;
+}
+
 /*
  * We approximate number of blocks, because we account bytes only.
  * A 'block' is 512 bytes
@@ -26,6 +31,11 @@ static inline void task_io_account_write(size_t bytes)
    current->ioac.write_bytes += bytes;
 }

+static inline void task_io_account_write_net(size_t bytes)
+{
+   current->ioac.write_net_bytes += bytes;
+}
+
 /*
  * We approximate number of blocks, because we account bytes only.
  * A 'block' is 512 bytes
@@ -59,6 +69,10 @@ static inline void task_io_account_read(size_t bytes)
 {
 }

+static inline void task_io_account_read_net(size_t bytes)
+{
+}
+
 static inline unsigned long task_io_get_inblock(const struct task_struct *p)
 {
    return 0;
@@ -68,6 +82,10 @@ static inline void task_io_account_write(size_t bytes)
 {
 }

+static inline void task_io_account_write_net(size_t bytes)
+{
+}
+
 static inline unsigned long task_io_get_oublock(const struct task_struct *p)
 {
    return 0;
diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h
index 341dddb..b0c5990 100644
--- a/include/linux/taskstats.h
+++ b/include/linux/taskstats.h
@@ -163,6 +163,10 @@ struct taskstats {
    /* Delay waiting for memory reclaim */
    __u64   freepages_count;
    __u64   freepages_delay_total;
+
+   /* Per-task network I/O accounting */
+   __u64   read_net_bytes;         /* bytes of socket read I/O */
+   __u64   write_net_bytes;        /* bytes of socket write I/O */
 };


diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index 00d59d0..b279e69 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -104,10 +104,14 @@ void xacct_add_tsk(struct taskstats *stats, struct task_struct *p)
    stats->read_bytes       = p->ioac.read_bytes;
    stats->write_bytes      = p->ioac.write_bytes;
    stats->cancelled_write_bytes = p->ioac.cancelled_write_bytes;
+   stats->read_net_bytes   = p->ioac.read_net_bytes;
+   stats->write_net_bytes  = p->ioac.write_net_bytes;
 #else
    stats->read_bytes       = 0;
    stats->write_bytes      = 0;
    stats->cancelled_write_bytes = 0;
+   stats->read_net_bytes   = 0;
+   stats->write_net_bytes  = 0;
 #endif
 }
 #undef KB
diff --git a/net/socket.c b/net/socket.c
index 769c386..dd7dbb6 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -87,6 +87,7 @@
 #include <linux/wireless.h>
 #include <linux/nsproxy.h>
 #include <linux/magic.h>
+#include <linux/task_io_accounting_ops.h>

 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -538,6 +539,7 @@ EXPORT_SYMBOL(sock_tx_timestamp);
 static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
                             struct msghdr *msg, size_t size)
 {
+   int ret;
    struct sock_iocb *si = kiocb_to_siocb(iocb);
    int err;

@@ -550,7 +552,12 @@ static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock,
    if (err)
            return err;

-   return sock->ops->sendmsg(iocb, sock, msg, size);
+   ret = sock->ops->sendmsg(iocb, sock, msg, size);
+
+   if (ret > 0)
+           task_io_account_write_net(ret);
+
+   return ret;
 }

 int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
@@ -666,6 +673,7 @@ EXPORT_SYMBOL_GPL(sock_recv_ts_and_drops);
 static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
                                   struct msghdr *msg, size_t size, int flags)
 {
+   int ret = 0;
    struct sock_iocb *si = kiocb_to_siocb(iocb);

    si->sock = sock;
@@ -674,7 +682,12 @@ static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
    si->size = size;
    si->flags = flags;

-   return sock->ops->recvmsg(iocb, sock, msg, size, flags);
+   ret = sock->ops->recvmsg(iocb, sock, msg, size, flags);
+
+   if (ret > 0)
+           task_io_account_read_net(ret);
+
+   return ret;
 }

 static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,

0
投票

Vnstat
是检查互联网带宽使用情况的简单工具,

这是安装它的命令

sudo apt-get install vnstat

要运行 vnstat,您需要运行以下命令。

vnstat

这里(检查监控网络带宽使用情况)还有一些用于检查每日、每周、每月和前 10 天网络带宽使用情况的更多选项。

希望对大家有帮助。


-1
投票

Cat /proc/net/dev 这是查看带宽使用情况的方法之一

gaddenna@gaddenna-Vostro-3546:~$ cat /proc/net/dev 
Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
 wlan1: 9420966650 7703510    0    1    0     0          0         0 673178457 4296602    0    0    0     0       0          0
  eth2: 7961371946 6849173    0   10    0     0          0    167030 446826449 3289015    0    0    0     0       0          0
    lo: 48209054   473527     0    0    0     0          0         0 48209054  473527     0    0    0     0       0          0
© www.soinside.com 2019 - 2024. All rights reserved.