From d8ff0336a5a34bbf418b337e15d19ad426184c5e Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 3 Jan 2007 22:18:38 +0000 Subject: - Matt Witherspoon fixed the flaw which made libcurl 7.16.0 always store downloaded data in two buffers, just to be able to deal with a special HTTP pipelining case. That is now only activated for pipelined transfers. In Matt's case, it showed as a considerable performance difference, --- CHANGES | 6 ++++++ RELEASE-NOTES | 1 + lib/sendf.c | 59 +++++++++++++++++++++++++++++++++++++---------------------- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/CHANGES b/CHANGES index 4e58026ba..d46ed330a 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,12 @@ Changelog +Daniel (3 January 2007) +- Matt Witherspoon fixed the flaw which made libcurl 7.16.0 always store + downloaded data in two buffers, just to be able to deal with a special HTTP + pipelining case. That is now only activated for pipelined transfers. In + Matt's case, it showed as a considerable performance difference, + Daniel (2 January 2007) - Victor Snezhko helped us fix bug report #1603712 (http://curl.haxx.se/bug/view.cgi?id=1603712) (known bug #36) --limit-rate diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 33fee2089..6ff132e7d 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -45,6 +45,7 @@ This release includes the following bugfixes: o libcurl.pc now uses Libs.private for "private" libs o --limit-rate (CURLOPT_MAX_SEND_SPEED_LARGE and CURLOPT_MAX_RECV_SPEED_LARGE) now work on windows again + o improved download performance by avoiding the unconditional "double copying" Other curl-related news: diff --git a/lib/sendf.c b/lib/sendf.c index 7d203879f..d0688ec21 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2006, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -46,6 +46,7 @@ #include "connect.h" /* for the Curl_sockerrno() proto */ #include "sslgen.h" #include "ssh.h" +#include "multiif.h" #define _MPRINTF_REPLACE /* use the internal *printf() functions */ #include @@ -453,7 +454,7 @@ CURLcode Curl_client_write(struct connectdata *conn, return CURLE_OK; } -#define MIN(a,b) (a < b ? a : b) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) /* * Internal read-from-socket function. This is meant to deal with plain @@ -469,8 +470,10 @@ int Curl_read(struct connectdata *conn, /* connection data */ ssize_t *n) /* amount bytes read */ { ssize_t nread; - size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested); size_t bytesfromsocket = 0; + char *buffertofill = NULL; + bool pipelining = (conn->data->multi && + Curl_multi_canPipeline(conn->data->multi)); /* Set 'num' to 0 or 1, depending on which socket that has been sent here. If it is the second socket, we set num to 1. Otherwise to 0. This lets @@ -479,22 +482,32 @@ int Curl_read(struct connectdata *conn, /* connection data */ *n=0; /* reset amount to zero */ - /* Copy from our master buffer first if we have some unread data there*/ - if (bytestocopy > 0) { - memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy); - conn->read_pos += bytestocopy; - conn->bits.stream_was_rewound = FALSE; + /* If session can pipeline, check connection buffer */ + if(pipelining) { + size_t bytestocopy = MIN(conn->buf_len - conn->read_pos, sizerequested); - *n = (ssize_t)bytestocopy; - return CURLE_OK; - } + /* Copy from our master buffer first if we have some unread data there*/ + if (bytestocopy > 0) { + memcpy(buf, conn->master_buffer + conn->read_pos, bytestocopy); + conn->read_pos += bytestocopy; + conn->bits.stream_was_rewound = FALSE; - /* If we come here, it means that there is no data to read from the buffer, - * so we read from the socket */ - bytesfromsocket = MIN(sizerequested, sizeof(conn->master_buffer)); + *n = (ssize_t)bytestocopy; + return CURLE_OK; + } + /* If we come here, it means that there is no data to read from the buffer, + * so we read from the socket */ + bytesfromsocket = MIN(sizerequested, sizeof(conn->master_buffer)); + buffertofill = conn->master_buffer; + } + else { + bytesfromsocket = MIN((long)sizerequested, conn->data->set.buffer_size ? + conn->data->set.buffer_size : BUFSIZE); + buffertofill = buf; + } if(conn->ssl[num].use) { - nread = Curl_ssl_recv(conn, num, conn->master_buffer, bytesfromsocket); + nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket); if(nread == -1) { return -1; /* -1 from Curl_ssl_recv() means EWOULDBLOCK */ @@ -502,20 +515,20 @@ int Curl_read(struct connectdata *conn, /* connection data */ } #ifdef USE_LIBSSH2 else if (conn->protocol & PROT_SCP) { - nread = Curl_scp_recv(conn, num, conn->master_buffer, bytesfromsocket); + nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket); /* TODO: return CURLE_OK also for nread <= 0 read failures and timeouts ? */ } else if (conn->protocol & PROT_SFTP) { - nread = Curl_sftp_recv(conn, num, conn->master_buffer, bytesfromsocket); + nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket); } #endif /* !USE_LIBSSH2 */ else { if(conn->sec_complete) - nread = Curl_sec_read(conn, sockfd, conn->master_buffer, + nread = Curl_sec_read(conn, sockfd, buffertofill, bytesfromsocket); else - nread = sread(sockfd, conn->master_buffer, bytesfromsocket); + nread = sread(sockfd, buffertofill, bytesfromsocket); if(-1 == nread) { int err = Curl_sockerrno(); @@ -529,10 +542,12 @@ int Curl_read(struct connectdata *conn, /* connection data */ } if (nread >= 0) { - memcpy(buf, conn->master_buffer, nread); + if(pipelining) { + memcpy(buf, conn->master_buffer, nread); + conn->buf_len = nread; + conn->read_pos = nread; + } - conn->buf_len = nread; - conn->read_pos = nread; *n = nread; } -- cgit v1.2.3