kernel: use bulk free in kfree_skb_list to improve performance
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
085141dc5b
commit
98b654de2e
@ -0,0 +1,61 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Sat, 23 Mar 2019 18:26:10 +0100
|
||||
Subject: [PATCH] net: use bulk free in kfree_skb_list
|
||||
|
||||
Since we're freeing multiple skbs, we might as well use bulk free to save a
|
||||
few cycles. Use the same conditions for bulk free as in napi_consume_skb.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/core/skbuff.c
|
||||
+++ b/net/core/skbuff.c
|
||||
@@ -666,12 +666,44 @@ EXPORT_SYMBOL(kfree_skb);
|
||||
|
||||
void kfree_skb_list(struct sk_buff *segs)
|
||||
{
|
||||
- while (segs) {
|
||||
- struct sk_buff *next = segs->next;
|
||||
+ struct sk_buff *next = segs;
|
||||
+ void *skbs[16];
|
||||
+ int n_skbs = 0;
|
||||
|
||||
- kfree_skb(segs);
|
||||
- segs = next;
|
||||
+ while ((segs = next) != NULL) {
|
||||
+ next = segs->next;
|
||||
+
|
||||
+ if (segs->fclone != SKB_FCLONE_UNAVAILABLE) {
|
||||
+ kfree_skb(segs);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (!skb_unref(segs))
|
||||
+ continue;
|
||||
+
|
||||
+ trace_kfree_skb(segs, __builtin_return_address(0));
|
||||
+
|
||||
+ /* drop skb->head and call any destructors for packet */
|
||||
+ skb_release_all(segs);
|
||||
+
|
||||
+#ifdef CONFIG_SLUB
|
||||
+ /* SLUB writes into objects when freeing */
|
||||
+ prefetchw(segs);
|
||||
+#endif
|
||||
+
|
||||
+ skbs[n_skbs++] = segs;
|
||||
+
|
||||
+ if (n_skbs < ARRAY_SIZE(skbs))
|
||||
+ continue;
|
||||
+
|
||||
+ kmem_cache_free_bulk(skbuff_head_cache, n_skbs, skbs);
|
||||
+ n_skbs = 0;
|
||||
}
|
||||
+
|
||||
+ if (!n_skbs)
|
||||
+ return;
|
||||
+
|
||||
+ kmem_cache_free_bulk(skbuff_head_cache, n_skbs, skbs);
|
||||
}
|
||||
EXPORT_SYMBOL(kfree_skb_list);
|
||||
|
@ -0,0 +1,61 @@
|
||||
From: Felix Fietkau <nbd@nbd.name>
|
||||
Date: Sat, 23 Mar 2019 18:26:10 +0100
|
||||
Subject: [PATCH] net: use bulk free in kfree_skb_list
|
||||
|
||||
Since we're freeing multiple skbs, we might as well use bulk free to save a
|
||||
few cycles. Use the same conditions for bulk free as in napi_consume_skb.
|
||||
|
||||
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
|
||||
--- a/net/core/skbuff.c
|
||||
+++ b/net/core/skbuff.c
|
||||
@@ -666,12 +666,44 @@ EXPORT_SYMBOL(kfree_skb);
|
||||
|
||||
void kfree_skb_list(struct sk_buff *segs)
|
||||
{
|
||||
- while (segs) {
|
||||
- struct sk_buff *next = segs->next;
|
||||
+ struct sk_buff *next = segs;
|
||||
+ void *skbs[16];
|
||||
+ int n_skbs = 0;
|
||||
|
||||
- kfree_skb(segs);
|
||||
- segs = next;
|
||||
+ while ((segs = next) != NULL) {
|
||||
+ next = segs->next;
|
||||
+
|
||||
+ if (segs->fclone != SKB_FCLONE_UNAVAILABLE) {
|
||||
+ kfree_skb(segs);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (!skb_unref(segs))
|
||||
+ continue;
|
||||
+
|
||||
+ trace_kfree_skb(segs, __builtin_return_address(0));
|
||||
+
|
||||
+ /* drop skb->head and call any destructors for packet */
|
||||
+ skb_release_all(segs);
|
||||
+
|
||||
+#ifdef CONFIG_SLUB
|
||||
+ /* SLUB writes into objects when freeing */
|
||||
+ prefetchw(segs);
|
||||
+#endif
|
||||
+
|
||||
+ skbs[n_skbs++] = segs;
|
||||
+
|
||||
+ if (n_skbs < ARRAY_SIZE(skbs))
|
||||
+ continue;
|
||||
+
|
||||
+ kmem_cache_free_bulk(skbuff_head_cache, n_skbs, skbs);
|
||||
+ n_skbs = 0;
|
||||
}
|
||||
+
|
||||
+ if (!n_skbs)
|
||||
+ return;
|
||||
+
|
||||
+ kmem_cache_free_bulk(skbuff_head_cache, n_skbs, skbs);
|
||||
}
|
||||
EXPORT_SYMBOL(kfree_skb_list);
|
||||
|
Loading…
Reference in New Issue
Block a user