2017-05-18 67 views
4

我開發一個應用程序角度和我創建了一個下載頁面這樣的:Angular:併發下載後內存泄漏?

enter image description here

如果我看看Chrome的任務管理器我看到有關我的應用程序的過程中保留約130 MB的記憶。

然後,用戶可以啓動同時下載點擊每一個下載按鈕(總文件大小爲266 MB):

enter image description here

現在,如果我再次檢查任務管理器我看到內存使用情況隨着所有下載完成,其峯值約爲650 MB。 我注意到一個奇怪的事情:所述存儲器的最終用途似乎是總下式:

初始存儲器使用+ 2 *總文件大小=最終內存使用

130 MB + 2 * 266 MB = 130 MB + 532 MB = 662 MB =〜650 MB。

如果我嘗試使用Chrome垃圾回收器,它會切斷約30 MB,但我仍然擁有620 MB作爲內存使用情況的應用程序。 那麼,我該如何解決這個問題呢?你能看到我的代碼有什麼問題嗎? (我曾嘗試對組件的ngOnDestroy使用unsubscribe,但它沒有工作)

這是當我在一個文件的下載按鈕,點擊(從下載頁面)被調用的函數:

getFile(file: any): void { 
    this.fileDownloadService.downloadFile(file).subscribe(
     (fileinfo: SispFile) => { 
      file.downloading = true; 
     }, 
     (err: any) => { 
      file.downloading = false; 
      console.log('errore', err); 
     }, 
     () => { 
      file.downloading = false; 
      console.log('completated'); 
     }); 
} 

這裏是在FileDownloadServicedownloadFile功能,通過getFile叫:

downloadFile(file: SispFile): Observable<any> { 
    let conf: any = {}; 
    conf.totalChunks = Math.max(Math.ceil(file.size/this.chunkSizeDownload), 1); 
    conf.mime = file.extension; 
    conf.currentChunk = 0; 
    conf.byteDownloaded = 0; 
    conf.chunkSizeDownload = this.chunkSizeDownload; 
    conf.chunkBlobs = []; 
    conf.finalBlob = null; 

    file.progress = 0; 

    return new Observable(observer => { 
     observer.next(file); 
     this.addChunk(file, observer, conf); 
    }) 
} 

addChunk(file: SispFile, observer: any, conf: any) { 
    if (conf.currentChunk == conf.totalChunks) { 
     observer.complete(); 
     conf.finalBlob = new Blob(conf.chunkBlobs, {type: conf.mime}); 

     let fileURL = URL.createObjectURL(conf.finalBlob); 
     let a = document.createElement("a"); 
     a.href = fileURL; 
     a.download = file.name; 
     document.body.appendChild(a); 
     a.click(); 
     window.URL.revokeObjectURL(fileURL); 
    } else { 
     this.docService.downloadFile(file, conf.chunkSizeDownload, conf.byteDownloaded) 
      .then(response => { 
       let typedArray = this.createBlob(response['_body'], conf.mime); 
       conf.chunkBlobs[conf.currentChunk] = typedArray; 
       conf.currentChunk++; 
       conf.byteDownloaded = conf.currentChunk * conf.chunkSizeDownload; 
       if (conf.Downloaded + this.chunkSizeDownload > file.size) { 
        conf.chunkSizeDownload = file.size - conf.Downloaded + 1; 
       } 

       let progress = Math.round((conf.currentChunk * 100)/conf.totalChunks); 
       file.progress = progress; 
       observer.next(file); 
       this.addChunk(file, observer, conf); 
      }) 
      .catch((error: ErrorMessage) => { 
       observer.error(error); 
       console.log('Errore server: ' + error); 
      }); 
    } 
} 

這裏是最終調用後端端點的DocService

downloadFile(file: SispFile, length: number, offset: number) { 
    let url = Util.format(this.downloadFileUrl, {id: file.id}); 
    let body: any = { "downloadMode": "PAYLOAD", "fileId": file.id, "length": length, "offset": offset }; 
    return this.http.post(url, body) 
     .toPromise() 
     .then(response => { 
      return response; 
     }) 
     .catch(this.handleError); 
} 

回答

1

我發現,角有這個Testability類。它的定義如下:

Testability服務提供測試鉤子,可以從瀏覽器和像Protractor這樣的服務訪問 。每個自舉的 頁面上的Angular應用程序將具有可測試性的實例。

而且,您可以通過訪問TestabilityRegistry可測性實例的全球註冊的特定元素

正如我們在this issue中看到的,銷燬組件並不會釋放瀏覽器的內存,因爲可測試性API不會釋放它的引用。

所以,也許,通過清理TestabilityRegistry對銷燬可以幫助你擺脫那些總結出來的引用導致你的620MB內存泄漏。

這是我找到的the fix

我希望這有助於解決您的問題,或者至少我希望我能設法爲您提供不同的觀點或新的研究領域!

更新:

從我目前所看到的,爲了清潔TestabilityRegistry

modules/@angular/core/src/testability/testability.ts

destroy(): void { 
    this._applications.clear(); 
    testabilityGetter.onDestroy(); 
} 

這將是銷燬方法。

modules/@angular/core/src/application_ref.ts

this._injector.get(TestabilityRegistry).destroy(); 

我們調用destroy方法。

modules/@angular/platform-b​​rowser/src/browser/testability.ts

onDestroy(): void { 
    delete global.getAngularTestability; 
    delete global.getAllAngularTestabilities; 
    delete global.getAllAngularRootElements; 
    delete global.frameworkStabilizers; 
} 

摧毀當我們確保我們正在刪除的可測性的情況。

看一看this commit它向您展示瞭如何清理TestabilityRegistry。

+0

謝謝你的提示。那麼,我該怎麼辦?我發現修復不會合併到Angular主存儲庫。 – smartmouse

+1

@smartmouse我相信你最初可以分叉它並測試它是否能解決你的問題。也許你可以調整分叉庫,直到它適合你的需要。 – SrAxi

+0

如果我嘗試fork,那麼你知道如何清理'TestabilityRegistry'嗎? – smartmouse