From 093818de627bbf60cafe554ba429b3083970f8d2 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 14 May 2021 09:52:49 +0200 Subject: Kernel: Avoid allocations when receiving network packets This avoids two allocations when receiving network packets. One for inserting a PacketWithTimestamp into m_packet_queue and another one when inserting buffers into the list of unused packet buffers. With this fixed the only allocations in NetworkTask happen when initially allocating the PacketWithTimestamp structs and when switching contexts. --- Kernel/Net/NetworkAdapter.cpp | 40 +++++++++++++++++++++++----------------- Kernel/Net/NetworkAdapter.h | 20 ++++++++++++++------ 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/Kernel/Net/NetworkAdapter.cpp b/Kernel/Net/NetworkAdapter.cpp index e1b3a999a4..e453c325d9 100644 --- a/Kernel/Net/NetworkAdapter.cpp +++ b/Kernel/Net/NetworkAdapter.cpp @@ -153,27 +153,34 @@ void NetworkAdapter::did_receive(ReadonlyBytes payload) m_packets_in++; m_bytes_in += payload.size(); - Optional buffer; - if (m_packet_queue_size == max_packet_buffers) { // FIXME: Keep track of the number of dropped packets return; } - if (m_unused_packet_buffers.is_empty()) { - buffer = KBuffer::copy(payload.data(), payload.size()); + RefPtr packet; + + if (m_unused_packets.is_empty()) { + auto buffer = KBuffer::copy(payload.data(), payload.size()); + packet = adopt_ref_if_nonnull(new PacketWithTimestamp { move(buffer), kgettimeofday() }); } else { - buffer = m_unused_packet_buffers.take_first(); - --m_unused_packet_buffers_count; - if (payload.size() <= buffer.value().capacity()) { - memcpy(buffer.value().data(), payload.data(), payload.size()); - buffer.value().set_size(payload.size()); + packet = m_unused_packets.take_first(); + if (payload.size() <= packet->buffer.capacity()) { + memcpy(packet->buffer.data(), payload.data(), payload.size()); + packet->buffer.set_size(payload.size()); + packet->timestamp = kgettimeofday(); } else { - buffer = KBuffer::copy(payload.data(), payload.size()); + auto buffer = KBuffer::copy(payload.data(), payload.size()); + packet = adopt_ref_if_nonnull(new PacketWithTimestamp { move(buffer), kgettimeofday() }); } } - m_packet_queue.append({ buffer.value(), kgettimeofday() }); + if (!packet) { + dbgln("Discarding packet because we're out of memory"); + return; + } + + m_packet_queue.append(*packet); m_packet_queue_size++; if (on_receive) @@ -187,13 +194,12 @@ size_t NetworkAdapter::dequeue_packet(u8* buffer, size_t buffer_size, Time& pack return 0; auto packet_with_timestamp = m_packet_queue.take_first(); m_packet_queue_size--; - packet_timestamp = packet_with_timestamp.timestamp; - auto packet = move(packet_with_timestamp.packet); - size_t packet_size = packet.size(); + packet_timestamp = packet_with_timestamp->timestamp; + auto& packet_buffer = packet_with_timestamp->buffer; + size_t packet_size = packet_buffer.size(); VERIFY(packet_size <= buffer_size); - memcpy(buffer, packet.data(), packet_size); - m_unused_packet_buffers.append(packet); - ++m_unused_packet_buffers_count; + memcpy(buffer, packet_buffer.data(), packet_size); + m_unused_packets.append(*packet_with_timestamp); return packet_size; } diff --git a/Kernel/Net/NetworkAdapter.h b/Kernel/Net/NetworkAdapter.h index f1477f6e22..14748520c1 100644 --- a/Kernel/Net/NetworkAdapter.h +++ b/Kernel/Net/NetworkAdapter.h @@ -8,8 +8,8 @@ #include #include +#include #include -#include #include #include #include @@ -86,18 +86,26 @@ private: IPv4Address m_ipv4_netmask; IPv4Address m_ipv4_gateway; - struct PacketWithTimestamp { - KBuffer packet; + struct PacketWithTimestamp : public RefCounted { + PacketWithTimestamp(KBuffer buffer, Time timestamp) + : buffer(move(buffer)) + , timestamp(timestamp) + { + } + + KBuffer buffer; Time timestamp; + IntrusiveListNode> packet_node; }; // FIXME: Make this configurable static constexpr size_t max_packet_buffers = 1024; - SinglyLinkedList m_packet_queue; + using PacketList = IntrusiveList, &PacketWithTimestamp::packet_node>; + + PacketList m_packet_queue; size_t m_packet_queue_size { 0 }; - SinglyLinkedList m_unused_packet_buffers; - size_t m_unused_packet_buffers_count { 0 }; + PacketList m_unused_packets; String m_name; u32 m_packets_in { 0 }; u32 m_bytes_in { 0 }; -- cgit v1.2.3