MBOX-Line: From blong at google.com  Wed Nov 21 15:31:02 2012
To: imap-protocol@u.washington.edu
From: Brandon Long <blong@google.com>
Date: Fri Jun  8 12:34:49 2018
Subject: [Imap-protocol] Re: Suspend/Restore feature proposal
In-Reply-To: <20121121155417.Horde.ZeW7JqTPNxTAI-hTtrAT-Q9@bigworm.curecanti.org>
References: <20121115215854.Horde.zz6B0O0tmt3ylHiEXzXhQQ4@bigworm.curecanti.org>
	<CABa8R6tHP2My0k2LqT1RzHoLQZA+X_jwUMU0cydm2sAwo8f4Fg@mail.gmail.com>
	<20121116143137.Horde.7Kb3aEW5DhM6CnuA2hAx4Q8@bigworm.curecanti.org>
	<e122fa25-9110-4b36-855d-0e7e273c5805@flaska.net>
	<20121121155417.Horde.ZeW7JqTPNxTAI-hTtrAT-Q9@bigworm.curecanti.org>
Message-ID: <CABa8R6sJfnA=HYk-fmFfpXki91cne_LeqFyuhDebMGeDdsdj7g@mail.gmail.com>

On Wed, Nov 21, 2012 at 2:54 PM, Michael M Slusarz <slusarz@curecanti.org>wrote:

> Jan,
>
> Thanks for the input.  My responses are below.
>
>
> Quoting Jan Kundr?t <jkt@flaska.net>:
>
>  Hi Michael,
>> I've read your draft, it's an interesting extension. However, it seems to
>> me that the whole point here is to save a few roundtrips by skipping the
>> process of activating/configuring various optional features. I'll discuss
>> each extension separately.
>>
>
> I would strongly disagree with this statement.  As written, the draft is
> only minimally concerned with saving on network round-trips.
>

Yet, that and bytes are what you quote from your example.


> E.g. a webmail implementation: for any even reasonably sized setup,
> interaction between the webmail backend and the IMAP server will almost
> certainly be done through a private network.  Such a setup has the added
> benefit that the IMAP connection does not need any sort of security [TLS]
> overhead.  I have assumed in the draft that the client/server round-trip is
> negligible or, in the very least, not the bottleneck in the IMAP
> interaction.
>
> However, client/server round-trip *is* most likely an issue for a whole
> category of disconnected-like clients: those running on mobile hardware.
>  Pipelining in this environment in no way guarantees that a server can or
> will return the response in the same network packet.  In other words, this
> draft becomes *more* important the more that client/server round-trip time
> becomes the bottleneck/limiting factor, whether pipelined or not.
>
> Sidebar: I'm not a huge fan in general of pipelining as a performance
> since it is not always a feasible option for clients.  For example, a
> client may use an OO-library to connect to the IMAP server.  This library
> may not provide a reasonable (or any) way of allowing multiple commands to
> be sent at once via the API.  For example, to start compression, enable
> QRESYNC, and set the language, it is more than reasonable to expect this
> kind of pseudocode:
>
> $result = $imap->useCompression(true);
> // Check for success
> $imap->useQresync(true);
> // Check for success
> $imap->setLanguage([LANGUAGE])**;
> // Check for success
>
> In any OO IMAP interface the order of IMAP commands to allow for efficient
> pipelining, or the fact that pipelining even exists, should obviously not
> be a part of the API.  Thus pipelining is fairly useless in the real world
> as a way to guarantee an increase in performance.
>

Thats not a true statement.  Its useless if you're forced to use a bad
client API that you aren't willing to work around?  Is that bad client API
going to support adding a new command?


> There are other, more important reasons why a mechanism to restore
> configuration is useful:
>
> - It prevents the need to re-parse the CAPABILITY list.  Note that parsing
> the CAPABILITY list involves *MUCH* more than just the actual string
> tokenization of the list, although this alone may not be a trivial task
> (see below).
>
> A client may, depending on the capabilities returned, need to perform
> various internal initialization tasks.  For example - if CONDSTORE/QRESYNC
> is listed, a client may have to then parse a separate configuration file to
> grab the details of the local cache where it is storing this information,
> and then connect to this cache, etc.  Or if language is listed, a client
> might have to parse a local list of language availability to determine if
> it can/should change the language.
>

And... it would have had to do that anyways.  If its resuming the
connection, it has to either do that initialization or it has to cache that
initialization, both of which it can do just as easily on non-resume if
we're talking about a new connection every 10s.

Parse a local list of language availability?  So, you want to avoid reading
a local config file ... on the hope that the client doesn't need to know
that language information anyways just to display stuff to the user which
doesn't come from the server?


> And CAPABILITY parsing is more than just determining what capabilities are
> listed.  It is also determining which capabilities SHOULD not be listed.
>  Just today, Cyrus was fixed due to a bug that our code was triggering:
> APPENDing binary data via a literal8 caused Cyrus to immediately terminate
> the connection with a BYE response.  Our code is smart enough to catch this
> broken behavior by removing BINARY appending from the list of available
> capabilities.  But without a way to ensure that every subsequent connection
> is a continuation of the current session, we have to do this detection
> EVERY SINGLE TIME.  This is potentially a huge performance hit, since we
> may be appending MBs of data to the server before the BYE response can be
> returned (e.g. appending a sent-mail message containing attachments).
>

So, you worked around the cyrus bug by determining the connection exhibits
the bug and then never using it for that server again?  Or, you could just
not use BINARY ever, or issue an ID command to know if the remote server
has the bug.  You could even pipeline it!  Or you could store the known bad
server information somewhere in your app server.


> - As mentioned above, sending an initialization command to the server may
> take quite a bit of work on the client side to prepare.  It's not as easy
> as hardcoding 'ENABLE QRESYNC' in client code - it may take quite a bit of
> CPU cycles to get to that point in a given client.
>

But this doesn't change anything about the having to do that.  Regardless
of whether you're resuming a session or not, you still have to do that work.


> Another example: a client keeps all of its imap initialization code in a
> separate dynamically-loadable module.  If the session is successfully
> resumed, this module does not need to be loaded/interpreted/run.
>

What kind of clients are we talking about?  I'm just completely failing to
think this is an issue.


> - From the server side, it may be much more expensive to initiate an IMAP
> session as compared with resuming one.  This draft allows the server to
> optimize if possible.  I believe Timo's post indicates that resuming in
> Dovecot is more efficient than creating a new session.
>

Resuming into the middle of a selected folder seems cheap.  Resuming the
status of N commands seems  optimizing in the small.  I would think it
would cost more in terms of either caching the data in memory or stashing
the data to disk/reading it back than the overhead of parsing a couple
commands and maybe allocating a data structure.


> - Even when pipelining commands, they still need to be sent, the incoming
> command needs to be tokenized (server), the command is performed (server),
> the response sent back, any untagged responses are tokenized (client), the
> untagged responses are interpreted (client), the tagged response is
> tokenized (client), and the tagged response is processed (client).  None of
> this is "free".  Pipelining eliminates none of this.


Tokenization is what clients and servers do, and this takes a trivial
amount of time and cpu in reasonable languages.


>  COMPRESS=DEFLATE
>>>
>>
>> I was wondering if this one actually provides any benefit for a webmail
>> client. But you're right that it indeed has an overhead and requires a full
>> roundtrip to set up. However, please note that your extension also requires
>> a full roundtrip, so you aren't any better here.
>>
>
> First a point of clarification: the draft is not specific to webmail
> clients.  It is intended for any disconnected client that may have need to
> initiate multiple IMAP connections during the client's lifetime.
>
> Granted, it is extremely useful for webmail clients due to extreme
> disconnected nature of the connections, but it would also be highly useful
> for clients on any device that does not have a constant (or reliable)
> network connection to the server.  e.g. smartmobile clients; ActiveSync
> polling.
>
> Whether or not COMPRESS is beneficial to a webmail implementation is
> beyond the scope of this discussion.
>
> Second, you are partially right.  A successful restoration of the
> configuration state does require a round-trip to the server.  But a RESUME
> command sent before initialization is an example of a command that CAN be
> easily pipelined with an authentication command.  And the full round-trip
> is offset somewhat by the fact that upon a successful RESUME, the
> CAPABILITY string will not be sent-back to the client if the server
> normally does this automatically on authentication.  And if the server
> doesn't normally return CAPABILITY information, then this is a complete win
> (RESUME/tagged OK vs. CAPABILITY command/CAPABILITY untagged
> response/tagged OK).


And what does "resuming" a COMPRESS=DEFLATE do?  I assume we're not talking
about trying to keep the old dictionary or anything like that, right?
 We're actually talking about just the equivalent of starting it again.


>  ENABLE (CONDSTORE/QRESYNC)
>>> LANGUAGE
>>> COMPARATOR
>>>
>>
>> It looks to me that you can easily pipeline all of these and that you do
>> not risk anything by doing so. Yes, I'm aware of the wording of the ENABLE
>> RFC which sounds like one really MUST check its return code, but a
>> subsequent thread on this list indicated that this was not the desired
>> outcome and that it is completely legal to pipeline ENABLE QRESYNC with
>> SELECT ... QRESYNC.
>>
>
> I would argue that the language of the RFC still controls despite what an
> e-mail on this list says.  A client shouldn't be punished for interpreting
> it that way either.
>
>
>  As of the LANGUAGE -- how often do you expect to hit an error condition
>> which is not described by an appropriate response code? I don't think that
>> blocking for its result would be a good design choice.
>>
>
> That could be your decision as a client author.  I would vehemently
> disagree.


Or just re-issue the command to get the response translated.

 And finally, what IMAP servers support the LANGUAGE extension?
>>
>
> Why does this matter?  RFC 5255 is a Standards Track extension.  A year
> from now, every IMAP server and 200 new ones may support it.


True.  But that also goes to my point that you need to specify which
extensions and what information would need to be resumed, you can't just
say "any which apply", what if the server author doesn't think the way you
do and one of these doesn't get resumed?

 CONVERSIONS
>>> saved CONTEXTs
>>> NOTIFY
>>>
>>
>> Are you actually aware of a single IMAP server supporting any of these
>> (besides CONTEXT=SEARCH, which again can easily be pipelined without any
>> race conditions, and is specific to a mailbox state anyway, which is
>> outside of scope of your extensions)?
>>
>
> Again, why does this matter?  All of these are Standards Track extensions
> (your argument might hold a bit more water if these were Experimental
> documents).
>
> And what about future extensions?  Those obviously aren't supported by ANY
> server yet.
>
> A given client may not support any of these extensions.  This client could
> make the decision that SUSPEND/RESUME is pointless.  That doesn't mean the
> SUSPEND feature is pointless since another client may support ALL of these
> extensions.
>
>
>  In general, all of the items which you included as an example look like
>> easily pipelineable items. Have you tried to use pipelining for these? What
>> was the total time spent waiting for their completion in that case? What
>> would be the best theoretical time which you could get by RESTORE?
>>
>
> It would be impossible to determine benchmarks since there is no defined
> protocol yet.  And, as mentioned above, any given client/server interaction
> may provide different results based on their own internal optimizations and
> extension support.
>

But without an actual proof that this is useful for some combination of
client/server, why would we adopt yet another extension that no one will
implement?


> About the only thing you could do is look at network traffic savings.  The
> following is an example of the possible savings giving a moderate use of
> IMAP configuration state (this is a more real-world example of Examples 1 &
> 2 in the draft):
>
> Initial session:
>
> [User authenticated]
> A1 CAPABILITY
> * CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE
> SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT
> MULTIAPPEND UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1
> CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS
> SPECIAL-USE ACL RIGHTS=texk
> [This is the CAPABILITY list from Dovecot 2.1.10]
> A1 OK Capability completed.
> A2 ENABLE QRESYNC
> * ENABLED QRESYNC
> A2 OK Enabled.
> A3 LANGUAGE DE
> * LANGUAGE (DE)
> * NAMESPACE (("" "/")) (("Other Users/" "/" "TRANSLATION" ("Andere
> Ben&APw-tzer/"))) (("Public Folders/" "/" "TRANSLATION" ("Gemeinsame
> Postf&AM8-cher/")))
> A3 Sprachwechsel durch LANGUAGE-Befehl ausgefuehrt
> [...]
> A20 SUSPEND
> * SUSPEND c3RhdGUgdG9rZW4=
> * BYE Server logging out.
> A20 OK Logout completed.
>
> Additional network data required by SUSPEND commands: 29 bytes (LOGOUT vs.
> SUSPEND; SUSPEND untagged response)
> [However, this command will only normally be run the FIRST time the
> session is accessed, so this is a one-time only hit]
> Additional round-trips required: 0
>
> Subsequent sessions:
>
> A1 RESUME c3RhdGUgdG9rZW4=
> A1 OK
> A2 LOGIN joe passwd
> A2 OK [RESUME c3RhdGUgdG9rZW4=] LOGIN completed and configuration restored.
> [...]
>
> Additional network data required by RESUME commands: 61 bytes (RESUME
> command, RESUME response code)
> Additional round-trips required: 1
> Network data saved by RESUME: ~650 bytes
> Round-trips saved: 3
> Server parsed commands saved: 3
> Client issued commands saved: 3
> Untagged responses that do not need to be re-parsed: 4
>
>
> In this example, the one-time addition of 29 bytes of network traffic (1
> additional untagged response parse) results in the savings of 2
> round-trips, ~600 bytes of network traffic, and 3 additional commands that
> need to be parsed on the client/server side.  And remember this doesn't
> factor in any initialization code that needs to be run within the
> server/client to perform these commands.
>
> To me, that is substantial savings, especially when the connection may be
> re-established every 10 seconds.
>

Have you considered not re-establishing a connection every 10s?  This is a
connected protocol, not http.

Brandon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman13.u.washington.edu/pipermail/imap-protocol/attachments/20121121/9121521e/attachment.html>
