簡體   English   中英

為什么我的解決方案如此緩慢?如何提高查詢的性能?

[英]Why is my solution so slow and how can I improve performance of the query?

目前我能夠優化性能,但它仍然有點慢:/

最新編輯:

我目前的解決方案(最快的atm(但仍然很慢)並保持秩序):

服務器

router.post('/images', function(req, res, next) {
    var image = bucket.file(req.body.image);
    image.download(function(err, contents) {
        if (err) {
            console.log(err);
        } else {
            var resultImage = base64_encode(contents);
            var index = req.body.index;
            var returnObject = {
                image: resultImage,
                index: index
            }
            res.send(returnObject);
        }
    });
});

客戶端查詢

$scope.getDataset = function() {

                fb.orderByChild('id').startAt(_start).limitToFirst(_n).once("value", function(dataSnapshot) {

                    dataSnapshot.forEach(function(childDataSnapshot) {
                        _start = childDataSnapshot.child("id").val() + 1;

                        var post = childDataSnapshot.val();
                        var image = post.image;

                        var imageObject = {
                            image: image,
                            index: position
                        };
                        position++;
                        $.ajax({
                            type: "POST",
                            url: "images",
                            data: imageObject,
                        }).done(function(result) {
                            post.image = result.image;
                            $scope.data[result.index] = post;
                            $scope.$apply();
                            firstElementsLoaded = true; 
                        });
                    })  
                });
            };

客戶端HTML

<div ng-controller="ctrl">
        <div class="allcontent">
            <div id="pageContent" ng-repeat="d in data track by $index"><a href="details/{{d.key}}" target="_blank"><h3 class="text-left">{{d.title}}<a href="../users/{{d.author}}"><span class="authorLegend"><i> by {{d.username}}</i></span></a></h3>
                </a>
                <div class="postImgIndex" ng-show="{{d.upvotes - d.downvotes > -50}}">
                    <a href="details/{{d.key}}" target="_blank"><img class="imgIndex" ng-src="data:image/png;base64,{{d.image}}"></a>
                </div>
                <div class="postScore">{{d.upvotes - d.downvotes}} HP</div>
            </div>
        </div>
    </div>

您的解決方案很慢,因為您從雲存儲中下載映像並在自己的服務器上提供這些映像。 下載和上傳延遲,使用base64編碼數據的開銷約為33%,而且您的服務器在提供圖像時非常緊張,而不是專注於提供您的網站內容。

正如許多評論所指出的那樣,最佳實踐解決方案是使用圖像的公共URL,如下所示:

function getPublicUrl (filename) {
  return "https://storage.googleapis.com/${CLOUD_BUCKET}/${filename}";
}

通過使用公共URL,您可以直接使用Google的全球服務基礎架構雲存儲 服務 並且應用程序不必響應圖像請求,從而為其他請求釋放CPU周期。

如果您不希望機器人使用上述方法抓取您的圖片,Google建議您使用robots.txt文件阻止訪問您的圖片。

  1. 在優化之前,您最好收集一些數據,我將在下面的代碼中顯示一些數據
  2. 看起來像base64_encode(contents)可能花費很多CPU,你的邏輯似乎反復這樣做。 這是猜測,你必須自己找到它的真正瓶頸
  3. 其他建議可能會減少改進,但這將是非常有效的(gzip \\ CDN \\ http2 \\ loadbalance ...)

優化數據收集 - 服務器端,哪個操作花費了太多時間

 router.post('/images', function(req, res, next) { var d = new Date() var image = bucket.file(req.body.image); image.download(function(err, contents) { console.log('download:' + new Date() - d) if (err) { console.log(err); } else { var resultImage = base64_encode(contents); console.log('base64_encode:' + new Date() - d) var index = req.body.index; var returnObject = { image: resultImage, index: index } res.send(returnObject); } }); }); 

優化數據收集 - 客戶端()

chrome調試欄

備用base64_encode(contents)

 $scope.getDataset = function() { fb.orderByChild('id').startAt(_start).limitToFirst(_n).once("value", function(dataSnapshot) { dataSnapshot.forEach(function(childDataSnapshot, index) { _start = childDataSnapshot.child("id").val() + 1; var post = childDataSnapshot.val(); getImageBase64(post.image) .then((image) => { post.image = image; $scope.data[index] = post; $scope.$apply(); firstElementsLoaded = true; }) }) }); function getImageBase64(image1) { //without help of server, this will make your app faster //network reduced //server calculation reduced if (CanIUseBucktAndBase64Here) { return new Promise((reslove, reject) { var image = bucket.file(image1); image.download(function(err, contents) { if (err) { reject(err); } else { //use worker thread might gain better performance var resultImage = base64_encode(contents); resolve(resultImage) } }); }) } //with help of server return $.ajax({ type: "POST", url: "images", data: image1, }) .then(result => result.image) } }; 

每次都避免下載

 //------------load all to local suit for less images---------- // if you have many images and you can use cheaper cache like file cache //--init.js download all images, run only once downloadAll() //--server.js //when image updated, let server know and flush cache server.get('/imageupdated', (req, res) => { downfile(req.params.imgid) res.send('got it') }) //form cache first server.post('/image', (req, res) => { memcache.get(req.body.imgid) .then((content) => { if (!content) return downfile(req.body.imgid) res.send({ content }) return true }) .then((content) => { if (content === true) return res.send({ content }) }) }) server.listen() //--common.js download file and cache to memcache function downfile(imgid) { var base64 = '' return bucket.download(imgid) .then((file) => { base64 = base64(file) return memcache.set(imgid, base64) }) .then(() => { return base64 }) } //downfileBatch async function downfileBatch(skip, limit) { return cloudDrive.getImages(skip, limit) .then((list) => { return Promise.all(list.map()) }) } //down load all images async function downloadAll() { var i = 0, limit = 5 while (true) { var list = await downfileBatch(i, limit) if (list.length < limit) {} else { i += limit } } return true } 

優化代碼的最簡單方法是向服務器端發送單個ajax請求,而不是為每個映像執行ajax請求。

從循環中刪除ajax調用。 循環遍歷集合,收集需要發送到陣列中的服務器的數據,然后通過單個ajax請求發送它。 這會加快速度。

此外,確保修改服務器端POST處理程序以便它可以處理數組,您將從客戶端傳遞。

我不確定如何提高傳送文件的速度,但它們出現故障的問題是因為它們是異步的。 基本上發生的事情是你告訴服務器給你一堆文件然后你等待。 一旦服務器將它們發送給您,您就可以處理它們。 但是你不知道他們進來的順序。 您需要做的是跟蹤他們到達的順序。 這樣做的方法是通過某種方式跟蹤每個帖子的信息。 例如,假設你有

var arr = new Array(10);
for (var i = 0 ; i < arr.length; i++){
  $.ajax({
    url:____,
    type:"GET" (or whatever type you want),
    data: _____,
    context: {index: i}
    success : function(data){
                 arr[this.index] = data
              }
  })
}

這應該正確設置值。 語法可能有點偏,但我相信這是以正確的順序設置它們的正確想法。 重要的部分是設置上下文,它將在成功處理程序中設置“this”等於什么

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM