Почему мое решение так медленно и как я могу улучшить производительность запроса?

В настоящее время мне удалось немного улучшить производительность, но она все еще несколько медленная:/

ПОСЛЕДНИЕ ИЗМЕНЕНИЯ:

Мое текущее решение (самый быстрый 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>

Ответ 1

Ваше решение идет медленно, потому что вы загружаете изображения из облачного хранилища и обслуживаете их на своем собственном сервере. Вы получаете задержку при загрузке и загрузке, накладные расходы на 33%, используя базовые 64-кодированные данные, плюс ваш сервер напряжен в доставке изображений вместо того, чтобы сосредоточиться на доставке вашего контента на веб-сайте.

Как отмечалось многими в комментариях, лучшим решением является использование общедоступного URL-адреса для таких изображений:

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

Используя общедоступный URL-адрес, вы непосредственно используете Cloud Storage , используя глобальную инфраструктуру обслуживания Google.. И приложение не должно отвечать на запросы на изображения, освобождая циклы CPU для других запросов.

Если вы не хотите, чтобы боты сканировали ваши изображения с использованием вышеуказанного метода, Google рекомендует использовать файл robots.txt для блокировки доступа к ваши изображения.

Ответ 2

  • Перед оптимизацией вам лучше собрать некоторые данные, я покажу их в следующем фрагменте
  • Похоже, base64_encode(contents) может стоить много CPU, ваша логика, кажется, многократно делает это. Это угадывание, истинное узкое место, которое вам нужно найти самим собой.
  • Другие предложения могут сделать меньше улучшения, но это будет много общего эффекта (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);
    }
  });
});

Ответ 3

Самый простой способ оптимизации вашего кода - отправить один аякс-запрос серверной стороне, а не выполнять запрос ajax для каждого из изображений.

Удалите вызовы ajax из цикла. Прокрутите коллекцию, соберите данные, которые необходимо отправить на сервер в массиве, а затем отправьте их с помощью одного запроса ajax. Это ускорит процесс.

Кроме того, убедитесь, что вы модифицируете обработчик POST на стороне сервера, чтобы он мог обрабатывать массив, вы будете проходить с клиентской стороны.

Ответ 4

Я не уверен, как увеличить скорость доставки файлов, но проблема их не в том, что они асинхронны. В основном, что происходит, вы говорите серверу, чтобы получить кучу файлов, а затем вы ждете. как только сервер отправит их вам, вы справитесь с ними. но вы не знаете, в каком порядке они приходят. Что вам нужно сделать, так это следить за порядком прибытия. Способ сделать это - иметь некоторый способ отслеживания информации о каждом сообщении. Например, скажем, у вас есть

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" равно в обработчике успеха