磁碟IO的問題。
大檔寫入跟小檔寫入的問題。
你自已用磁碟讀寫測速軟體跑看看就知道,4K的寫入是很慢的,4K以下更慢。
註: TCP/IP三階段握手:
Client(CLOSED)-->SYN; Client(SYN_SENT)-->Server(LISTEN)
Server(LISTEN)-->SYN/ACK; Server(SYN_RECEIVED)->Client(SYN_SENT)
Client(SYN_SENT)-->ACK; Client(ESTABLISHED)-->Server(ESTABLISHED)
剛好有空寫了一個腳本, 用dd建立了一個100k的空檔, 和1000個0.1k的空檔, 然後用scp傳檔測試, 中間沒有任何sleep:
#!/bin/bash
rm *.txt
dd if=/dev/zero of=100k.txt bs=1024 count=0 seek=100 1>/dev/null
for i in `seq 1 1000`; do
dd if=/dev/zero of=0.1k-$i.txt bs=102 count=0 seek=1 1>/dev/null
done
START=$(date +%s.%N)
scp 100k.txt adminuser@192.168.0.88:~/testfile/
END=$(date +%s.%N)
DIFF1=$(echo "$END - $START" | bc | sed "s/^./0./" )
START=$(date +%s.%N)
for i in `seq 1 1000`; do
scp 0.1k-$i.txt adminuser@192.168.0.88:~/testfile/
done
END=$(date +%s.%N)
DIFF2=$(echo "$END - $START" | bc)
DIFF3=$(echo "$DIFF2 - $DIFF1" | bc)
RATIO=$(echo "$DIFF3*100/$DIFF1"|bc)
echo "To scp a single file of 100kb in size takes $DIFF1 and to scp 1000 files of 0.1kb each in size takes $DIFF2"
echo "The time difference ratio is $RATIO%"
結果是:
To scp a single file of 100kb in size takes 0.268555700 and to scp 1000 files of 0.1kb each in size takes 263.874764439
The time difference ratio is 98156%
那是981倍!.
再做一次測試, 這次增加一個測試: 1000個1k的檔案:
#!/bin/bash
rm *.txt
dd if=/dev/zero of=100k.txt bs=1024 count=0 seek=100 1>/dev/null
for i in `seq 1 1000`; do
dd if=/dev/zero of=0.1k-$i.txt bs=102 count=0 seek=1 1>/dev/null
dd if=/dev/zero of=1k-$i.txt bs=1024 count=0 seek=1 1>/dev/null
done
START=$(date +%s.%N)
scp 100k.txt adminuser@192.168.0.88:~/testfile/
END=$(date +%s.%N)
DIFF1=$(echo "$END - $START" | bc | sed "s/^./0./" )
START=$(date +%s.%N)
for i in `seq 1 1000`; do
scp 0.1k-$i.txt adminuser@192.168.0.88:~/testfile/
done
END=$(date +%s.%N)
DIFF2=$(echo "$END - $START" | bc)
DIFF3=$(echo "$DIFF2 - $DIFF1" | bc)
RATIO1=$(echo "$DIFF3*100/$DIFF1"|bc)
START=$(date +%s.%N)
for i in `seq 1 1000`; do
scp 1k-$i.txt adminuser@192.168.0.88:~/testfile/
done
END=$(date +%s.%N)
DIFF4=$(echo "$END - $START" | bc)
DIFF5=$(echo "$DIFF4 - $DIFF1" | bc)
RATIO2=$(echo "$DIFF5*100/$DIFF1"|bc)
DIFF6=$(echo "$DIFF4 - $DIFF2" | bc)
RATIO3=$(echo "$DIFF6*100/$DIFF2"|bc)
echo "1x100k=$DIFF1"
echo "1000x0.1k=$DIFF2; RATIO OVER 1X100K: $RATIO1"
echo "1000x1k=$DIFF4; RATIO OVER 1x100k: $RATIO2; RATIO OVER 1000x0.1k: $RATIO3"
結果是:
1x100k=0.266028082
1000x0.1k=261.604391897; RATIO OVER 1X100K: 98237
1000x1k=262.151353571; RATIO OVER 1x100k: 98442; RATIO OVER 1000x0.1k: 0
傳1000個0.1k或傳1000個1k的時間相近, 差不多是傳一個100k的980+倍, 這表示可以不計TCP/IP的表頭封包的影響, 也可忽略硬體層的影響.
TCP/IP三階段握手非常昂貴, 所以Googlg提出QUIC的協定:
https://en.wikipedia.org/wiki/QUIC
這是一個過牆梯, 爬UDP的牆.
再加幾個測試:
1000個5K是1000倍
1000個10K是968倍
也就是說, 1000個10K, 和1000個1K的總傳輸時間相近,其平均時間和傳送單一100K的檔案一樣, 所以, 花在TCP/IP協定的時間是固定的且遠超過在LAN中傳送檔案的時間, 共要花1000次的起滅TCP/IP連線, 單單是在LAN, 這個起滅時間就要260ms了, 何況是複雜的跨海峽連線.
(如果有時間抓封包檢視可能會更真實.)
100K的資料傳輸時間由幾秒變成要數十分鐘,
感覺是自行開發的程式所設計的傳輸方式才發生的問題
如果是UDP看是否因為發包頻率不當導致掉包,
那麼就要檢查程式若有掉包的重傳機制是否妥當
使用TCP的話要看每個迴圈是否有安插delay的設計,
因為跑一次迴圈只會被delay一次
而跑1000次迴圈就會被delay 1000次
如果迴圈每送一次是安排休息1秒,
那麼1000次就是16.67分鐘以上了...
我猜是類似後面這種原因最有可能!