FileDownLoader框架在下載稍微大一點的文件時,下載速度不理想遮精,經(jīng)過實踐發(fā)現(xiàn)居夹,出現(xiàn)問題的原因主要體現(xiàn)在兩點:
1、本身的bug本冲。
2准脂、下載策略的問題。
先說第一點:
1眼俊、本身的bug:
bug源自于框架本身的分塊策略:
// 1 connection: [0, 1MB)
private static final long ONE_CONNECTION_UPPER_LIMIT = 1024 * 1024; // 1MB
// 2 connection: [1MB, 5MB)
private static final long TWO_CONNECTION_UPPER_LIMIT = 5 * 1024 * 1024; // 5MB
// 3 connection: [5MB, 50MB)
private static final long THREE_CONNECTION_UPPER_LIMIT = 50 * 1024 * 1024; // 50MB
// 4 connection: [50MB, 100MB)
private static final long FOUR_CONNECTION_UPPER_LIMIT = 100 * 1024 * 1024; // 100MB
@Override
public int determineConnectionCount(int downloadId, String url, String path, long totalLength) {
if (totalLength < ONE_CONNECTION_UPPER_LIMIT) {
return 1;
}
if (totalLength < TWO_CONNECTION_UPPER_LIMIT) {
return 2;
}
if (totalLength < THREE_CONNECTION_UPPER_LIMIT) {
return 3;
}
if (totalLength < FOUR_CONNECTION_UPPER_LIMIT) {
return 4;
}
return 5;
}
默認邏輯是根據(jù)不同的文件大小意狠,創(chuàng)建的下載連接數(shù)也不一樣,文件總量越大疮胖,創(chuàng)建的塊也越多环戈,最大是5闷板。在多個塊的下載時候,框架內(nèi)部可能對下載任務沒有協(xié)調(diào)好院塞,導致會偶現(xiàn)下載任務停住的問題遮晚,這樣就給人一種下載很慢的感覺。
解決方案:
在Application中進行設置拦止,將塊的數(shù)量固定為1,這樣可以解決偶現(xiàn)卡死的問題县遣。
private void initFileDownload() {
FileDownloader.setupOnApplicationOnCreate(this)
.connectionCreator(new FileDownloadUrlConnection
.Creator(new FileDownloadUrlConnection.Configuration()
.connectTimeout(15_000) // set connection timeout.
.readTimeout(15_000) // set read timeout.
))
.connectionCountAdapter((downloadId, url, path, totalLength) -> {
return 1;//下載文件塊數(shù)是1,解決偶現(xiàn)的下載任務停止問題。
})
.commit();
}
作者的初衷可能也為了讓下載速度有一個平衡才做了這樣一個分塊策略汹族。
雖然我們規(guī)避了bug萧求,但強行將塊設置為1的話顶瞒,下載速度肯定是不如多個塊下載的,為了彌補這些損失守问,同時為了讓本身的下載速度有進一步提升坑资,我們做了第二點—下載策略的修改。
2仿便、下載策略的問題攒巍。
所謂的策略,其實就是為了尋求某個平衡。
每一條小的策略肯定都有它的優(yōu)點和缺點枕屉,為什么要這么做都有它的理由,如何定制一個最完美平衡的策略西潘,需要我們開發(fā)者根據(jù)自己的需求去達成哨颂。
先看本身的下載策略有助于我們對 “為什么這樣下載不是很快,改完就很快”這個問題的理解品姓。
默認策略一:
- process.non-separate=true // 開啟子進程
為什么要這樣:
默認開啟子進程,根據(jù)作者的說法是腹备,為了兼容老版本,保持行為的一致性镀岛。
帶來的問題:
- 子進程和主進程頻繁IPC衅码,對CPU資源有著大量的消耗。
- IPC過程中產(chǎn)生大量的I/O事件,數(shù)據(jù)傳輸成本高
解決這些不必要的通信事件 艾猜,設置為
process.non-separate=false // 直接在主進程中下, 可以有效減少IPC產(chǎn)生的I/O
默認策略二:
BaseDownloadTask#setCallbackProgressIgnored(void)
或者
FileDownloadQueueSet#ignoreEachTaskInternalProgress(void)
//忽略掉下載過程中的大量的進度值回調(diào)淤毛,減少計算進度而帶來CPU的I/O消耗算柳。
在我們的實際場景中,進度值是根據(jù)下載任務數(shù)/總?cè)蝿諗?shù)來計算的蔗蹋,而不是每一個下載小任務的進度回調(diào)囱淋。
所以我們根本用不上進度回調(diào),直接加上這兩條策略之一即可皂吮。
默認策略三:
download.max-network-thread-count=3
//默認開啟3個線程下載税手,進程數(shù)區(qū)間在[1,12]。
下載線程越多當然更快艺挪,我們開啟8-10個兵扬,提升效果明顯口蝠。
默認策略四:
download.min-progress-step = 65536
最小緩沖大小掂器,用于判定是否是時候?qū)⒕彌_區(qū)中進度同步到數(shù)據(jù)庫,以及是否是時候要確保下緩存區(qū)的數(shù)據(jù)都已經(jīng)寫文件灭必。值越小乃摹,更新會越頻繁,下載速度會越慢孵睬,但是應對進程被無法預料的情況殺死時會更加安全
這個改不改影響不大,正常情況不會下載那么長時間秘狞,如果有較大的問題可以酌情設置蹈集。
默認策略五:
ddownload.min-progress-time=2000
最小緩沖時間,用于判定是否是時候?qū)⒕彌_區(qū)中進度同步到數(shù)據(jù)庫减响,以及是否是時候要確保下緩存區(qū)的數(shù)據(jù)都已經(jīng)寫文件。值越小支示,更新會越頻繁鄙才,下載速度會越慢,但是應對進程被無法預料的情況殺死時會更加安全
設置為5000秒据途,意外殺死的情況較少叙甸,并且較小的進度損失可以接受裆蒸。
在assets文件夾底下創(chuàng)建一個filedownloader.properties文件糖驴,將上述配置引入即可佛致。