[prev in list] [next in list] [prev in thread] [next in thread]
List: kmail-devel
Subject: [PATCH] speed up status setting
From: Till Adam <till () adam-lilienthal ! de>
Date: 2003-12-21 9:00:17
[Download RAW message or body]
[Attachment #2 (multipart/signed)]
[Attachment #4 (multipart/mixed)]
Hey folks,
the attached patch speeds up status setting for local and especially imap
folders by:
o accumulating all jobs for each folder in a separate list (could be several
when marking messages in search folders, for example) and send that
list off to each folder when done instead of processing each message
individually in KMSetStatusCommand.
o in the imap folder case, taking the list of uids handed over by the
KMSetStatusCommand and chunking it into groups that will be processed
as one list of uid sets depending on what the result status flags of the
mails is. So if there are some mails in the folder that are important and
some that are not, there will be two groups in the case of for example
"Mark all as read", one with result flags "\SEEN \FLAG" and one with result
flags just "\SEEN". Build sets of uids for each of those, a la
";UID=3:6,16:32" and send of each of those sets to the server for
processing
With this scheme the number of imap transactions goes from 20000 to a handfull
when marking all mails in a for a folder with 20000 mails in it as read.
Needless to say that speeds things up several orders of magnitude. The
limiting factor for both local and imap status setting is now disk i/o from
index accessing.
Please review.
Till
["KMail-statusSettingSpeedup.diff" (text/x-diff)]
Index: imapjob.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/imapjob.cpp,v
retrieving revision 1.33
diff -u -3 -p -r1.33 imapjob.cpp
--- imapjob.cpp 18 Dec 2003 21:10:39 -0000 1.33
+++ imapjob.cpp 21 Dec 2003 12:55:07 -0000
@@ -97,8 +97,8 @@ void ImapJob::init( JobType jt, QString
{
// transfers the complete message to the server
KURL url = account->getUrl();
- url.setPath( folder->imapPath() + ";SECTION="
- + QString::fromLatin1( KMFolderImap::statusToFlags( msg->status() ) ) );
+ QString flags = KMFolderImap::statusToFlags( msg->status() );
+ url.setPath( folder->imapPath() + ";SECTION=" + flags );
ImapAccountBase::jobData jd;
jd.parent = 0; jd.offset = 0;
jd.total = 1; jd.done = 0;
Index: kmcommands.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmcommands.cpp,v
retrieving revision 1.94
diff -u -3 -p -r1.94 kmcommands.cpp
--- kmcommands.cpp 16 Dec 2003 19:19:54 -0000 1.94
+++ kmcommands.cpp 21 Dec 2003 12:55:10 -0000
@@ -1098,6 +1098,7 @@ void KMSetStatusCommand::execute()
parentStatus = false;
}
}
+ QMap< KMFolder*, QValueList<int> > folderMap;
for ( it = mSerNums.begin(); it != mSerNums.end(); ++it ) {
kmkernel->msgDict()->getLocation( *it, &folder, &idx );
if (folder) {
@@ -1114,9 +1115,17 @@ void KMSetStatusCommand::execute()
continue;
}
}
- folder->setStatus( idx, mStatus, mToggle );
+ /* Collect the ids for each folder in a separate list and
+ send them off in one go at the end. */
+ folderMap[folder].append(idx);
}
}
+ QMapIterator< KMFolder*, QValueList<int> > it2 = folderMap.begin();
+ while ( it2 != folderMap.end() ) {
+ KMFolder *f = it2.key();
+ f->setStatus( (*it2), mStatus, mToggle );
+ ++it2;
+ }
}
Index: kmfolderimap.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmfolderimap.cpp,v
retrieving revision 1.156
diff -u -3 -p -r1.156 kmfolderimap.cpp
--- kmfolderimap.cpp 20 Dec 2003 11:09:00 -0000 1.156
+++ kmfolderimap.cpp 21 Dec 2003 12:55:14 -0000
@@ -920,19 +920,18 @@ void KMFolderImap::flagsToStatus(KMMsgBa
//-----------------------------------------------------------------------------
-QCString KMFolderImap::statusToFlags(KMMsgStatus status)
+QString KMFolderImap::statusToFlags(KMMsgStatus status)
{
- QCString flags = "";
- if (status & KMMsgStatusNew || status & KMMsgStatusUnread)
- return flags;
+ QString flags;
if (status & KMMsgStatusDeleted)
flags = "\\DELETED";
else {
- flags = "\\SEEN";
+ if (status & KMMsgStatusOld || status & KMMsgStatusRead)
+ flags = "\\SEEN ";
if (status & KMMsgStatusReplied)
- flags += " \\ANSWERED";
+ flags += "\\ANSWERED ";
if (status & KMMsgStatusFlag)
- flags += " \\FLAGGED";
+ flags += "\\FLAGGED";
}
return flags;
}
@@ -1237,19 +1236,38 @@ void KMFolderImap::setStatus(QValueList<
{
KMFolder::setStatus(ids, status, toggle);
if (mReadOnly) return;
-
+
/* The status has been already set in the local index. Update the flags on
- * the server. Needs to be done for each message individually. */
- for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it )
- {
+ * the server. To avoid doing that for each message individually, group them
+ * by the status string they will be assigned and make sets for each of those
+ * groups of mails. This is necessary because the imap kio_slave status job
+ * does not append flags but overwrites them. Example:
+ *
+ * 2 important mails and 3 unimportant mail, all unread. Mark all as read calls
+ * this method with a list of uids. The 2 important mails need to get the string
+ * \SEEN \FLAGGED while the others need to get just \SEEN. Build sets for each
+ * of those and sort them, so the server can handle them efficiently. */
+ QMap< QString, QStringList > groups;
+ for ( QValueList<int>::Iterator it = ids.begin(); it != ids.end(); ++it ) {
KMMessage *msg = 0;
bool unget = !isMessage(*it);
msg = getMsg(*it);
if (!msg) continue;
- QCString flags = statusToFlags(msg->status());
- setImapStatus(imapPath() + ";UID=" + msg->headerField("X-UID"), flags);
+ QString flags = statusToFlags(msg->status());
+ // Collect uids for each type of flags.
+ groups[flags].append(msg->headerField("X-UID"));
if (unget) unGetMsg(*it);
}
+ QMapIterator< QString, QStringList > dit;
+ for ( dit = groups.begin(); dit != groups.end(); ++dit ) {
+ QCString flags = dit.key().latin1();
+ QStringList sets = makeSets( (*dit), true );
+ // Send off a status setting job for each set.
+ for ( QStringList::Iterator slit = sets.begin(); slit != sets.end(); ++slit ) {
+ QString imappath = imapPath() + ";UID=" + ( *slit );
+ setImapStatus(imappath, flags);
+ }
+ }
mAccount->displayProgress();
}
Index: kmfolderimap.h
===================================================================
RCS file: /home/kde/kdepim/kmail/kmfolderimap.h,v
retrieving revision 1.54
diff -u -3 -p -r1.54 kmfolderimap.h
--- kmfolderimap.h 22 Nov 2003 18:09:11 -0000 1.54
+++ kmfolderimap.h 21 Dec 2003 12:55:15 -0000
@@ -216,7 +216,7 @@ public:
/**
* Convert message status to a list of IMAP flags
*/
- static QCString statusToFlags(KMMsgStatus status);
+ static QString statusToFlags(KMMsgStatus status);
/**
* Return the filename of the folder (reimplemented from KFolder)
[Attachment #8 (application/pgp-signature)]
_______________________________________________
KMail developers mailing list
KMail-devel@kde.org
https://mail.kde.org/mailman/listinfo/kmail-devel
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic