Skip to content
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

Merged
merged 1 commit into from
May 22, 2024

Conversation

SergeyRyabinin
Copy link
Contributor

@SergeyRyabinin SergeyRyabinin commented May 10, 2024

Issue #, if available:

Unlike in lib curl,

WinHTTP expects a pointer + size to where Windows is going to write us a reply:

WINHTTPAPI BOOL WinHttpReadData(
  [in]  HINTERNET hRequest,
  [out] LPVOID    lpBuffer,
  [in]  DWORD     dwNumberOfBytesToRead,
  [out] LPDWORD   lpdwNumberOfBytesRead
);

https://learn.microsoft.com/en-us/windows/win32/api/winhttp/nf-winhttp-winhttpreaddata
while C++'s iostream (it the central point of requests/response handling in the SDK from the initial design) manipulates C++'s streams:

// inserts blocks of characters 
basic_ostream& write( const char_type* s, std::streamsize count );

https://en.cppreference.com/w/cpp/io/basic_iostream
and can't provide raw pre-allocated buffer that WinHTTP wants.

Should WinHTTP provide std::iostream interface - this would not be an issue.

Description of changes:

Create a hack-y class to access raw pointers of the underlying buffer of the streambuffer to perform writes directly to the pptr pointer.

Check all that applies:

  • Did a review by yourself.
  • Added proper tests to cover this PR. (If tests are not applicable, explain.)
  • Checked if this PR is a breaking (APIs have been changed) change.
  • Checked if this PR will not introduce cross-platform inconsistent behavior.
  • Checked if this PR would require a ReadMe/Wiki update.

Check which platforms you have built SDK on to verify the correctness of this PR.

  • Linux
  • Windows
  • Android
  • MacOS
  • IOS
  • Other Platforms

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

}

read = 0;
while (writerFunc(dstBegin, dstSz, read) && read > 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of having two while loops they seem to have similar bodies, seems like we could use a do while here to avoid dry

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are 1 while loop. While it is a bit ugly to have similar conditions, it looks to have a bit more clear logic.

@SergeyRyabinin SergeyRyabinin force-pushed the sr/winHttpReplyPerf branch 2 times, most recently from 410b24d to 814f1a3 Compare May 13, 2024 21:50
@SergeyRyabinin SergeyRyabinin changed the title Avoid excessive reply buffer copy in WinHTTP using a hack Avoid excessive reply buffer copy in WinHTTP May 13, 2024
@SergeyRyabinin SergeyRyabinin marked this pull request as ready for review May 13, 2024 21:52
@SergeyRyabinin SergeyRyabinin force-pushed the sr/winHttpReplyPerf branch 9 times, most recently from 7c3111d to 8c472e1 Compare May 16, 2024 00:04
}
}
}
return totalRead;
Copy link
Contributor

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?

Copy link
Contributor

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 invariant

Copy link
Contributor Author

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

@SergeyRyabinin SergeyRyabinin force-pushed the sr/winHttpReplyPerf branch 2 times, most recently from 911c421 to 7e5292b Compare May 21, 2024 23:24
}
}
}
return totalRead;
Copy link
Contributor

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 invariant

if (ioStream.fail()) {
AWS_LOGSTREAM_ERROR("StreamBufProtectedWriter", "Failed to write 1 byte (eof: "
<< ioStream.eof() << ", bad: " << ioStream.bad() << ")");
return 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

np: please return false/true instead of int

@@ -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" ))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NICE!

return false;
}

static uint64_t WriteWithHelperBuffer(Aws::IOStream& ioStream, const WriterFunc& writerFunc, uint64_t& read)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the return type should be bool

return false;
}

static uint64_t WriteDirectlyToPtr(StreamBufProtectedWriter* pBuffer, const WriterFunc& writerFunc, uint64_t& read)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: the return type should be bool

{
ioStream.write(tmpBuf, read);
if (ioStream.fail()) {
AWS_LOGSTREAM_ERROR("StreamBufProtectedWriter", "Failed to write " << tmpBufSz
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: shouldn't it be "Failed to write " << read?

@SergeyRyabinin SergeyRyabinin merged commit 0ac4224 into main May 22, 2024
3 of 4 checks passed
@SergeyRyabinin SergeyRyabinin deleted the sr/winHttpReplyPerf branch May 22, 2024 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants