Re: [hybi] Multiplexing: Pre-AddChannelResponse quota

"Arman Djusupov" <arman@noemax.com> Thu, 07 June 2012 12:14 UTC

Return-Path: <arman@noemax.com>
X-Original-To: hybi@ietfa.amsl.com
Delivered-To: hybi@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 5C75A21F884C for <hybi@ietfa.amsl.com>; Thu, 7 Jun 2012 05:14:42 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.399
X-Spam-Level:
X-Spam-Status: No, score=-2.399 tagged_above=-999 required=5 tests=[AWL=0.200, BAYES_00=-2.599]
Received: from mail.ietf.org ([12.22.58.30]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1BE5PAM6UGVo for <hybi@ietfa.amsl.com>; Thu, 7 Jun 2012 05:14:41 -0700 (PDT)
Received: from mail.noemax.com (mail.noemax.com [64.34.201.8]) by ietfa.amsl.com (Postfix) with ESMTP id EA0A521F884A for <hybi@ietf.org>; Thu, 7 Jun 2012 05:14:40 -0700 (PDT)
DKIM-Signature: a=rsa-sha1; t=1339071276; x=1339676076; s=m1024; d=noemax.com; c=relaxed/relaxed; v=1; bh=DVOiKIwT//2z0q6WA/+ryi60DZU=; h=From:Subject:Date:Message-ID:To:Cc:MIME-Version:Content-Type:Content-Transfer-Encoding:In-Reply-To:References; b=7vV4rV/L8Dr+b67xYi9gmYlpZCccmzDSxxpuOQFauvoZsWCDj59QYkpohJRi7fwPIzA2oOkkr98opRk6XVvEf0UIOVBP2fzSVs+UP/3c7SOXHbNXyFwqzdGI6J6CHB6r0NDm62xF+LZoktsuu1+u3NHWXFk5IQU30qiWLNGgnn0=
Received: from mail.noemax.com by mail.noemax.com (IceWarp 10.4.1) with ASMTP (SSL) id RSV45335; Thu, 07 Jun 2012 15:14:35 +0300
From: Arman Djusupov <arman@noemax.com>
To: 'Jamie Lokier' <jamie@shareable.org>
References: <CAH9hSJZUAHQzDm4ofq6onc620SNretLQDOcjSnr2eQ0YA9yFdQ@mail.gmail.com> <002f01cd3cc4$4791b380$d6b51a80$@noemax.com> <20120607034440.GD26406@jl-vm1.vm.bytemark.co.uk>
In-Reply-To: <20120607034440.GD26406@jl-vm1.vm.bytemark.co.uk>
Date: Thu, 07 Jun 2012 15:14:23 +0300
Message-ID: <001001cd44a7$17c0a220$4741e660$@noemax.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
X-Mailer: Microsoft Outlook 14.0
thread-index: AQHbEEjWH8q2xL+U7IgUz4ieagM0MAIpCHL8APvLbp+WugWmUA==
Content-Language: en-us
Cc: hybi@ietf.org
Subject: Re: [hybi] Multiplexing: Pre-AddChannelResponse quota
X-BeenThere: hybi@ietf.org
X-Mailman-Version: 2.1.12
Precedence: list
List-Id: Server-Initiated HTTP <hybi.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/hybi>, <mailto:hybi-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/hybi>
List-Post: <mailto:hybi@ietf.org>
List-Help: <mailto:hybi-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=subscribe>
X-List-Received-Date: Thu, 07 Jun 2012 12:14:42 -0000

The common pre-handshake quota mechanics need to be simplified. 

A server's buffer pool capacity is very volatile. There is no reliable way to predict what capacity the server will have in a few seconds. Whatever complex decision process the server uses to estimate its buffer availability, at the moment when a buffer has to be acquired this estimation will be already outdated. When the server code cannot really know what amount of memory will be available during the next handshake, what is the point of giving a client an estimation on the server's buffering capacity?

Since there is no run-time precision, the reasonable solution is to set those limits based on either optimistic or pessimistic expectations and worst case scenarios.
 
During the initial handshake the server can negotiate a value that would indicate the maximum amount of initial quota the client can use before the handshake is complete. So before handshaking the client simply sets its quota to this value. The server will be spending its buffers as normal knowing that the client didn't violate any initial agreements. So there would be no additional common quota calculation on the server side. 

If a large number of clients establish logical channels concurrently and each uses an initial quota, the server may run out of buffers (unless it has the capacity to provide buffering to all new channels being established). I'm not too much concerned about it. Whatever we do, there will always be a case when the server may run out of buffers.

My expectation is that by using more complex algorithms for the initial quota we won't really make it more reliable.

With best regards,
Arman

-----Original Message-----
From: Jamie Lokier [mailto:jamie@shareable.org] 
Sent: Thursday, June 07, 2012 6:45 AM
To: Arman Djusupov
Cc: 'Takeshi Yoshino'; hybi@ietf.org
Subject: Re: [hybi] Multiplexing: Pre-AddChannelResponse quota

Arman Djusupov wrote:
> 
>    Resending would be required when the allocation of a logical channel
>    has failed on the server or the intermediary due to any kind of mux
>    related error. For example: “Maximum number of logical channels per
>    physical connection has been reached “ or “Intermediary cannot reach
>    the destination endpoint”. The current draft requires that if an
>    AddChannelResponse is received with a failed flag, the client attempts
>    to open a new physical connection. Since the browser must keep the mux
>    extension transparent it cannot let the JS application handle the
>    recovery from mux related errors.

If there is a max_simultaneous_handshakes - why not recast that as "initial new-channels window" - meaning a flow control grant, which is updated by further grants from the server.  (Very similar to the flow control per channel).

Then it means initially you can set a number, and subsequently, the server will control the rate of admission of new channels.  Then it can regulate it at a smaller or larger value, be conservative if appropriate until a client has proven not to be an attack, etc.

There's basically zero message overhead, as the grant update would follow AddChannelResponse if the server wants to maintain a constant number in flight.

Having redefined max_simultaneous_handshakes that way....

It removes the need to re-send due to "maximum number of channels reached" - because it can't happen.  The token is a promise.  (If the server can't take it, there's a fault so it's a reason for a hard error).

"Intermediate cannot reach destination endpoint" ought to be a non-retry error for the same reason that it would be for an HTTP intermediary.  I guess this is debatable.

But assuming that debate was won :-) there would be no reason for re-sending.

That said, it doesn't really matter, the client is free to limit the amount of data it sends before a channel is confirmed, to an amount it considers reasonable to store.

A goal that I think is worthwhile are zero-latency-creation channels,

That is where a JS would be free to create channels, with no round-trip overhead to start a request-response pattern over them.

It's currently paradoxical that HTTP (and especially SPDY) use one _less_ round-trip to send short AJAX-style requests from independent code (or independent pages), compared with multiplexed WebSocket.

Zero-latency-creation channels would make WS behave at least as well as AJAX in the small-request-response pattern, which is after all extremely common.

>    I like the idea of using the total pre-handshake quota for all logical
>    channels. This would allow high throughput channels to utilize a common
>    pre-handshake quota when other channels do not require to send any data
>    prior to receiving an AddChannelResponse. I believe that this solution
>    would be more optimal than having a pre-handshake quota per logical
>    channel.

It's more flexible for the client, which can choose to abuse it or not.  I like the idea - but... does it make any problems for the server?

The server may know it has enough memory for N bytes per channel buffer, but it may not have a data structure which can efficiently assign M*N bytes to a single channel (for example due to memory fragmentation or pre-allocation issues, or simply how "malloc" works).
It might also want to prevent M*N for heuristic reasons such as channel fairness - which it is already responsible for when channels are up and running.

In my view, the server must have the ability to constrain the initial parameters of each channel that the client can assume.  It would be fine to allow the server to grant a total pre-handshake quota, as an optional extra, but there should definitely be some constraint on pre-handshake per-channel data.  But I do favour that being non-zero.

>    However, this solution would require the client to subtract the
>    required value from the common quota and specify this value in
>    the AddChannelRequest header, so that the server knows from which
>    initial value to start counting the remote side quota.

Isn't it clear without it?  The client sends pre-handshake data, the server moves it from the common pool to the new channel buffer, potentially freeing up space in the common pool (if it wants), and the server simply treats the data, for flow control window purposes, as if it came after the channel was set up.  Everyone agrees.

Anyway, the client shouldn't have to pause/delay sending data after AddChannelRequest, until the response, if there is sufficient quota to keep sending.  Specifying the amount used in the request would seem to enforce that delay, which is unnecessary in principle.

>    There should also be a way to restore the common quota, e.g. in
>    AddChannelResponse the server can send a header which would
>    specify the value that should be added to the common
>    pre-handshake quota.

If there is a common pre-handshake data quota, I agree with this.
However, it should not be attached specifically to AddChannelResponse.
Rather, the server should be able to increase this amount granted at any time, so have its own message.

It parallels what I suggested at the start of this mail, about making the physical handshake quota be a window that is maintained by flow control grants from the server, rather than a fixed in-flight constant, in the same way as per-channel flow control does.

All the best,
-- Jamie