Set wxWebResponseCURL buffer size as soon as known

Currently for wxWebRequestCURL objects using memory storage, a download
is processed by appending to a wxMemoryBuffer each time the write
callback is called. For a large transfer, this can result in many, many
reallocation calls and can block the main application.

This commit uses the progress callback for wxWebRequestCURL objects
added in a previous commit to set a minimum size for the buffer as soon
as it is known.
This commit is contained in:
New Pagodi
2021-02-07 20:43:51 -06:00
parent 3e5fd5462d
commit 48cba4f88e
4 changed files with 25 additions and 4 deletions

View File

@@ -187,6 +187,10 @@ protected:
void ReportDataReceived(size_t sizeReceived); void ReportDataReceived(size_t sizeReceived);
// This function can optionally be called to preallocate the read buffer,
// if the total amount of data to be downloaded is known in advance.
void PreAllocBuffer(size_t sizeNeeded);
private: private:
// Called by wxWebRequestImpl only. // Called by wxWebRequestImpl only.
friend class wxWebRequestImpl; friend class wxWebRequestImpl;

View File

@@ -114,11 +114,12 @@ public:
// Methods called from libcurl callbacks // Methods called from libcurl callbacks
size_t CURLOnWrite(void *buffer, size_t size); size_t CURLOnWrite(void *buffer, size_t size);
size_t CURLOnHeader(const char* buffer, size_t size); size_t CURLOnHeader(const char* buffer, size_t size);
int CURLOnProgress(); int CURLOnProgress(curl_off_t);
private: private:
wxWebRequestHeaderMap m_headers; wxWebRequestHeaderMap m_headers;
wxString m_statusText; wxString m_statusText;
wxFileOffset m_knownDownloadSize;
CURL* GetHandle() const CURL* GetHandle() const
{ return static_cast<wxWebRequestCURL&>(m_request).GetHandle(); } { return static_cast<wxWebRequestCURL&>(m_request).GetHandle(); }

View File

@@ -688,6 +688,11 @@ void* wxWebResponseImpl::GetDataBuffer(size_t sizeNeeded)
return m_readBuffer.GetAppendBuf(sizeNeeded); return m_readBuffer.GetAppendBuf(sizeNeeded);
} }
void wxWebResponseImpl::PreAllocBuffer(size_t sizeNeeded)
{
m_readBuffer.SetBufSize(sizeNeeded);
}
void wxWebResponseImpl::ReportDataReceived(size_t sizeReceived) void wxWebResponseImpl::ReportDataReceived(size_t sizeReceived)
{ {
m_readBuffer.UngetAppendBuf(sizeReceived); m_readBuffer.UngetAppendBuf(sizeReceived);

View File

@@ -67,7 +67,7 @@ static size_t wxCURLHeader(char *buffer, size_t size, size_t nitems, void *userd
return static_cast<wxWebResponseCURL*>(userdata)->CURLOnHeader(buffer, size * nitems); return static_cast<wxWebResponseCURL*>(userdata)->CURLOnHeader(buffer, size * nitems);
} }
int wxCURLXferInfo(void* clientp, curl_off_t WXUNUSED(dltotal), int wxCURLXferInfo(void* clientp, curl_off_t dltotal,
curl_off_t WXUNUSED(dlnow), curl_off_t WXUNUSED(dlnow),
curl_off_t WXUNUSED(ultotal), curl_off_t WXUNUSED(ultotal),
curl_off_t WXUNUSED(ulnow)) curl_off_t WXUNUSED(ulnow))
@@ -75,7 +75,7 @@ int wxCURLXferInfo(void* clientp, curl_off_t WXUNUSED(dltotal),
wxCHECK_MSG( clientp, 0, "invalid curl progress callback data" ); wxCHECK_MSG( clientp, 0, "invalid curl progress callback data" );
wxWebResponseCURL* response = reinterpret_cast<wxWebResponseCURL*>(clientp); wxWebResponseCURL* response = reinterpret_cast<wxWebResponseCURL*>(clientp);
return response->CURLOnProgress(); return response->CURLOnProgress(dltotal);
} }
int wxCURLProgress(void* clientp, double dltotal, double dlnow, double ultotal, int wxCURLProgress(void* clientp, double dltotal, double dlnow, double ultotal,
@@ -90,6 +90,8 @@ int wxCURLProgress(void* clientp, double dltotal, double dlnow, double ultotal,
wxWebResponseCURL::wxWebResponseCURL(wxWebRequestCURL& request) : wxWebResponseCURL::wxWebResponseCURL(wxWebRequestCURL& request) :
wxWebResponseImpl(request) wxWebResponseImpl(request)
{ {
m_knownDownloadSize = 0;
curl_easy_setopt(GetHandle(), CURLOPT_WRITEDATA, static_cast<void*>(this)); curl_easy_setopt(GetHandle(), CURLOPT_WRITEDATA, static_cast<void*>(this));
curl_easy_setopt(GetHandle(), CURLOPT_HEADERDATA, static_cast<void*>(this)); curl_easy_setopt(GetHandle(), CURLOPT_HEADERDATA, static_cast<void*>(this));
@@ -152,8 +154,17 @@ size_t wxWebResponseCURL::CURLOnHeader(const char * buffer, size_t size)
return size; return size;
} }
int wxWebResponseCURL::CURLOnProgress() int wxWebResponseCURL::CURLOnProgress(curl_off_t total)
{ {
if ( m_knownDownloadSize != total )
{
if ( m_request.GetStorage() == wxWebRequest::Storage_Memory )
{
PreAllocBuffer(static_cast<size_t>(total));
}
m_knownDownloadSize = total;
}
return 0; return 0;
} }