Bugzilla – Attachment 97378 Details for
Bug 24185
'If all unavailable' state for 'on shelf holds' makes holds page very slow if there's a lot of items
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 24185: Make holds page fast when 'on shelf holds' set to 'If all unavailable'
Bug-24185-Make-holds-page-fast-when-on-shelf-holds.patch (text/plain), 5.39 KB, created by
Andrii Nugged
on 2020-01-15 07:26:25 UTC
(
hide
)
Description:
Bug 24185: Make holds page fast when 'on shelf holds' set to 'If all unavailable'
Filename:
MIME Type:
Creator:
Andrii Nugged
Created:
2020-01-15 07:26:25 UTC
Size:
5.39 KB
patch
obsolete
>From 69f768158d0b290a981b5b3ef88abcf064e2a168 Mon Sep 17 00:00:00 2001 >From: Andrew Nugged <nugged@gmail.com> >Date: Wed, 15 Jan 2020 00:50:49 +0200 >Subject: [PATCH] Bug 24185: Make holds page fast when 'on shelf holds' set to > 'If all unavailable' > >When "reserve/request.pl -> C4/Reserves.pm::IsAvailableForItemLevelRequest" called many times with hundred of items and "on shelf holds" parameter set to "If all unavailable" for these items + patron, it goes slow. > >It happens because in subloop it is checking if all items available so it is O(n^2) and it re-checks each time the same info for each item with repeating DB/data requests. > >Fix: >The inner loop 1:1 picked out into separate subroutine and called outside of the loop, saving data in 'items_any_available' variable once, this variable passed to IsAvailableForItemLevelRequest to be used inside as the precalculated result. > >This made algorithm O(n) instead of O(n^2) so there is noticeable speed increase. > >How to reproduce: > >1) on freshly installed kohadevbox create/import one book, >remember that biblionumber for later use it in down below, > >2) add 100 items for that book for some library, > >3) find some patron, that patron's card number we will >use as a borrower down below to open holds page, > >4) check for the rule or set up a single circulation rule >in admin "/cgi-bin/koha/admin/smart-rules.pl", >that rule should match above book items/library/patron, >check that rule to have a non-zero number of holds (total, daily, count) allowed, >and, IMPORTANT: set up "On shelf holds allowed" to "If all unavailable", >("item level holds" doesn't matter). > >5) open "Home > Catalog > THAT_BOOK > Place a hold on THAT_BOOK" page >("holds" tab), and enter patron code in the search field, >or you can create a direct link by yourself, for example, in my case it was: >/cgi-bin/koha/reserve/request.pl?biblionumber=4&findborrower=23529000686353 > >6) it should be pretty long page generation time on old code, densely increasing for every hundred items added. In the case of this solution, it's fast, and time increases a little only, linear. > >I tested on my computer in VirtualBox for page generation times, >did 3-5 runs for same case to check if results are stable, and got such values: > >(old code): > 100 items: 50 seconds > 200 items: 3.2 minutes > 300 items: 7.3 minutes > >(version with fix): > 100 items: 4.4 seconds > 200 items: 7.5 seconds > 300 items: 10.4 seconds >--- > C4/Reserves.pm | 13 ++++++++++++- > reserve/request.pl | 13 ++++++++++++- > 2 files changed, 24 insertions(+), 2 deletions(-) > >diff --git a/C4/Reserves.pm b/C4/Reserves.pm >index 7554b3e143..baf88086a5 100644 >--- a/C4/Reserves.pm >+++ b/C4/Reserves.pm >@@ -1204,7 +1204,12 @@ and canreservefromotherbranches. > =cut > > sub IsAvailableForItemLevelRequest { >- my ( $item, $patron, $pickup_branchcode ) = @_; >+ my $item = shift; >+ my $patron = shift; >+ my $pickup_branchcode = shift; >+ # items_any_available is precalculated status passed from request.pl when set of items >+ # looped outside of IsAvailableForItemLevelRequest to avoid nested loops: >+ my $items_any_available = shift; > > my $dbh = C4::Context->dbh; > # must check the notforloan setting of the itemtype >@@ -1239,6 +1244,12 @@ sub IsAvailableForItemLevelRequest { > if ( $on_shelf_holds == 1 ) { > return 1; > } elsif ( $on_shelf_holds == 2 ) { >+ >+ # if we have this param predefined from outer caller sub, we just need >+ # to return it, so we saving from having loop inside other loop: >+ return $items_any_available ? 0 : 1 >+ if defined $items_any_available; >+ > my $any_available = ItemsAnyAvailableForHold( { biblionumber => $item->biblionumber, patron => $patron }); > return $any_available ? 0 : 1; > } else { # on_shelf_holds == 0 "If any unavailable" (the description is rather cryptic and could still be improved) >diff --git a/reserve/request.pl b/reserve/request.pl >index 8db78a1e33..ee01839097 100755 >--- a/reserve/request.pl >+++ b/reserve/request.pl >@@ -444,6 +444,15 @@ foreach my $biblionumber (@biblionumbers) { > $itemtypes->{ $biblioitem->{itemtype} }{imageurl} ); > } > >+ # iterating through all items first to check if any of them available >+ # to pass this value further inside down to IsAvailableForItemLevelRequest to >+ # it's complicated logic to analyse. >+ # (before this loop was inside that sub loop so it was O(n^2) ) >+ my $items_any_available; >+ >+ $items_any_available = ItemsAnyAvailableForHold( { biblionumber => $biblioitemnumber, patron => $patron }) >+ if $patron; >+ > foreach my $itemnumber ( @{ $itemnumbers_of_biblioitem{$biblioitemnumber} } ) { > my $item = $iteminfos_of->{$itemnumber}; > my $do_check; >@@ -557,7 +566,9 @@ foreach my $biblionumber (@biblionumbers) { > !$item->{cantreserve} > && !$exceeded_maxreserves > && $can_item_be_reserved eq 'OK' >- && IsAvailableForItemLevelRequest($item_object, $patron) >+ # items_any_available defined outside of the current loop, >+ # so we avoiding loop inside IsAvailableForItemLevelRequest: >+ && IsAvailableForItemLevelRequest($item_object, $patron, undef, $items_any_available) > ) > { > $item->{available} = 1; >-- >2.17.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 24185
:
96079
|
96080
|
96151
|
96354
|
96460
|
96461
|
96464
|
96491
|
96492
|
96493
|
96500
|
97375
|
97376
|
97377
|
97378
|
101355
|
101356
|
101357
|
101358
|
101607
|
101608
|
101609
|
101611
|
101613
|
101614
|
101615
|
101616