From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 9886D1FBEB for ; Wed, 10 Jun 2020 07:07:30 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 60/82] imap: UID FETCH: optimize (UID FLAGS) harder Date: Wed, 10 Jun 2020 07:04:57 +0000 Message-Id: <20200610070519.18252-61-e@yhbt.net> In-Reply-To: <20200610070519.18252-1-e@yhbt.net> References: <20200610070519.18252-1-e@yhbt.net> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: We can speed up this common mutt request by another 2-3x by not loading the entire smsg from SQLite, just the UID. --- lib/PublicInbox/IMAP.pm | 42 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/lib/PublicInbox/IMAP.pm b/lib/PublicInbox/IMAP.pm index 0fe31a77244..0d553da91f9 100644 --- a/lib/PublicInbox/IMAP.pm +++ b/lib/PublicInbox/IMAP.pm @@ -41,8 +41,9 @@ sub LINE_MAX () { 512 } # does RFC 3501 have a limit like RFC 977? sub UID_BLOCK () { 50_000 } # these values area also used for sorting -sub NEED_BLOB () { 1 } -sub NEED_EML () { NEED_BLOB|2 } +sub NEED_SMSG () { 1 } +sub NEED_BLOB () { NEED_SMSG|2 } +sub NEED_EML () { NEED_BLOB|4 } my $OP_EML_NEW = [ NEED_EML - 1, \&op_eml_new ]; my %FETCH_NEED = ( @@ -57,7 +58,7 @@ my %FETCH_NEED = ( BODYSTRUCTURE => [ NEED_EML, \&emit_bodystructure ], ENVELOPE => [ NEED_EML, \&emit_envelope ], FLAGS => [ 0, \&emit_flags ], - INTERNALDATE => [ 0, \&emit_internaldate ], + INTERNALDATE => [ NEED_SMSG, \&emit_internaldate ], ); my %FETCH_ATT = map { $_ => [ $_ ] } keys %FETCH_NEED; @@ -578,6 +579,38 @@ sub uid_fetch_smsg { # long_response 1; # more } +sub uid_fetch_uid { # long_response + my ($self, $tag, $uids, $range_info, $ops) = @_; + while (!@$uids) { # rare + my ($beg, $end, $range_csv) = @$range_info; + if (scalar(@$uids = @{$self->{ibx}->over-> + uid_range($beg, $end)})) { + $range_info->[0] = $uids->[-1] + 1; + } elsif (!$range_csv) { + $self->write(\"$tag OK Fetch done\r\n"); + return; + } else { + my $next_range = range_step($self, \$range_csv); + if (!ref($next_range)) { # error + $self->write(\"$tag $next_range\r\n"); + return; + } + @$range_info = @$next_range; + } + # continue looping + } + for (@$uids) { + $self->msg_more("* $_ FETCH (UID $_"); + for (my $i = 0; $i < @$ops;) { + my $k = $ops->[$i++]; + $ops->[$i++]->($self, $k); + } + $self->msg_more(")\r\n"); + } + @$uids = (); + 1; # more +} + sub cmd_status ($$$;@) { my ($self, $tag, $mailbox, @items) = @_; return "$tag BAD no items\r\n" if !scalar(@items); @@ -794,7 +827,8 @@ sub fetch_compile ($) { $r[2] = [ map { [ $_, @{$partial{$_}} ] } sort keys %partial ]; } - $r[0] = $need ? \&uid_fetch_msg : \&uid_fetch_smsg; + $r[0] = $need & NEED_BLOB ? \&uid_fetch_msg : + ($need & NEED_SMSG ? \&uid_fetch_smsg : \&uid_fetch_uid); # r[1] = [ $key1, $cb1, $key2, $cb2, ... ] use sort 'stable'; # makes output more consistent