-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid excessive reply buffer copy in WinHTTP #2954
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
|
||
/** | ||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <aws/core/Core_EXPORTS.h> | ||
#include <aws/core/utils/Array.h> | ||
#include <streambuf> | ||
#include <functional> | ||
|
||
namespace Aws | ||
{ | ||
namespace Utils | ||
{ | ||
namespace Stream | ||
{ | ||
/** | ||
* This is a wrapper to perform a hack to write directly to the put area of the underlying streambuf | ||
*/ | ||
class AWS_CORE_API StreamBufProtectedWriter : public std::streambuf | ||
{ | ||
public: | ||
StreamBufProtectedWriter() = delete; | ||
|
||
using WriterFunc = std::function<bool(char* dst, uint64_t dstSz, uint64_t& read)>; | ||
|
||
static uint64_t WriteToBuffer(Aws::IOStream& ioStream, const WriterFunc& writerFunc) | ||
{ | ||
uint64_t totalRead = 0; | ||
|
||
while (true) | ||
{ | ||
StreamBufProtectedWriter* pBufferCasted = static_cast<StreamBufProtectedWriter*>(ioStream.rdbuf()); | ||
bool bufferPresent = pBufferCasted && pBufferCasted->pptr() && (pBufferCasted->pptr() < pBufferCasted->epptr()); | ||
uint64_t read = 0; | ||
bool success = false; | ||
if (bufferPresent) | ||
{ | ||
// have access to underlying put ptr. | ||
success = WriteDirectlyToPtr(pBufferCasted, writerFunc, read); | ||
} | ||
else | ||
{ | ||
// can't access underlying buffer, stream buffer maybe be customized to not use put ptr. | ||
// or underlying put buffer is simply not initialized yet. | ||
success = WriteWithHelperBuffer(ioStream, writerFunc, read); | ||
} | ||
totalRead += read; | ||
if (!success) | ||
{ | ||
break; | ||
} | ||
|
||
if (pBufferCasted && pBufferCasted->pptr() && (pBufferCasted->pptr() >= pBufferCasted->epptr())) | ||
{ | ||
if(!ForceOverflow(ioStream, writerFunc)) | ||
{ | ||
break; | ||
} else { | ||
totalRead++; | ||
} | ||
} | ||
} | ||
return totalRead; | ||
} | ||
protected: | ||
static bool ForceOverflow(Aws::IOStream& ioStream, const WriterFunc& writerFunc) | ||
{ | ||
char dstChar; | ||
uint64_t read = 0; | ||
if (writerFunc(&dstChar, 1, read) && read > 0) | ||
{ | ||
ioStream.write(&dstChar, 1); | ||
if (ioStream.fail()) { | ||
AWS_LOGSTREAM_ERROR("StreamBufProtectedWriter", "Failed to write 1 byte (eof: " | ||
<< ioStream.eof() << ", bad: " << ioStream.bad() << ")"); | ||
return false; | ||
} | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
static uint64_t WriteWithHelperBuffer(Aws::IOStream& ioStream, const WriterFunc& writerFunc, uint64_t& read) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: the return type should be |
||
{ | ||
char tmpBuf[1024]; | ||
uint64_t tmpBufSz = sizeof(tmpBuf); | ||
|
||
if(writerFunc(tmpBuf, tmpBufSz, read) && read > 0) | ||
{ | ||
ioStream.write(tmpBuf, read); | ||
if (ioStream.fail()) { | ||
AWS_LOGSTREAM_ERROR("StreamBufProtectedWriter", "Failed to write " << tmpBufSz | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: shouldn't it be |
||
<< " (eof: " << ioStream.eof() << ", bad: " << ioStream.bad() << ")"); | ||
return false; | ||
} | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
static uint64_t WriteDirectlyToPtr(StreamBufProtectedWriter* pBuffer, const WriterFunc& writerFunc, uint64_t& read) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: the return type should be bool |
||
{ | ||
auto dstBegin = pBuffer->pptr(); | ||
uint64_t dstSz = pBuffer->epptr() - dstBegin; | ||
if(writerFunc(dstBegin, dstSz, read) && read > 0) | ||
{ | ||
assert(read <= dstSz); | ||
pBuffer->pbump((int) read); | ||
return true; | ||
} | ||
return false; | ||
} | ||
}; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,13 @@ | |
#include <metric/CloudWatchMetrics.h> | ||
|
||
int main(int argc, char *argv[]) { | ||
if (1 == argc || | ||
2 == argc && (std::string(argv[1]) == "-h" || std::string(argv[1]) == "--help" )) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NICE! |
||
{ | ||
Benchmark::Configuration::PrintHelp(); | ||
return 0; | ||
} | ||
|
||
Aws::SDKOptions options; | ||
Aws::InitAPI(options); | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
under what conditions are you getting to this line? only way out of while is to return. is this expected or while is missing a break somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as dimitry also if the line is "unreachable in theory but we need to return something" we should assert use
AWS_UNREACHABLE
as a invariantThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to break + proper return