*large* album gets slower while going to next page

adventure
adventure's picture

Joined: 2004-03-21
Posts: 59
Posted: Sat, 2004-03-27 14:57

Hello,

Recently I added 1200 photos in one album.. It went okay :-)
It has 76 pages.

When loading page 1 to 30 every thing goes okay.. But when i load page 76 i get maximum excution time exceeded.

I understand what it means. But I do not see why it is so slow... It still needs to load only 15 images. So perhaps the algoritme could be better.

Any one ever tried?
Is there a profiler for php code btw?

Cheers,
Harry

 
adventure
adventure's picture

Joined: 2004-03-21
Posts: 59
Posted: Sun, 2004-03-28 17:05

Well there is a nice profiler for php.

http://www.adepteo.net/profiler/

I didn't find a easy way to increase speed. Tryed some stuff but I simple don't know the entire framework and frankly after seening some code. I don't want to. Don't get me wrong gallery is great!

Here some profiler reports (file edited is view_albums):

Page 1 show this one:

Page 1

============================================================================
                              PROFILER OUTPUT
============================================================================
Calls                    Time  Routine
-----------------------------------------------------------------------------
  1      7,1220 ms (  0,06 %)  findStartPoint
  1    1370,9629 ms ( 11,46 %)  hack check
  3    122,9346 ms (  1,03 %)  something
  1    291,4860 ms (  2,44 %)  page numbers
  1     21,6632 ms (  0,18 %)  part1
  1    139,2195 ms (  1,16 %)  part2
 15    396,1840 ms (  3,31 %)  photo
  1    588,2354 ms (  4,92 %)  unprofiled
 15    8676,1394 ms ( 72,53 %)  something2

       348,2423 ms (  2,91 %)  Missed
============================================================================
       11962,1892 ms (100,00 %)  OVERALL TIME

And page30 show this one. (I also added some zone to be countend and a cache function)

============================================================================
                              PROFILER OUTPUT
============================================================================
Calls                    Time  Routine
-----------------------------------------------------------------------------
  1    275,8203 ms (  1,43 %)  findStartPoint
451    2567,7032 ms ( 13,35 %)  getNextPhoto
496    1420,6243 ms (  7,39 %)  getNextPhoto_cache
  1    1484,7620 ms (  7,72 %)  hack check
  3     31,2140 ms (  0,16 %)  something
  1    273,4261 ms (  1,42 %)  page numbers
  1     21,6660 ms (  0,11 %)  part1
  1     49,3307 ms (  0,26 %)  part2
 15    3119,4386 ms ( 16,22 %)  photo
  1    599,6962 ms (  3,12 %)  unprofiled
 15    8140,8012 ms ( 42,33 %)  something2

       1245,8324 ms (  6,48 %)  Missed
============================================================================
       19230,3150 ms (100,00 %)  OVERALL TIME
============================================================================

As you can see the load time is increased page 75 is the limit of 30 seconds.

The findstart point & photo & something2 will rise heavly.

My cache function only save 50 calls

450 = 2,5 sec so thats about 0,2 seconds... :-(

After writing in the methode getNextPhoto()

return ++$idx;

It didn't even get faster. The other parts where to many lines to see a easy speed up.

Well hope somebody is inspired to crank it up for me ;-)

 
MarkCurly

Joined: 2004-05-20
Posts: 20
Posted: Sat, 2004-05-22 09:31

OK, Summary:

1) Function "isMovie($id)" which is called from view_album.php is inefficient.
An alternative function runs much faster, while still providing full functionality.
(Item (1) is NOT a hack, it should be made into a bug fix.)

2) If you don't hide photos, and everybody has the same permissions to view photos and albums, then there are some hacks that can be made to speed it up some more.
(Edited 24/5/04: removed "and you don't use nested albums" because the hack will work with nested albums.)

3) With both changes (1) & (2) above made, page 500 of an album will load up just as fast as page 1 (!! Yay !!)

4) Even with changes per (1) and (2) above, larger albums will take longer to load than smaller albums. This is because all of the photo meta-data must be loaded each time an album page is viewed, even though only 20 or so photos on that page are shown.
If performance is an issue, then use smaller albums.

Detail:

1) Code in view_album.php calls function "isMovie($id)".
"isMovie" calls getPhotoIndex($id), which loops through all of the photos in the album until it finds *index* the photo with the given $id. This loop is inefficient, and contributes to the extended delay when viewing higher page numbers.
(view_album.php aleady HAD the *index* of the photo, so there is no need to call getPhotoIndex($id).)

Fix:
1a) Modify gallery/classes/Album.php. Add a new function isMovieByIndex (around line 1447)

-----
function isMovie($id) {
$index = $this->getPhotoIndex($id);
$photo = $this->getPhoto($index);
return $photo->isMovie();
}

+function isMovieByIndex($index) {
+ $photo = $this->getPhoto($index);
+ return $photo->isMovie();
+}
+
function isItemOwner($uid, $index)
{
-----

1b) In view_album.php, modify code that sets the $id variable:
Find this comment:
// Find the correct starting point, accounting for hidden photos
... make changes below this point only.

Change occurences of:
- $id = $gallery->album->getPhotoId($i);
to:
+ $id = $gallery->album->getPhotoId($i);
+ $ididx = $i;

1c) Change occurences of:
...$gallery->album->isMovie($id)...
to:
...$gallery->album->isMovieByIndex($ididx)...

2) Hidden photos and nested albums that the viewer does not have permission to view complicate the process of numbering pages when the are viewed.
view_photo.php determines the first photo to view on a page by calling getNextPhoto() in a loop, skipping over photos corresponding to previous pages. While looping, it skips (and does not count) hidden or inaccesible photos or nested albums.
(Edited 24/5/05: "and also expands nested albums" BZZT - Wrong!)

If you don't hide photos, and everybody has the same permissions to view photos and albums, then there are some hacks that can be made to speed it up some more.

Change all calls to "$i = getNextPhoto($i)" to "$i++", and remove the very first loop:
/* DO NOT ITERATE
while ($cnt < $start) {
$rowStart = getNextPhoto($rowStart);
$cnt++;
}
* --DO NOT ITERATE
*/
// JUST GO STRAIGHT THERE
$cnt = $start;
$rowStart = $start;
// --JUST GO STRAIGHT THERE

Coming soon! a patch that speeds it up as much as the hack, but works with hidden photos!

Gallery 1.4.3.pl1

 
nivekiam
nivekiam's picture

Joined: 2002-12-10
Posts: 16504
Posted: Sat, 2004-05-22 16:52

I'm having the same slowing down problem with Gallery. There are over 1600 images in my install with about 150 of them that are hidden from most users and from public view. Most (about 80%) of the images are all within 1 album or in the many sub-albums of that album.

It really seems to become a resouce hog on the server and is causing time out issues if people are either posting images or even just viewing.

I'm going to try your hack and see if it helps, but I'd really like to see Gallery (G1) become a lot more effecient with being able to handle large numbers of images.

I'm currently using Gallery 1.4.3.pl1 (though my sig may say differently) and I had this problem with the 1.4.2

 
nivekiam
nivekiam's picture

Joined: 2002-12-10
Posts: 16504
Posted: Sat, 2004-05-22 17:08

Well I've only ran a few "tests" on it and need to wait on feedback from the users of the Gallery, but it does seem to have increased performance. Gallery still hits the server harder than I think it should, but it not hitting it as hard.

 
adventure
adventure's picture

Joined: 2004-03-21
Posts: 59
Posted: Sat, 2004-05-22 21:55

nivekiam, Always nice to meet a fellow speed up person ;-)

I made a speed this week with safes me a lot of time.
But for a large album, it will probably not do much.

I made a cache methode for the getNextPhoto methode.
(checkout cvs code, because that getNextPhoto methode is better to cache)

The album methodes numHidden numVisable numPhotos and the getNextphoto should all share the same cache i think.

That will speed up.

Cheers,
Harry

 
MarkCurly

Joined: 2004-05-20
Posts: 20
Posted: Tue, 2004-06-01 08:36
MarkCurly wrote:
Coming soon! a patch that speeds it up as much as the hack, but works with hidden photos!

Here is a patch to speed up Gallery 1.4.3-pl1

NOTE: A core Gallery developer who tried this patch on 1.4.4(development version) reported that it gave array out of bounds errors on all albums with nested sub-albums.
However, it works well for me on 1.4.3-pl1 and PHP 4.3.3 and I do have nested sub-albums.

My optimization is fairly simple, but (I think) very effective, and consists of three separate changes (in two patch files):

1) view_album.php calls classes/Album.php/numVisibleItems() to count the number of visible photos or nested albums.
It can be modified to return an array of item index numbers of the visible items.
If it returns an array, no further testing is needed in view_album as to whether the photo or nested album is visible or not (that test having already been made and returned in the array).
Because of the array, no searching is needed to skip over hidden items when determining which item starts the page or row.
view_album.php then does NOT even call util.php/getNextPhoto(), and does NOT need to (BUT see point (4) below).

2) view_album calls classes/Album.php/isMovie($id), which then calls $index = $this->getPhotoIndex($id), which has a for loop which loops through all of the photos until it finds the index corresponding to the given $id.
isMovie() then continues processing with the given index.
view_album ALREADY had the index of the photo, so it doesn't make sense to use the id to search for the index.
A new alternate function (?) "isMovieByIndex($i)" simply leaves out the call to "$index = $this->getPhotoIndex($id)" and uses the index passed in.

3) (small) classes/Album.php/numVisibleItems contains a call to $album->load(...), to load a nested album to test if it should be visible.
$album->load(...) by default, also loads the photos of that nested album (optional parameter), but it is not required to load the photos and is inefficient.
A two character change:
$album->load($photo->getAlbumName(),0);
(note addition of ",0" so as not to load the nested album's photos)

These patches don't speed up page one of an album very much (unless it has sub-albums).
They DO speed up higher numbered pages, quite well.

Without these patches, I was getting 30 second maximum execution limit errors with about 2000 photos in an album, and higher page numbers took successively longer and longer to load (page 200 taking twice as long to load as page 100 for example).

With these patches, the last page loads just as quickly as the first page.

(END of performance enhancements)

4) (Even before the patch is applied) There is a bug/problem with util.php/getNextPhoto() & classes/Album.php/numVisibleItems().

These two functions use slightly different tests to decide if a photo or nested album is to be shown or not.

After the patch is applied, view_album.php does not call getNextPhoto at all, but relies on the tests in numVisibleItems instead.

The difference in the tests may or may not effect which photos are displayed or hidden in your albums after you apply this patch. (These differences made no difference to my albums.)

Mark

 
MarkCurly

Joined: 2004-05-20
Posts: 20
Posted: Thu, 2004-06-10 12:03
MarkCurly wrote:
Here is a patch to speed up Gallery 1.4.3-pl1

If you download the patch and try it, can I please get some feedback?
Good or Bad.