Почему мое решение так медленно и как я могу улучшить производительность запроса?
В настоящее время мне удалось немного улучшить производительность, но она все еще несколько медленная:/
ПОСЛЕДНИЕ ИЗМЕНЕНИЯ:
Мое текущее решение (самый быстрый 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" равно в обработчике успеха