mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 22:41:25 +12:00
Compression: Improve async compression performance
This commit is contained in:
parent
6214d0c9a5
commit
b00fe1d12f
2 changed files with 38 additions and 9 deletions
|
@ -171,12 +171,17 @@ void uncompressed_serialization_file_handler::finalize(utils::serial& ar)
|
||||||
ar.data = {}; // Deallocate and clear
|
ar.data = {}; // Deallocate and clear
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum : u64
|
||||||
|
{
|
||||||
|
pending_compress_bytes_bound = 0x400'0000,
|
||||||
|
pending_data_wait_bit = 1ull << 63,
|
||||||
|
};
|
||||||
|
|
||||||
struct compressed_stream_data
|
struct compressed_stream_data
|
||||||
{
|
{
|
||||||
z_stream m_zs{};
|
z_stream m_zs{};
|
||||||
lf_queue<std::vector<u8>> m_queued_data_to_process;
|
lf_queue<std::vector<u8>> m_queued_data_to_process;
|
||||||
lf_queue<std::vector<u8>> m_queued_data_to_write;
|
lf_queue<std::vector<u8>> m_queued_data_to_write;
|
||||||
atomic_t<usz> m_pending_bytes = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void compressed_serialization_file_handler::initialize(utils::serial& ar)
|
void compressed_serialization_file_handler::initialize(utils::serial& ar)
|
||||||
|
@ -286,21 +291,24 @@ bool compressed_serialization_file_handler::handle_file_op(utils::serial& ar, us
|
||||||
// Avoid flooding RAM, wait if there is too much pending memory
|
// Avoid flooding RAM, wait if there is too much pending memory
|
||||||
const usz new_value = m_pending_bytes.atomic_op([&](usz v)
|
const usz new_value = m_pending_bytes.atomic_op([&](usz v)
|
||||||
{
|
{
|
||||||
v &= ~(1ull << 63);
|
v &= ~pending_data_wait_bit;
|
||||||
|
|
||||||
if (v > 0x400'0000)
|
if (v >= pending_compress_bytes_bound)
|
||||||
{
|
{
|
||||||
v |= 1ull << 63;
|
v |= pending_data_wait_bit;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Overflow detector
|
||||||
|
ensure(~v - pending_data_wait_bit > ar.data.size());
|
||||||
|
|
||||||
v += ar.data.size();
|
v += ar.data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (new_value & (1ull << 63))
|
if (new_value & pending_data_wait_bit)
|
||||||
{
|
{
|
||||||
m_pending_bytes.wait(new_value);
|
m_pending_bytes.wait(new_value);
|
||||||
}
|
}
|
||||||
|
@ -635,19 +643,32 @@ void compressed_serialization_file_handler::stream_data_prepare_thread_op()
|
||||||
|
|
||||||
buffer_offset = m_zs.next_out - m_stream_data.data();
|
buffer_offset = m_zs.next_out - m_stream_data.data();
|
||||||
|
|
||||||
|
m_zs.avail_in = adjust_for_uint(data.size() - (m_zs.next_in - data.data()));
|
||||||
|
|
||||||
if (m_zs.avail_out == 0)
|
if (m_zs.avail_out == 0)
|
||||||
{
|
{
|
||||||
m_stream_data.resize(m_stream_data.size() + (m_zs.avail_in + 3ull) / 4);
|
m_stream_data.resize(m_stream_data.size() + (m_zs.avail_in + 3ull) / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_zs.avail_in = adjust_for_uint(data.size() - (m_zs.next_in - data.data()));
|
|
||||||
}
|
}
|
||||||
while (m_zs.avail_out == 0 || m_zs.avail_in != 0);
|
while (m_zs.avail_out == 0 || m_zs.avail_in != 0);
|
||||||
|
|
||||||
// Forward for file write
|
// Forward for file write
|
||||||
const usz queued_size = data.size();
|
const usz queued_size = data.size();
|
||||||
ensure(buffer_offset);
|
ensure(buffer_offset);
|
||||||
m_pending_bytes += buffer_offset - queued_size;
|
|
||||||
|
const usz size_diff = buffer_offset - queued_size;
|
||||||
|
const usz new_val = m_pending_bytes.add_fetch(size_diff);
|
||||||
|
const usz left = new_val & ~pending_data_wait_bit;
|
||||||
|
|
||||||
|
if (new_val & pending_data_wait_bit && left < pending_compress_bytes_bound && left - size_diff >= pending_compress_bytes_bound && !m_pending_signal)
|
||||||
|
{
|
||||||
|
// Notification is postponed until data write and memory release
|
||||||
|
m_pending_signal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure wait bit state has not changed by the update
|
||||||
|
ensure(~((new_val - size_diff) ^ new_val) & pending_data_wait_bit);
|
||||||
|
|
||||||
m_stream_data.resize(buffer_offset);
|
m_stream_data.resize(buffer_offset);
|
||||||
stream.m_queued_data_to_write.push(std::move(m_stream_data));
|
stream.m_queued_data_to_write.push(std::move(m_stream_data));
|
||||||
}
|
}
|
||||||
|
@ -673,10 +694,17 @@ void compressed_serialization_file_handler::file_writer_thread_op()
|
||||||
m_file->write(data);
|
m_file->write(data);
|
||||||
data = {}; // Deallocate before notification
|
data = {}; // Deallocate before notification
|
||||||
|
|
||||||
if (m_pending_bytes.sub_fetch(last_size) == 1ull << 63)
|
const usz new_val = m_pending_bytes.sub_fetch(last_size);
|
||||||
|
const usz left = new_val & ~pending_data_wait_bit;
|
||||||
|
const bool pending_sig = m_pending_signal && m_pending_signal.exchange(false);
|
||||||
|
|
||||||
|
if (pending_sig || (new_val & pending_data_wait_bit && left < pending_compress_bytes_bound && left + last_size >= pending_compress_bytes_bound))
|
||||||
{
|
{
|
||||||
m_pending_bytes.notify_all();
|
m_pending_bytes.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure wait bit state has not changed by the update
|
||||||
|
ensure(~((new_val + last_size) ^ new_val) & pending_data_wait_bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,7 @@ private:
|
||||||
usz m_stream_data_index = 0;
|
usz m_stream_data_index = 0;
|
||||||
usz m_file_read_index = 0;
|
usz m_file_read_index = 0;
|
||||||
atomic_t<usz> m_pending_bytes = 0;
|
atomic_t<usz> m_pending_bytes = 0;
|
||||||
|
atomic_t<bool> m_pending_signal = false;
|
||||||
bool m_write_inited = false;
|
bool m_write_inited = false;
|
||||||
bool m_read_inited = false;
|
bool m_read_inited = false;
|
||||||
bool m_errored = false;
|
bool m_errored = false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue