mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:47:34 +00:00
LibCore: Avoid some successive allocations in Stream::read_all()
For the general case, allocations will always have the size of a block. In case of a smaller read a block will be filled entirely before another allocation appends. It also adds a specialization for Stream::File::read_all() that tries to detect the size of the file with fstat to perform a single allocation.
This commit is contained in:
parent
3843b8c0a1
commit
e432a284d7
2 changed files with 38 additions and 11 deletions
|
@ -47,20 +47,35 @@ bool Stream::read_or_error(Bytes buffer)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<ByteBuffer> Stream::read_all()
|
ErrorOr<ByteBuffer> Stream::read_all(size_t block_size)
|
||||||
{
|
{
|
||||||
ByteBuffer output;
|
return read_all_impl(block_size);
|
||||||
u8 buffer_raw[4096];
|
}
|
||||||
Bytes buffer { buffer_raw, 4096 };
|
|
||||||
|
|
||||||
while (true) {
|
ErrorOr<ByteBuffer> Stream::read_all_impl(size_t block_size, size_t file_size)
|
||||||
Bytes read_bytes = TRY(read(buffer));
|
{
|
||||||
if (read_bytes.is_empty())
|
ByteBuffer data;
|
||||||
break;
|
data.ensure_capacity(file_size);
|
||||||
output.append(read_bytes);
|
|
||||||
|
size_t total_read {};
|
||||||
|
size_t next_reading_size { block_size };
|
||||||
|
for (Span<u8> chunk; !is_eof();) {
|
||||||
|
if (next_reading_size == block_size)
|
||||||
|
chunk = TRY(data.get_bytes_for_writing(next_reading_size));
|
||||||
|
auto const nread = TRY(read(chunk)).size();
|
||||||
|
|
||||||
|
next_reading_size -= nread;
|
||||||
|
|
||||||
|
if (next_reading_size == 0)
|
||||||
|
next_reading_size = block_size;
|
||||||
|
|
||||||
|
total_read += nread;
|
||||||
|
|
||||||
|
if (nread < block_size)
|
||||||
|
data.resize(total_read);
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Stream::write_or_error(ReadonlyBytes buffer)
|
bool Stream::write_or_error(ReadonlyBytes buffer)
|
||||||
|
@ -191,6 +206,14 @@ ErrorOr<Bytes> File::read(Bytes buffer)
|
||||||
return buffer.trim(nread);
|
return buffer.trim(nread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<ByteBuffer> File::read_all(size_t block_size)
|
||||||
|
{
|
||||||
|
// Note: This is used as a heuristic, it's not valid for devices or virtual files.
|
||||||
|
auto const potential_file_size = TRY(System::fstat(m_fd)).st_size;
|
||||||
|
|
||||||
|
return read_all_impl(block_size, potential_file_size);
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<size_t> File::write(ReadonlyBytes buffer)
|
ErrorOr<size_t> File::write(ReadonlyBytes buffer)
|
||||||
{
|
{
|
||||||
if (!has_flag(m_mode, OpenMode::Write)) {
|
if (!has_flag(m_mode, OpenMode::Write)) {
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
/// Tries to fill the entire buffer through reading. Returns whether the
|
/// Tries to fill the entire buffer through reading. Returns whether the
|
||||||
/// buffer was filled without an error.
|
/// buffer was filled without an error.
|
||||||
virtual bool read_or_error(Bytes);
|
virtual bool read_or_error(Bytes);
|
||||||
ErrorOr<ByteBuffer> read_all();
|
virtual ErrorOr<ByteBuffer> read_all(size_t block_size = 4096);
|
||||||
|
|
||||||
virtual bool is_writable() const { return false; }
|
virtual bool is_writable() const { return false; }
|
||||||
/// Tries to write the entire contents of the buffer. It is possible for
|
/// Tries to write the entire contents of the buffer. It is possible for
|
||||||
|
@ -62,6 +62,9 @@ public:
|
||||||
virtual ~Stream()
|
virtual ~Stream()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ErrorOr<ByteBuffer> read_all_impl(size_t block_size, size_t file_size = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SeekMode {
|
enum class SeekMode {
|
||||||
|
@ -197,6 +200,7 @@ public:
|
||||||
|
|
||||||
virtual bool is_readable() const override;
|
virtual bool is_readable() const override;
|
||||||
virtual ErrorOr<Bytes> read(Bytes) override;
|
virtual ErrorOr<Bytes> read(Bytes) override;
|
||||||
|
virtual ErrorOr<ByteBuffer> read_all(size_t block_size = 4096) override;
|
||||||
virtual bool is_writable() const override;
|
virtual bool is_writable() const override;
|
||||||
virtual ErrorOr<size_t> write(ReadonlyBytes) override;
|
virtual ErrorOr<size_t> write(ReadonlyBytes) override;
|
||||||
virtual bool is_eof() const override;
|
virtual bool is_eof() const override;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue