All of lore.kernel.org
 help / color / mirror / Atom feed
* Patch: Improve HTTP time by sending Connection:close
@ 2016-11-12 17:26 Walter Huf
  2016-11-15 13:21 ` Daniel Kiper
  0 siblings, 1 reply; 8+ messages in thread
From: Walter Huf @ 2016-11-12 17:26 UTC (permalink / raw)
  To: grub-devel

[-- Attachment #1: Type: text/plain, Size: 2225 bytes --]

GRUB's HTTP module declares support for HTTP/1.1, which defaults to
Connection:keepalive. At the end of the content, the server holds the TCP
connection open waiting for the next request.
It seems that grub_net_poll_cards() is watching for the HTTP module to set
net->stall, and otherwise waits the full 400ms GRUB_NET_INTERVAL to return
to processing. However, HTTP module only sets that flag in specific
conditions:

   - parse_line detects that we are at the end of downloading a chunked
   Transfer-Encoding
   - http_err detects a problem with the underlying TCP connection
   - http_receive has queued 20 netbuffer packets for processing

If the file is small and takes less than 20 packets, and the server is not
using chunked encoding, grub_net_poll_cards() will wait the full 400ms
before continuing to process and finish the file download.

This patch sets Connection:close, which will tell the server to close the
connection as soon as it has finished sending the file. GRUB closes any
connections that are left open (in http_seek), so it does not change
performance. When the server disconnects, I think it triggers http_err and
then quits out of grub_net_poll_cards early.

---
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
index 5aa4ad3..a5d64f6 100644
--- a/grub-core/net/http.c
+++ b/grub-core/net/http.c
@@ -318,6 +318,7 @@ http_establish (struct grub_file *file, grub_off_t
offset, int initial)
    + grub_strlen (data->filename)
    + sizeof (" HTTP/1.1\r\nHost: ") - 1
    + grub_strlen (file->device->net->server)
+   + sizeof ("\r\nConnection: close") - 1
    + sizeof ("\r\nUser-Agent: " PACKAGE_STRING
      "\r\n") - 1
    + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX"
@@ -366,6 +367,17 @@ http_establish (struct grub_file *file, grub_off_t
offset, int initial)
        grub_strlen (file->device->net->server));

   ptr = nb->tail;
+  err = grub_netbuff_put (nb,
+  sizeof ("\r\nConnection: close")
+  - 1);
+  if (err)
+    {
+      grub_netbuff_free (nb);
+      return err;
+    }
+  grub_memcpy (ptr, "\r\nConnection: close",
+       sizeof ("\r\nConnection: close") - 1);
+  ptr = nb->tail;
   err = grub_netbuff_put (nb,
   sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n")
   - 1);

[-- Attachment #2: Type: text/html, Size: 3747 bytes --]

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: Patch: Improve HTTP time by sending Connection:close
  2016-11-12 17:26 Patch: Improve HTTP time by sending Connection:close Walter Huf
@ 2016-11-15 13:21 ` Daniel Kiper
  2016-11-15 14:30   ` Andrei Borzenkov
  0 siblings, 1 reply; 8+ messages in thread
From: Daniel Kiper @ 2016-11-15 13:21 UTC (permalink / raw)
  To: hufman, grub-devel

On Sat, Nov 12, 2016 at 09:26:17AM -0800, Walter Huf wrote:
> GRUB's HTTP module declares support for HTTP/1.1, which defaults to
> Connection:keepalive. At the end of the content, the server holds the TCP
> connection open waiting for the next request.
> It seems that grub_net_poll_cards() is watching for the HTTP module to set

Do you have a feeling or are you sure? I think that we have to be sure here.

> net->stall, and otherwise waits the full 400ms GRUB_NET_INTERVAL to return
> to processing. However, HTTP module only sets that flag in specific
> conditions:
>
>    - parse_line detects that we are at the end of downloading a chunked
>    Transfer-Encoding
>    - http_err detects a problem with the underlying TCP connection
>    - http_receive has queued 20 netbuffer packets for processing
>
> If the file is small and takes less than 20 packets, and the server is not
> using chunked encoding, grub_net_poll_cards() will wait the full 400ms
> before continuing to process and finish the file download.
>
> This patch sets Connection:close, which will tell the server to close the
> connection as soon as it has finished sending the file. GRUB closes any
> connections that are left open (in http_seek), so it does not change

Why in http_seek? Is it correct or not?

> performance. When the server disconnects, I think it triggers http_err and

"I think" is too soft. You have to be sure here.

> then quits out of grub_net_poll_cards early.

Lack of SOB.

Have you tested this patch with large/huge number of files to transfer? I have
a feeling that it can slowdown whole transfer in such cases due to number of
connects/disconnects. Maybe this feature should be conditional thing.

Daniel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: Improve HTTP time by sending Connection:close
  2016-11-15 13:21 ` Daniel Kiper
@ 2016-11-15 14:30   ` Andrei Borzenkov
  2016-11-15 20:44     ` Daniel Kiper
  0 siblings, 1 reply; 8+ messages in thread
From: Andrei Borzenkov @ 2016-11-15 14:30 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: hufman

On Tue, Nov 15, 2016 at 4:21 PM, Daniel Kiper <dkiper@net-space.pl> wrote:
> On Sat, Nov 12, 2016 at 09:26:17AM -0800, Walter Huf wrote:
>> GRUB's HTTP module declares support for HTTP/1.1, which defaults to
>> Connection:keepalive. At the end of the content, the server holds the TCP
>> connection open waiting for the next request.
>> It seems that grub_net_poll_cards() is watching for the HTTP module to set
>
> Do you have a feeling or are you sure? I think that we have to be sure here.
>

See http://savannah.gnu.org/bugs/?49531 which has more details.

>> net->stall, and otherwise waits the full 400ms GRUB_NET_INTERVAL to return
>> to processing. However, HTTP module only sets that flag in specific
>> conditions:
>>
>>    - parse_line detects that we are at the end of downloading a chunked
>>    Transfer-Encoding
>>    - http_err detects a problem with the underlying TCP connection
>>    - http_receive has queued 20 netbuffer packets for processing
>>
>> If the file is small and takes less than 20 packets, and the server is not
>> using chunked encoding, grub_net_poll_cards() will wait the full 400ms
>> before continuing to process and finish the file download.
>>
>> This patch sets Connection:close, which will tell the server to close the
>> connection as soon as it has finished sending the file. GRUB closes any
>> connections that are left open (in http_seek), so it does not change
>
> Why in http_seek? Is it correct or not?
>
>> performance. When the server disconnects, I think it triggers http_err and
>
> "I think" is too soft. You have to be sure here.
>
>> then quits out of grub_net_poll_cards early.
>
> Lack of SOB.
>

I must have missed it. Is it now required?

> Have you tested this patch with large/huge number of files to transfer? I have
> a feeling that it can slowdown whole transfer in such cases due to number of
> connects/disconnects. Maybe this feature should be conditional thing.
>

Currently grub will always establish new connection in http_open ->
http_establish, so it should not change anything from grub PoV, but
reduce amount of lingering connections on server. But I would really
like to explore another patch in above bug report - gracefully close
connection when we finished receive data. That said, this one does not
hurt as long as we do not reuse existing connection.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: Improve HTTP time by sending Connection:close
  2016-11-15 14:30   ` Andrei Borzenkov
@ 2016-11-15 20:44     ` Daniel Kiper
  2016-11-15 21:43       ` Walter Huf
  0 siblings, 1 reply; 8+ messages in thread
From: Daniel Kiper @ 2016-11-15 20:44 UTC (permalink / raw)
  To: arvidjaar, hufman, grub-devel

On Tue, Nov 15, 2016 at 05:30:28PM +0300, Andrei Borzenkov wrote:
> On Tue, Nov 15, 2016 at 4:21 PM, Daniel Kiper <dkiper@net-space.pl> wrote:
> > On Sat, Nov 12, 2016 at 09:26:17AM -0800, Walter Huf wrote:
> >> GRUB's HTTP module declares support for HTTP/1.1, which defaults to
> >> Connection:keepalive. At the end of the content, the server holds the TCP
> >> connection open waiting for the next request.
> >> It seems that grub_net_poll_cards() is watching for the HTTP module to set
> >
> > Do you have a feeling or are you sure? I think that we have to be sure here.
> >
>
> See http://savannah.gnu.org/bugs/?49531 which has more details.

OK but I think that this should be a part of commit meesage.

> >> net->stall, and otherwise waits the full 400ms GRUB_NET_INTERVAL to return
> >> to processing. However, HTTP module only sets that flag in specific
> >> conditions:
> >>
> >>    - parse_line detects that we are at the end of downloading a chunked
> >>    Transfer-Encoding
> >>    - http_err detects a problem with the underlying TCP connection
> >>    - http_receive has queued 20 netbuffer packets for processing
> >>
> >> If the file is small and takes less than 20 packets, and the server is not
> >> using chunked encoding, grub_net_poll_cards() will wait the full 400ms
> >> before continuing to process and finish the file download.
> >>
> >> This patch sets Connection:close, which will tell the server to close the
> >> connection as soon as it has finished sending the file. GRUB closes any
> >> connections that are left open (in http_seek), so it does not change
> >
> > Why in http_seek? Is it correct or not?
> >
> >> performance. When the server disconnects, I think it triggers http_err and
> >
> > "I think" is too soft. You have to be sure here.
> >
> >> then quits out of grub_net_poll_cards early.
> >
> > Lack of SOB.
> >
>
> I must have missed it. Is it now required?

No (probably it should be sooner or later but we have to discuss this
issue separetly), however, nice to have.

> > Have you tested this patch with large/huge number of files to transfer? I have
> > a feeling that it can slowdown whole transfer in such cases due to number of
> > connects/disconnects. Maybe this feature should be conditional thing.
> >
>
> Currently grub will always establish new connection in http_open ->
> http_establish, so it should not change anything from grub PoV, but
> reduce amount of lingering connections on server. But I would really
> like to explore another patch in above bug report - gracefully close
> connection when we finished receive data. That said, this one does not

Looking (shortly) at problem description I am not sure that it will fix
the issue. Though I am not convinced that we should play with keep alive
too. Hence, better/nicer solution is appreciated.

Daniel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: Improve HTTP time by sending Connection:close
  2016-11-15 20:44     ` Daniel Kiper
@ 2016-11-15 21:43       ` Walter Huf
  2016-11-16  3:20         ` Andrei Borzenkov
  2016-11-17 18:32         ` Daniel Kiper
  0 siblings, 2 replies; 8+ messages in thread
From: Walter Huf @ 2016-11-15 21:43 UTC (permalink / raw)
  To: grub-devel; +Cc: arvidjaar, Daniel Kiper

[-- Attachment #1: Type: text/plain, Size: 5059 bytes --]

GRUB has a bug where it waits a minimum of 400ms for every file it fetches
over HTTP, unless the server serves it with Transfer-Encoding:chunked or
the file just happens to be split into 20 TCP packets. When using
pxeboot.img built with just pxe and http module (following instructions
from https://www.gnu.org/software/grub/manual/html_node/Network.html), this
causes an initial text menu to take about 7 seconds to load with all the
modules being dynamically fetched.
The SOB (statement of benefit?) of this patch is to fix this bug with the
smallest change to existing data structures and logic.
GRUB specifically checks for existing connections that are attached to file
objects when seeking and closes them. New file requests don't have any
sockets attached, and so it always opens a new connection to fetch new
files. Adding the Connection:close header does not reduce performance.

The alternate patch on that bug ticket is a larger change, involving
changing a (module-internal) data structure. I was also less sure of the
flow of logic in http_receive(), so I did not immediately suggest it. It
seems that the GRUB project is understandably conservative about changes,
so I first provided the change that would have the smallest side-effect.

I couched my phrasing with "I believe" and "I think" because I am not sure
if I've fully understood the 3000+ lines of undocumented C code in net.c,
netbuff.c, http.c, and tcp.c in only one week. I submitted this bug to
bring a performance problem to your attention, and included a possible
patch that fixes it for me, in the hope that someone on the project who is
familiar with this code can review it and offer feedback.

If the suggestion is to instead implement a more complete implementation of
Connection:keepalive, I can try that out and offer a rough patch to improve
that. As a newcomer to this project, I would feel more comfortable
contributing a small change to fix the problem immediately instead of a
large possibly-breaking change.

Thank you!

On Tue, Nov 15, 2016 at 12:44 PM, Daniel Kiper <dkiper@net-space.pl> wrote:

> On Tue, Nov 15, 2016 at 05:30:28PM +0300, Andrei Borzenkov wrote:
> > On Tue, Nov 15, 2016 at 4:21 PM, Daniel Kiper <dkiper@net-space.pl>
> wrote:
> > > On Sat, Nov 12, 2016 at 09:26:17AM -0800, Walter Huf wrote:
> > >> GRUB's HTTP module declares support for HTTP/1.1, which defaults to
> > >> Connection:keepalive. At the end of the content, the server holds the
> TCP
> > >> connection open waiting for the next request.
> > >> It seems that grub_net_poll_cards() is watching for the HTTP module
> to set
> > >
> > > Do you have a feeling or are you sure? I think that we have to be sure
> here.
> > >
> >
> > See http://savannah.gnu.org/bugs/?49531 which has more details.
>
> OK but I think that this should be a part of commit meesage.
>
> > >> net->stall, and otherwise waits the full 400ms GRUB_NET_INTERVAL to
> return
> > >> to processing. However, HTTP module only sets that flag in specific
> > >> conditions:
> > >>
> > >>    - parse_line detects that we are at the end of downloading a
> chunked
> > >>    Transfer-Encoding
> > >>    - http_err detects a problem with the underlying TCP connection
> > >>    - http_receive has queued 20 netbuffer packets for processing
> > >>
> > >> If the file is small and takes less than 20 packets, and the server
> is not
> > >> using chunked encoding, grub_net_poll_cards() will wait the full 400ms
> > >> before continuing to process and finish the file download.
> > >>
> > >> This patch sets Connection:close, which will tell the server to close
> the
> > >> connection as soon as it has finished sending the file. GRUB closes
> any
> > >> connections that are left open (in http_seek), so it does not change
> > >
> > > Why in http_seek? Is it correct or not?
> > >
> > >> performance. When the server disconnects, I think it triggers
> http_err and
> > >
> > > "I think" is too soft. You have to be sure here.
> > >
> > >> then quits out of grub_net_poll_cards early.
> > >
> > > Lack of SOB.
> > >
> >
> > I must have missed it. Is it now required?
>
> No (probably it should be sooner or later but we have to discuss this
> issue separetly), however, nice to have.
>
> > > Have you tested this patch with large/huge number of files to
> transfer? I have
> > > a feeling that it can slowdown whole transfer in such cases due to
> number of
> > > connects/disconnects. Maybe this feature should be conditional thing.
> > >
> >
> > Currently grub will always establish new connection in http_open ->
> > http_establish, so it should not change anything from grub PoV, but
> > reduce amount of lingering connections on server. But I would really
> > like to explore another patch in above bug report - gracefully close
> > connection when we finished receive data. That said, this one does not
>
> Looking (shortly) at problem description I am not sure that it will fix
> the issue. Though I am not convinced that we should play with keep alive
> too. Hence, better/nicer solution is appreciated.
>
> Daniel
>

[-- Attachment #2: Type: text/html, Size: 6366 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: Improve HTTP time by sending Connection:close
  2016-11-15 21:43       ` Walter Huf
@ 2016-11-16  3:20         ` Andrei Borzenkov
  2016-11-17 18:32         ` Daniel Kiper
  1 sibling, 0 replies; 8+ messages in thread
From: Andrei Borzenkov @ 2016-11-16  3:20 UTC (permalink / raw)
  To: Walter Huf, grub-devel; +Cc: Daniel Kiper

16.11.2016 00:43, Walter Huf пишет:
> The SOB (statement of benefit?) of this patch

It is "Signed-off-by: xxx" line that are required by some projects
(first appeared in Linux kernel I think). OTOH some projects actively
reject it.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: Improve HTTP time by sending Connection:close
  2016-11-15 21:43       ` Walter Huf
  2016-11-16  3:20         ` Andrei Borzenkov
@ 2016-11-17 18:32         ` Daniel Kiper
  2016-11-17 18:41           ` Konrad Rzeszutek Wilk
  1 sibling, 1 reply; 8+ messages in thread
From: Daniel Kiper @ 2016-11-17 18:32 UTC (permalink / raw)
  To: hufman, grub-devel; +Cc: arvidjaar, Daniel Kiper

On Tue, Nov 15, 2016 at 01:43:16PM -0800, Walter Huf wrote:
> GRUB has a bug where it waits a minimum of 400ms for every file it fetches
> over HTTP, unless the server serves it with Transfer-Encoding:chunked or
> the file just happens to be split into 20 TCP packets. When using
> pxeboot.img built with just pxe and http module (following instructions
> from https://www.gnu.org/software/grub/manual/html_node/Network.html), this
> causes an initial text menu to take about 7 seconds to load with all the
> modules being dynamically fetched.

I agree that this looks like a bug.

> The SOB (statement of benefit?) of this patch is to fix this bug with the
> smallest change to existing data structures and logic.

I meant Signed-off-by: ...
In your case it should look like:

Signed-off-by: Walter Huf <hufman@gmail.com>

> GRUB specifically checks for existing connections that are attached to file
> objects when seeking and closes them. New file requests don't have any
> sockets attached, and so it always opens a new connection to fetch new
> files. Adding the Connection:close header does not reduce performance.

I am not sure that I correctly understand what is written above but it seems
to me that we have a problem with HTTP connection close. So, I think that
there are two ways to fix it:
  - if server accepts Connection:keepalive then we should use existing
    connection as long as possible and transfer all/(maximum number of?)
    files,
  - if it does not then we should close HTTP connection immediately
    after file transfer and open another one for a new transfer.

> The alternate patch on that bug ticket is a larger change, involving
> changing a (module-internal) data structure. I was also less sure of the
> flow of logic in http_receive(), so I did not immediately suggest it. It
> seems that the GRUB project is understandably conservative about changes,
> so I first provided the change that would have the smallest side-effect.

Patch size is important factor but not crucial one. First of all it
should properly fix a given bug and do not introduce regressions.

> I couched my phrasing with "I believe" and "I think" because I am not sure
> if I've fully understood the 3000+ lines of undocumented C code in net.c,
> netbuff.c, http.c, and tcp.c in only one week. I submitted this bug to

I prefer to spend more time on code/functionality analysis than provide fix which
is based on vague imagination. So, that is why I am asking for more details.

> bring a performance problem to your attention, and included a possible

Thanks for doing that!

> patch that fixes it for me, in the hope that someone on the project who is
> familiar with this code can review it and offer feedback.

I think that we are doing that right now.

> If the suggestion is to instead implement a more complete implementation of
> Connection:keepalive, I can try that out and offer a rough patch to improve

I am not convinced that we should play with Connection:keepalive.
Please look above.

> that. As a newcomer to this project, I would feel more comfortable
> contributing a small change to fix the problem immediately instead of a
> large possibly-breaking change.

As I said earlier, size of a given patch is not very important (at least for me).
It have to be correct. So, please dive into the code and understand how it works.
If you are not sure send questions to the list then somebody familiar with a given
chunk will try to explain what is going on. We are happy to help. Though you must
put some effort to provide correct patch too. Otherwise it does not work.

Daniel


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Patch: Improve HTTP time by sending Connection:close
  2016-11-17 18:32         ` Daniel Kiper
@ 2016-11-17 18:41           ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 8+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-11-17 18:41 UTC (permalink / raw)
  To: The development of GNU GRUB; +Cc: hufman, arvidjaar, Daniel Kiper

On Thu, Nov 17, 2016 at 07:32:16PM +0100, Daniel Kiper wrote:
> On Tue, Nov 15, 2016 at 01:43:16PM -0800, Walter Huf wrote:
> > GRUB has a bug where it waits a minimum of 400ms for every file it fetches
> > over HTTP, unless the server serves it with Transfer-Encoding:chunked or
> > the file just happens to be split into 20 TCP packets. When using
> > pxeboot.img built with just pxe and http module (following instructions
> > from https://www.gnu.org/software/grub/manual/html_node/Network.html), this
> > causes an initial text menu to take about 7 seconds to load with all the
> > modules being dynamically fetched.
> 
> I agree that this looks like a bug.
> 
> > The SOB (statement of benefit?) of this patch is to fix this bug with the
> > smallest change to existing data structures and logic.
> 
> I meant Signed-off-by: ...
> In your case it should look like:
> 
> Signed-off-by: Walter Huf <hufman@gmail.com>

It is not as simple as that. Putting your SoB means that you:

        Developer's Certificate of Origin 1.1

        By making a contribution to this project, I certify that:

        (a) The contribution was created in whole or in part by me and I
            have the right to submit it under the open source license
            indicated in the file; or

        (b) The contribution is based upon previous work that, to the best
            of my knowledge, is covered under an appropriate open source
            license and I have the right under that license to submit that
            work with modifications, whether created in whole or in part
            by me, under the same open source license (unless I am
            permitted to submit under a different license), as indicated
            in the file; or

        (c) The contribution was provided directly to me by some other
            person who certified (a), (b) or (c) and I have not modified
            it.

        (d) I understand and agree that this project and the contribution
            are public and that a record of the contribution (including all
            personal information I submit with it, including my sign-off) is
            maintained indefinitely and may be redistributed consistent with
            this project or the open source license(s) involved.

then you just add a line saying

	Signed-off-by: Random J Developer <random@developer.example.org>



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2016-11-17 18:42 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-12 17:26 Patch: Improve HTTP time by sending Connection:close Walter Huf
2016-11-15 13:21 ` Daniel Kiper
2016-11-15 14:30   ` Andrei Borzenkov
2016-11-15 20:44     ` Daniel Kiper
2016-11-15 21:43       ` Walter Huf
2016-11-16  3:20         ` Andrei Borzenkov
2016-11-17 18:32         ` Daniel Kiper
2016-11-17 18:41           ` Konrad Rzeszutek Wilk

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.