dpvs學(xué)習(xí)筆記: 17 壓測性能及優(yōu)化

測試環(huán)境

DPVS: Inspur NF5270M3, E5-2630 2.60GHz 24 cores, memory 96G
Real Server: 6 臺(tái)核數(shù)不同的機(jī)器,148 個(gè) redis-server
Bench Client: 8 臺(tái)核數(shù)不同的機(jī)器,24000 個(gè)連接 ping
官方推薦用 f-stack nginx 壓測,還要讓 real server 跑 dpdk 太麻煩。使用 redis ping 模擬小包,平均 74 bytes, 使用 set 指定 1000 bytes value 來模擬大包。

測試配置及腳本

啟動(dòng) redis-server 實(shí)例,一定要 taskset 綁核

taskset -c 8 ./redis-server ./redis6380.conf
taskset -c 9 ./redis-server ./redis6381.conf
taskset -c 10 ./redis-server ./redis6382.conf
......

測試機(jī)啟動(dòng) redis-benchmark pipeline 壓測 ping

#!/bin/sh
cpus=`lscpu | grep '^CPU(s)' | awk '{print $2}'`
for i in `seq 8 $cpus`
do
    nohup taskset -c $i ./redis-benchmark -h 10.20.23.241 -p 6379 -c 100 -n 100000000 -t ping -P 10 -l&
done

統(tǒng)計(jì)InPkts OutPkts

ipvsadm -ln --stats 
ipvsadm --zero
dpip link show dpdk0 -s

dpvs配置: two-arm, full-nat, 8 lcores,nic intel 82599ES

性能問題排查

模擬大包時(shí),two-arm 雙 10G 網(wǎng)卡很快打滿,符合預(yù)期。關(guān)鍵轉(zhuǎn)發(fā)能力要看小包,也就是 pps (packets per second),發(fā)現(xiàn)只有 250w/pps, 遠(yuǎn)低于官方數(shù)據(jù)最理想的 1500w

打開 dpvs debug 模式,可以看到增加了 -g ,并且優(yōu)化級(jí)別是 0

# cat src/Makefile | grep -i debug
DEBUG := 1      # enable for debug
ifeq ($(DEBUG),)
    CFLAGS += -g -O0 -D DEBUG

重新壓測,并使用 perf 抓取性能數(shù)據(jù)

perf record -g -p `pidof dpvs` #約 30 秒后 ctrl+c
perf report -i ./perf.data
perf top1

perf top2

由于 dpvs 是多核程序,所以看 lcore-slave-3 即可,一步步觀察,INET_HOOK占了 9.85% cpu, 里面的 dp_vs_in 占了 4.21%,rte_rwlock_read_lock/unlock 相關(guān)的占了合計(jì) 5.1%. 再深入 dp_vs_in 函數(shù),發(fā)現(xiàn) xmit_inbound xmit_outbound tcp_conn_lookup 占用較高,具體到底層函數(shù)都是 tcp header checksum 計(jì)算相關(guān)函數(shù),比較符合預(yù)期。那值得懷疑的就是 rte_rwlock_read_lock/unlock,貼上源碼:

int INET_HOOK(int af, unsigned int hook, struct rte_mbuf *mbuf,
              struct netif_port *in, struct netif_port *out,
              int (*okfn)(struct rte_mbuf *mbuf))
{
    struct list_head *hook_list;
    struct inet_hook_ops *ops;
    struct inet_hook_state state;
    int verdict = INET_ACCEPT;

    state.hook = hook;
    hook_list = af_inet_hooks(af, hook);

    rte_rwlock_read_lock(af_inet_hook_lock(af));

    ops = list_entry(hook_list, struct inet_hook_ops, list);

    if (!list_empty(hook_list)) {
        verdict = INET_ACCEPT;
        list_for_each_entry_continue(ops, hook_list, list) {
repeat:
            verdict = ops->hook(ops->priv, mbuf, &state);
            if (verdict != INET_ACCEPT) {
                if (verdict == INET_REPEAT)
                    goto repeat;
                break;
            }
        }
    }

    rte_rwlock_read_unlock(af_inet_hook_lock(af));

    if (verdict == INET_ACCEPT || verdict == INET_STOP) {
        return okfn(mbuf);
    } else if (verdict == INET_DROP) {
        rte_pktmbuf_free(mbuf);
        return EDPVS_DROP;
    } else { /* INET_STOLEN */
        return EDPVS_OK;
    }
}
static inline rte_rwlock_t *af_inet_hook_lock(int af)
{
    assert(af == AF_INET || af == AF_INET6);

    if (af == AF_INET)
        return &inet_hook_lock;
    else
        return &inet6_hook_lock;
}

鎖的內(nèi)容是 af_inet_hook_lock(af), 再看實(shí)現(xiàn),居然鎖的是一個(gè)全局 lock !!! dpdk 程序最忌多個(gè)核之間共享數(shù)據(jù),特別是鎖競爭。查看 git 提交紀(jì)錄,由 cc5369c1a3bd4fa7bd838c62fc1cb8797db61b4e ipv6/ipvs: ipvs core support ipv6 引入的問題。仔細(xì)閱讀代碼,這個(gè)鎖只在初始化期有用,運(yùn)行期完全可以忽略,何況還是個(gè)讀鎖,也就是 INET_HOOK 根本用不到,果斷注釋掉重新壓測。

perf top3

關(guān)掉后再次壓測,上面的 perf 圖里,沒有了鎖爭用問題,占 cpu 比例最高的是 dp_vs_in,集中在 tcp header checksum,這部分沒有辦法,本身就是 cpu 消耗型的。符合預(yù)期。

NETIF: Fail to send 1 packets on dpdk1 tx3
NETIF: Fail to send 7 packets on dpdk1 tx2
NETIF: Fail to send 4 packets on dpdk1 tx2
NETIF: Fail to send 2 packets on dpdk1 tx1
NETIF: Fail to send 1 packets on dpdk1 tx1

如果遇到丟包,也就是 imiss 問題,需要調(diào)大 dpvs.conf 隊(duì)列的 descriptor_number 值,默認(rèn)的可能有點(diǎn)小,大并發(fā)時(shí)丟包。

最終壓測數(shù)據(jù)

關(guān)掉 DEBUG 模式,77 bytes 小包打到 700w pps, 兩個(gè)萬兆網(wǎng)卡打到 8.5G,網(wǎng)卡先于 dpvs 達(dá)到瓶頸,性能比較平穩(wěn)沒有抖動(dòng)。以后有機(jī)會(huì)測網(wǎng)卡 bonding 的數(shù)據(jù)。


grafana

鎖的問題和 iqiyi 研發(fā)溝通了一下,他們之前的壓測數(shù)據(jù)是引入 ipv6 之前的,后續(xù)會(huì)再內(nèi)部進(jìn)行壓測優(yōu)化性能。多核編程鎖還是永恒的話題,一個(gè)讀鎖也會(huì)有這么大影響,看來有機(jī)會(huì)得研究下底層鎖的實(shí)現(xiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容