Buffer writes in blocks of 4Kb when writing buffers to files

Could make kakoune more compatible with tools looking for file
modifications by reducing the amount of writes done.

As discussed in #2812
This commit is contained in:
Maxime Coste 2019-04-01 22:57:55 +11:00
parent a32da9d3ee
commit d91e017803

View File

@ -257,6 +257,41 @@ void write(int fd, StringView data)
} }
} }
struct BufferedWriter
{
BufferedWriter(int fd) : fd{fd} {}
~BufferedWriter()
{
if (pos != 0)
Kakoune::write(fd, {buffer, pos});
}
void write(StringView data)
{
while (not data.empty())
{
const ByteCount length = data.length();
const ByteCount write_len = std::min(length, size - pos);
memcpy(buffer + (int)pos, data.data(), (int)write_len);
pos += write_len;
if (pos == size)
{
Kakoune::write(fd, {buffer, size});
pos = 0;
}
data = data.substr(write_len);
}
}
private:
static constexpr ByteCount size = 4096;
int fd;
ByteCount pos = 0;
char buffer[(int)size];
};
void write_buffer_to_fd(Buffer& buffer, int fd) void write_buffer_to_fd(Buffer& buffer, int fd)
{ {
auto eolformat = buffer.options()["eolformat"].get<EolFormat>(); auto eolformat = buffer.options()["eolformat"].get<EolFormat>();
@ -266,17 +301,18 @@ void write_buffer_to_fd(Buffer& buffer, int fd)
else else
eoldata = "\n"; eoldata = "\n";
BufferedWriter writer{fd};
if (buffer.options()["BOM"].get<ByteOrderMark>() == ByteOrderMark::Utf8) if (buffer.options()["BOM"].get<ByteOrderMark>() == ByteOrderMark::Utf8)
if (::write(fd, "\xEF\xBB\xBF", 3) < 0) writer.write("\xEF\xBB\xBF");
throw runtime_error(format("unable to write data to the buffer (fd: {}; errno: {})", fd, ::strerror(errno)));
for (LineCount i = 0; i < buffer.line_count(); ++i) for (LineCount i = 0; i < buffer.line_count(); ++i)
{ {
// end of lines are written according to eolformat but always // end of lines are written according to eolformat but always
// stored as \n // stored as \n
StringView linedata = buffer[i]; StringView linedata = buffer[i];
write(fd, linedata.substr(0, linedata.length()-1)); writer.write(linedata.substr(0, linedata.length()-1));
write(fd, eoldata); writer.write(eoldata);
} }
} }