今天在做一個小任務(wù),需要調(diào)用阿里云的圖像識別接口,對 62662 張照片進(jìn)行場景識別,并將結(jié)果寫到本地的 csv 文件中。
因為任務(wù)很簡單,沒想很多就開始碼。自從有了 async/await 之后,已經(jīng)很久不寫 callback 了,所以上手就寫成這樣:
本文所有代碼均有簡化,只保留關(guān)鍵過程
async fetchSceneTags(imagePath) { try { const result = await callAliyunAPI(imagePath); return result.errno === 0 ? result.tags : []; } catch(error) { return []; } } async function writeScene(paths) { for (let i = 0, len = paths.length; i < len; i++) { await tags = fetchSceneTags(paths[i]) writeToFile(tags); writeStdout(`${i} / ${len}`); } } function start() { const paths = loadPaths(); writeScene(paths); }
運(yùn)行起來以后沒問題就放著忙別的去了。過了差不多 2 小時回來一看,才跑了 17180 張圖,每分鐘 144 張。這才意識到同步速度太慢了,于是停掉進(jìn)程,將代碼改成下面這樣:
fetchSceneTagsAsync(imagePath, callback) { callAliyunAPI(imagePath) .then(result => { const tags = result.errno === 0 ? result.tags : []; callback(tags); }) .catch(error => callback([])); } function writeSceneAsync(paths) { const callback = tags => { await tags = fetchSceneTagsAsync(paths[i]) writeToFile(tags); } paths.forEach(path => fetchSceneTagsAsync(path, callback)); } function start() { const paths = loadPaths(); writeSceneAsync(paths); }
跑了一下,直接停擺了。嗯,不能一下把請求全發(fā)出去,加一個 Throttle:
fetchSceneTagsAsync(imagePath, callback) { callAliyunAPI(imagePath) .then(result => { const tags = result.errno === 0 ? result.tags : []; callback(tags); }) .catch(error => callback([])); } function throttle(paths, callback) { if(paths.length === 0) return; const sub = paths.splice(0, 10); sub.forEach(path => fetchSceneTagsAsync(path, callback)); setTimeout(() => throttle(paths, callback), 1000) } function writeSceneAsync(paths) { const callback = tags => { await tags = fetchSceneTagsAsync(paths[i]) writeToFile(tags); } throttle(paths, callback) } function start() { const paths = loadPaths(); writeSceneAsync(paths); }
重新啟動服務(wù),觀察了一下,大約每分鐘處理 568 張圖片,速度提升約 4 倍。
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com