使用FileDownloader提升下載速度辦法

FileDownLoader框架在下載稍微大一點(diǎn)的文件時(shí),下載速度不理想,經(jīng)過實(shí)踐發(fā)現(xiàn),出現(xiàn)問題的原因主要體現(xiàn)在兩點(diǎn):
1、本身的bug。
2、下載策略的問題。

先說第一點(diǎn):

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;
}

默認(rèn)邏輯是根據(jù)不同的文件大小,創(chuàng)建的下載連接數(shù)也不一樣,文件總量越大,創(chuàng)建的塊也越多,最大是5。在多個(gè)塊的下載時(shí)候,框架內(nèi)部可能對(duì)下載任務(wù)沒有協(xié)調(diào)好,導(dǎo)致會(huì)偶現(xiàn)下載任務(wù)停住的問題,這樣就給人一種下載很慢的感覺。

解決方案:
在Application中進(jìn)行設(shè)置,將塊的數(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)的下載任務(wù)停止問題。
                })
                .commit();
    }

作者的初衷可能也為了讓下載速度有一個(gè)平衡才做了這樣一個(gè)分塊策略。
雖然我們規(guī)避了bug,但強(qiáng)行將塊設(shè)置為1的話,下載速度肯定是不如多個(gè)塊下載的,為了彌補(bǔ)這些損失,同時(shí)為了讓本身的下載速度有進(jìn)一步提升,我們做了第二點(diǎn)—下載策略的修改。

2、下載策略的問題。

所謂的策略,其實(shí)就是為了尋求某個(gè)平衡。
每一條小的策略肯定都有它的優(yōu)點(diǎn)和缺點(diǎn),為什么要這么做都有它的理由,如何定制一個(gè)最完美平衡的策略,需要我們開發(fā)者根據(jù)自己的需求去達(dá)成。

先看本身的下載策略有助于我們對(duì) “為什么這樣下載不是很快,改完就很快”這個(gè)問題的理解。
默認(rèn)策略一:

  1. process.non-separate=true // 開啟子進(jìn)程

為什么要這樣:
默認(rèn)開啟子進(jìn)程,根據(jù)作者的說法是,為了兼容老版本,保持行為的一致性。

帶來的問題:

  • 子進(jìn)程和主進(jìn)程頻繁IPC,對(duì)CPU資源有著大量的消耗。
  • IPC過程中產(chǎn)生大量的I/O事件,數(shù)據(jù)傳輸成本高

解決這些不必要的通信事件 ,設(shè)置為

process.non-separate=false // 直接在主進(jìn)程中下, 可以有效減少IPC產(chǎn)生的I/O

默認(rèn)策略二:

BaseDownloadTask#setCallbackProgressIgnored(void)
或者
FileDownloadQueueSet#ignoreEachTaskInternalProgress(void)
//忽略掉下載過程中的大量的進(jìn)度值回調(diào),減少計(jì)算進(jìn)度而帶來CPU的I/O消耗。

在我們的實(shí)際場景中,進(jìn)度值是根據(jù)下載任務(wù)數(shù)/總?cè)蝿?wù)數(shù)來計(jì)算的,而不是每一個(gè)下載小任務(wù)的進(jìn)度回調(diào)。
所以我們根本用不上進(jìn)度回調(diào),直接加上這兩條策略之一即可。

默認(rèn)策略三:

download.max-network-thread-count=3
//默認(rèn)開啟3個(gè)線程下載,進(jìn)程數(shù)區(qū)間在[1,12]。

下載線程越多當(dāng)然更快,我們開啟8-10個(gè),提升效果明顯。

默認(rèn)策略四:

download.min-progress-step = 65536
最小緩沖大小,用于判定是否是時(shí)候?qū)⒕彌_區(qū)中進(jìn)度同步到數(shù)據(jù)庫,以及是否是時(shí)候要確保下緩存區(qū)的數(shù)據(jù)都已經(jīng)寫文件。值越小,更新會(huì)越頻繁,下載速度會(huì)越慢,但是應(yīng)對(duì)進(jìn)程被無法預(yù)料的情況殺死時(shí)會(huì)更加安全

這個(gè)改不改影響不大,正常情況不會(huì)下載那么長時(shí)間,如果有較大的問題可以酌情設(shè)置。

默認(rèn)策略五:

ddownload.min-progress-time=2000
最小緩沖時(shí)間,用于判定是否是時(shí)候?qū)⒕彌_區(qū)中進(jìn)度同步到數(shù)據(jù)庫,以及是否是時(shí)候要確保下緩存區(qū)的數(shù)據(jù)都已經(jīng)寫文件。值越小,更新會(huì)越頻繁,下載速度會(huì)越慢,但是應(yīng)對(duì)進(jìn)程被無法預(yù)料的情況殺死時(shí)會(huì)更加安全

設(shè)置為5000秒,意外殺死的情況較少,并且較小的進(jìn)度損失可以接受。

在assets文件夾底下創(chuàng)建一個(gè)filedownloader.properties文件,將上述配置引入即可。

最后編輯于
?著作權(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ù)。

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