В настоящее время я сталкиваюсь с кошмаром. Моя БД имеет только 400 записей почти и проблема в том, что мой PHP-код, который генерирует Image Sliders, поэтому код принимает как 60 секунд почти казнить только 400 записей что слишком много времени, никто не может ждать столько времени.
Я действительно волнуюсь по этому поводу, так как я не уверен, что можно сделать, чтобы сделать это быстрее, но, насколько мне известно, использование цикла foreach вместо цикла for может ускорить процесс, но я хочу знать, можете ли вы, люди, порадовать, предоставьте мне решения.
Это частичный шаблон внутри сайта Symfony, который отображает ползунок изображения и извлекает каждое изображение из БД. Но я не беспокоюсь о SQL-запросах, так как это занимает около От 3 до 4 секунд самое большее, чтобы выполнить все запросы, чтобы получить эти изображения слайдера, но этот код, который генерирует слайдер, занимает чертовски много времени почти 60+ секунд в большинстве случаев это слишком много времени для ожидания.
Если вы, люди, можете предоставить мне оптимизированный код для лучшей производительности, я был бы благодарен за это.
Вот мой код как (_SearchResults.php) :
<?php if (count($locations) > 0): ?>
<?php foreach ($locations as $location): ?>
<?php if ($location->PhotoFiles->count()): ?>
<li class="item" data-location-id="<?php echo $location->id ?>">
<div class="searchItemSlider">
<?php $limit = ($location->PhotoFiles->count() >= 10 ? 10 : $location->PhotoFiles->count()); ?>
<?php for ($i = 1; $i < ($limit + 1); $i++): ?>
<?php $photo = $location->findPhotoIndex($i); ?>
<?php //if (1): ?>
<?php if ($photo && $thumb = $photo->getThumbnailByType(ThumbnailTable::THUMB_520_392)): ?>
<div class="searchItem">
<figure>
<?php if (file_exists($thumb->getFullFilesystemPath())): ?>
<?php //if (1 == 2): ?>
<div class="thumb-img">
<img class="lazyOwl" src="<?php echo $thumb->getFullWebPath() ?>" />
</div>
<?php else: ?>
<div class="thumb-img">
<img class="lazyOwl" src="/images/newfrontend/categories/no_venue.jpg" />
</div>
<?php endif; ?>
<figcaption>
<a href="<?= url_for("@venue_details?id=" . $location->id) ?>" title="<?php echo $location->venue_name; ?>"><?php echo $location->venue_name; ?></a>
<br />
</figcaption>
<?php $districtName = (strlen($location->venue_area)) ? $location->venue_area : $location->getGeoLocationDistrictName();
if (strlen($districtName)): ?>
<div class="district_name"><a href="<?= url_for("@venue_details?id=" . $location->id) ?>" title="<?php echo $location->venue_name; ?>"><?php echo $districtName ?></a></div>
<?php endif; ?>
</figure>
<p><?php echo substr(strip_tags(html_entity_decode($location->description)), 0, 100) ?></p>
<span class="eye"><a href="<?= url_for("@venue_details?id=" . $location->id) ?>" title="<?php echo $location->venue_name; ?>"><img src="/images/newfrontend/icons/eye-icon.png"/></a></span>
<div class="links">
<a href="<?php echo url_for('@venue_share?id=' . $location->id) ?>" class="arrow share_links" data-toggle="tooltip" title="Share this venue"> </a>
<?php if (!$sf_user->locationInWishlist($location->id)): ?>
<a href="<?php echo url_for('@wishlist_addtowishlistajaxraw') ?>" data-attr-venue-id="<?php echo $location->id ?>" class="pin add_to_wishlist" data-toggle="tooltip" title="Add to wishlist"> </a>
<?php else: ?>
<a href="javascript:void(0)" class="added-to-wishlist"> </a>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php endfor; ?>
</div>
</li>
<?php else: ?>
<li class="item" data-location-id="<?php echo $location->id ?>">
<div class="searchItemSlider">
<div class="searchItem">
<figure>
<div class="thumb-img">
<img class="lazyOwl" src="/images/newfrontend/categories/no_venue.jpg" />
</div>
<figcaption>
<a href="<?= url_for("@venue_details?id=" . $location->id) ?>" title="<?php echo $location->venue_name; ?>"><?php echo $location->venue_name; ?></a>
<br />
</figcaption>
<?php $districtName = (strlen($location->venue_area)) ? $location->venue_area : $location->getGeoLocationDistrictName();
if (strlen($districtName)):
?>
<div class="district_name"><a href="<?= url_for("@venue_details?id=" . $location->id) ?>" title="<?php echo $location->venue_name; ?>"><?php echo $districtName ?></a></div>
<?php endif; ?>
</figure>
<p><?php echo substr(strip_tags(html_entity_decode($location->description)), 0, 100) ?></p>
<span class="eye"><a href="<?= url_for("@venue_details?id=" . $location->id) ?>" title="<?php echo $location->venue_name; ?>"><img src="/images/newfrontend/icons/eye-icon.png"/></a></span>
<div class="links">
<a href="<?php echo url_for('@venue_share?id=' . $location->id) ?>" class="arrow share_links" title="Share this venue"> </a>
<?php if (!$sf_user->locationInWishlist($location->id)): ?>
<a href="<?php echo url_for('@wishlist_addtowishlistajaxraw') ?>" data-attr-venue-id="<?php echo $location->id ?>" class="pin add_to_wishlist" data-toggle="tooltip" title="Add to wishlist"> </a>
<?php else: ?>
<a href="javascript:void(0)" class="added-to-wishlist"> </a>
<?php endif; ?>
</div>
</div>
</div>
</li>
<?php endif; ?>
<?php endforeach; ?>
<?php endif; ?>
Обновить :
Место нахождения : /lib/model/doctrine/PhotoFile.class.php
/**
* Returns the first thumbnail of a certain type
* or false if no thumbnail matches
*
* @param const $type The type of thumbnail, from the ThumbnailTable::THUMB_* constants
* @return bool|Thumbnail
*/
public function getThumbnailByType($type) {
foreach ($this->Thumbnails as $t) {
if ($t->thumb_type == $type) {
return $t;
}
}
return false;
}
Место нахождения : /lib/model/doctrine/Location.class.php
/**
* Geocoder: get district name (administrative county)
*
* @return string
*/
public function getDistrictName()
{
return ($this->hasGeocode() ? $this->getGeocode()->district_name : null);
}
public function getGeoLocationDistrictName()
{
$districtName = '';
if($this->getGeocoded()->count() > 0)
{
if($this->getGeocoded()->getFirst()->getGeolocationPostcode()->count() > 0)
{
if($this->getGeocoded()->getFirst()->getGeolocationPostcode()->getFirst()->getGeolocationDistrict()->count() > 0)
{
$districtName = $this->getGeocoded()->getFirst()->getGeolocationPostcode()->getFirst()->getGeolocationDistrict()->getFirst()->getName();
}
}
}
return $districtName;
}
/**
* Gets the geocode data for this location.
* We store it locally so we don't need to keep querying for it.
*
* @return boolean|PcawCodes $pcawCode
*/
public function getGeocode()
{
if ($this->Geocoded->count())
{
return $this->Geocoded->getFirst();
}
if (!strlen($this->address_postcode))
{
// No postcode to geocode
return false;
}
$geocode = new JointGeocoder();
try
{
/* @var $result PcawCodes */
$result = $geocode->geocode("", $this->address_postcode);
// Add the postcode also to the GeolocationPostcode table
if($result) Doctrine::getTable('GeolocationPostcode')->addPostcodeIfMissing($result);
}
catch (Exception $e)
{
// Some problem occurred geocoding, return false
return false;
}
return $result;
}
Хочу заметить, что используемый вами инструмент оценки производительности указывает, что страница выполняет 4540 запросов. Если так, то это, вероятно, причина.
Основываясь на вашем коде, я подозреваю, что это проблема n + 1 — по сути, сделать еще один запрос внутри цикла, выбирая новую модель по отдельности. Большинство ORM имеют механизм, который решает эту проблему с помощью активной загрузки, благодаря чему они забирают все эти строки заранее. Использование быстрой загрузки также облегчает кеширование ответа.
Я не знаком с Доктриной, но согласно https://tideways.io/profiler/blog/5-doctrine-orm-performance-traps-you-should-avoid это поддерживает нетерпеливую загрузку.
Я не буду специально рассказывать вам, как вы можете решить эту проблему, но вместо этого сделаю предложения по повышению производительности.
3 — 4 секунды для выполнения ваших запросов — ДОЛГОЕ время. Оптимизируйте схему базы данных, анализируйте запросы, используйте соответствующие индексы.
Запросите только те данные, которые вам нужны. Если вам не нужно 400 результатов, ограничьте свой запрос соответствующим образом.
Как часто эти данные действительно меняются? Всегда ли это должно быть актуальным? Разобрать данные в структуру, которая вам нужна в вашем контроллере или классе обслуживания, а затем кэшировать их в файл или тому подобное.
Читайте кэшированные данные, вместо того, чтобы каждый раз попадать в базу данных.
Не создавайте миниатюры на лету или в случае необходимости. Сгенерируйте их при загрузке или сгенерируйте их один раз и кэшируйте для дальнейшего использования.
Создайте свое представление и кэшируйте свое представление, чтобы вы снова не обращались к базе данных каждый раз.
Служите вашему контенту с соответствующими заголовками кэша, чтобы браузер пользователя кэшировал страницу и / или ресурсы.