Skip to content

Commit

Permalink
Rework how filled buffers are returned, so that 1M scatter-gather lis…
Browse files Browse the repository at this point in the history
…ts scale well.
  • Loading branch information
ned14 committed May 24, 2019
1 parent d9720b3 commit 19115c0
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 78 deletions.
6 changes: 3 additions & 3 deletions include/llfio/revision.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
#define LLFIO_PREVIOUS_COMMIT_REF 80a4ec68793e072adaf7619bef8b97542926d452
#define LLFIO_PREVIOUS_COMMIT_DATE "2019-05-16 08:54:43 +00:00"
#define LLFIO_PREVIOUS_COMMIT_UNIQUE 80a4ec68
#define LLFIO_PREVIOUS_COMMIT_REF d9720b3670a8d481f202842d973f82b360a467e3
#define LLFIO_PREVIOUS_COMMIT_DATE "2019-05-24 19:26:26 +00:00"
#define LLFIO_PREVIOUS_COMMIT_UNIQUE d9720b36
26 changes: 11 additions & 15 deletions include/llfio/v2.0/detail/impl/posix/io_handle.ipp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* A handle to something
(C) 2015-2017 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
(C) 2015-2019 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
File Created: Dec 2015
Expand Down Expand Up @@ -111,20 +111,18 @@ io_handle::io_result<io_handle::buffers_type> io_handle::read(io_handle::io_requ
{
return posix_error();
}
for(auto &buffer : reqs.buffers)
for(size_t i = 0; i < reqs.buffers.size(); i++)
{
auto &buffer = reqs.buffers[i];
if(buffer.size() >= static_cast<size_t>(bytesread))
{
bytesread -= buffer.size();
}
else if(bytesread > 0)
{
buffer = {buffer.data(), (size_type) bytesread};
bytesread = 0;
}
else
{
buffer = {buffer.data(), 0};
buffer = {buffer.data(), (size_type) bytesread};
reqs.buffers = {reqs.buffers.data(), i + 1};
break;
}
}
return {reqs.buffers};
Expand Down Expand Up @@ -177,20 +175,18 @@ io_handle::io_result<io_handle::const_buffers_type> io_handle::write(io_handle::
{
return posix_error();
}
for(auto &buffer : reqs.buffers)
for(size_t i = 0; i < reqs.buffers.size(); i++)
{
auto &buffer = reqs.buffers[i];
if(buffer.size() >= static_cast<size_t>(byteswritten))
{
byteswritten -= buffer.size();
}
else if(byteswritten > 0)
{
buffer = {buffer.data(), (size_type) byteswritten};
byteswritten = 0;
}
else
{
buffer = {buffer.data(), 0};
buffer = {buffer.data(), (size_type) byteswritten};
reqs.buffers = {reqs.buffers.data(), i + 1};
break;
}
}
return {reqs.buffers};
Expand Down
42 changes: 19 additions & 23 deletions include/llfio/v2.0/detail/impl/posix/map_handle.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -567,22 +567,18 @@ map_handle::io_result<map_handle::buffers_type> map_handle::read(io_request<buff
LLFIO_LOG_FUNCTION_CALL(this);
byte *addr = _addr + reqs.offset;
size_type togo = reqs.offset < _length ? static_cast<size_type>(_length - reqs.offset) : 0;
for(buffer_type &req : reqs.buffers)
for(size_t i = 0; i < reqs.buffers.size(); i++)
{
if(togo != 0u)
buffer_type &req = reqs.buffers[i];
req = {addr, req.size()};
if(req.size() > togo)
{
req = {addr, req.size()};
if(req.size() > togo)
{
req = {req.data(), togo};
}
addr += req.size();
togo -= req.size();
}
else
{
req = {req.data(), 0};
req = {req.data(), togo};
reqs.buffers = {reqs.buffers.data(), i + 1};
break;
}
addr += req.size();
togo -= req.size();
}
return reqs.buffers;
}
Expand All @@ -594,23 +590,23 @@ map_handle::io_result<map_handle::const_buffers_type> map_handle::write(io_reque
size_type togo = reqs.offset < _length ? static_cast<size_type>(_length - reqs.offset) : 0;
if(QUICKCPPLIB_NAMESPACE::signal_guard::signal_guard(QUICKCPPLIB_NAMESPACE::signal_guard::signalc::undefined_memory_access,
[&] {
for(const_buffer_type &req : reqs.buffers)
for(size_t i = 0; i < reqs.buffers.size(); i++)
{
if(togo != 0u)
const_buffer_type &req = reqs.buffers[i];
if(req.size() > togo)
{
memcpy(addr, req.data(), togo);
req = {addr, togo};
reqs.buffers = {reqs.buffers.data(), i + 1};
return false;
}
else
{
if(req.size() > togo)
{
req = {req.data(), togo};
}
memcpy(addr, req.data(), req.size());
req = {addr, req.size()};
addr += req.size();
togo -= req.size();
}
else
{
req = {req.data(), 0};
}
}
return false;
},
Expand Down
2 changes: 1 addition & 1 deletion include/llfio/v2.0/detail/impl/windows/io_handle.ipp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* A handle to something
(C) 2015-2017 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
(C) 2015-2019 Niall Douglas <http://www.nedproductions.biz/> (11 commits)
File Created: Dec 2015
Expand Down
42 changes: 19 additions & 23 deletions include/llfio/v2.0/detail/impl/windows/map_handle.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -896,22 +896,18 @@ map_handle::io_result<map_handle::buffers_type> map_handle::read(io_request<buff
LLFIO_LOG_FUNCTION_CALL(this);
byte *addr = _addr + reqs.offset;
size_type togo = reqs.offset < _length ? static_cast<size_type>(_length - reqs.offset) : 0;
for(buffer_type &req : reqs.buffers)
for(size_t i = 0; i < reqs.buffers.size(); i++)
{
if(togo != 0u)
buffer_type &req = reqs.buffers[i];
req = {addr, req.size()};
if(req.size() > togo)
{
req = {addr, req.size()};
if(req.size() > togo)
{
req = {req.data(), togo};
}
addr += req.size();
togo -= req.size();
}
else
{
req = {req.data(), 0};
req = {req.data(), togo};
reqs.buffers = {reqs.buffers.data(), i + 1};
break;
}
addr += req.size();
togo -= req.size();
}
return reqs.buffers;
}
Expand All @@ -923,23 +919,23 @@ map_handle::io_result<map_handle::const_buffers_type> map_handle::write(io_reque
size_type togo = reqs.offset < _length ? static_cast<size_type>(_length - reqs.offset) : 0;
if(QUICKCPPLIB_NAMESPACE::signal_guard::signal_guard(QUICKCPPLIB_NAMESPACE::signal_guard::signalc::undefined_memory_access,
[&] {
for(const_buffer_type &req : reqs.buffers)
for(size_t i = 0; i < reqs.buffers.size(); i++)
{
if(togo != 0u)
const_buffer_type &req = reqs.buffers[i];
if(req.size() > togo)
{
memcpy(addr, req.data(), togo);
req = {addr, togo};
reqs.buffers = {reqs.buffers.data(), i + 1};
return false;
}
else
{
if(req.size() > togo)
{
req = {req.data(), togo};
}
memcpy(addr, req.data(), req.size());
req = {addr, req.size()};
addr += req.size();
togo -= req.size();
}
else
{
req = {req.data(), 0};
}
}
return false;
},
Expand Down
12 changes: 6 additions & 6 deletions include/llfio/v2.0/handle.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* A handle to something
(C) 2015-2017 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
(C) 2015-2019 Niall Douglas <http://www.nedproductions.biz/> (20 commits)
File Created: Dec 2015
Expand Down Expand Up @@ -74,11 +74,11 @@ class LLFIO_DECL handle
//! On opening, do we also create a new file or truncate an existing one?
enum class creation : unsigned char
{
open_existing = 0,
only_if_not_exist,
if_needed,
truncate //!< Atomically truncate on open, leaving creation date unmodified.
// NOTE: IF UPDATING THIS UPDATE THE std::ostream PRINTER BELOW!!!
open_existing = 0, //!< Filesystem entry must already exist
only_if_not_exist, //!< Filesystem entry must NOT exist, and is atomically created by the success of this operation
if_needed, //!< If filesystem entry exists that is used, else one is created
truncate //!< Filesystem entry must already exist. It is atomically truncated on open, leaving creation date and unique identifier unmodified.
// NOTE: IF UPDATING THIS UPDATE THE std::ostream PRINTER BELOW!!!
};
//! What i/o on the handle will complete immediately due to kernel caching
enum class caching : unsigned char // bit 0 set means safety fsyncs enabled
Expand Down
9 changes: 4 additions & 5 deletions include/llfio/v2.0/io_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@ class LLFIO_DECL io_handle : public handle
memory and that each buffer's size will have changed.
\return The buffers read, which may not be the buffers input. The size of each scatter-gather
buffer is updated with the number of bytes of that buffer transferred, and the pointer to
the data may be \em completely different to what was submitted (e.g. it may point into a
buffer returned is updated with the number of bytes of that buffer transferred, and the pointer
to the data may be \em completely different to what was submitted (e.g. it may point into a
memory map).
\param reqs A scatter-gather and offset request.
\param d An optional deadline by which the i/o must complete, else it is cancelled.
Expand All @@ -315,16 +315,15 @@ class LLFIO_DECL io_handle : public handle

/*! \brief Write data to the open handle.
\warning Depending on the implementation backend, not all of the buffers input may be written and
the some buffers at the end of the returned buffers may return with zero bytes written.
\warning Depending on the implementation backend, not all of the buffers input may be written.
For example, with a zeroed deadline, some backends may only consume as many buffers as the system has available write slots
for, thus for those backends this call is "non-blocking" in the sense that it will return immediately even if it
could not schedule a single buffer write. Another example is that some implementations will not
auto-extend the length of a file when a write exceeds the maximum extent, you will need to issue
a `truncate(newsize)` first.
\return The buffers written, which may not be the buffers input. The size of each scatter-gather
buffer is updated with the number of bytes of that buffer transferred.
buffer returned is updated with the number of bytes of that buffer transferred.
\param reqs A scatter-gather and offset request.
\param d An optional deadline by which the i/o must complete, else it is cancelled.
Note function may return significantly after this deadline if the i/o takes long to cancel.
Expand Down
4 changes: 2 additions & 2 deletions include/llfio/v2.0/map_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ class LLFIO_DECL map_handle : public io_handle
this function. See `QUICKCPPLIB_NAMESPACE::signal_guard` for a helper function.
\return The buffers read, which will never be the buffers input, because they will point into the mapped view.
The size of each scatter-gather buffer is updated with the number of bytes of that buffer transferred.
The size of each scatter-gather buffer returned is updated with the number of bytes of that buffer transferred.
\param reqs A scatter-gather and offset request.
\param d Ignored.
\errors None, though the various signals and structured exception throws common to using memory maps may occur.
Expand All @@ -617,7 +617,7 @@ class LLFIO_DECL map_handle : public io_handle
you configure it. If you don't want the guard, you can write memory directly using `address()`.
\return The buffers written, which will never be the buffers input because they will point at where the data was copied into the mapped view.
The size of each scatter-gather buffer is updated with the number of bytes of that buffer transferred.
The size of each scatter-gather buffer returned is updated with the number of bytes of that buffer transferred.
\param reqs A scatter-gather and offset request.
\param d Ignored.
\errors If during the attempt to write the buffers to the map a `SIGBUS` or `EXCEPTION_IN_PAGE_ERROR` is raised,
Expand Down

0 comments on commit 19115c0

Please sign in to comment.