aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-01-09 20:24:30 -0500
committerEric W. Biederman <ebiederm@xmission.com>2012-01-24 19:40:30 -0500
commitac13ac6f4c6c0504d2c927862216f4e422a2c0b5 (patch)
tree87d0d698e79b911428b8f8e2f357a27f74c854f9 /include
parent9e3d47df35abd6430fed04fb40a76c7358b1e815 (diff)
sysctl: Index sysctl directories with rbtrees.
One of the most important jobs of sysctl is to export network stack tunables. Several of those tunables are per network device. In several instances people are running with 1000+ network devices in there network stacks, which makes the simple per directory linked list in sysctl a scaling bottleneck. Replace O(N^2) sysctl insertion and lookup times with O(NlogN) by using an rbtree to index the sysctl directories. Benchmark before: make-dummies 0 999 -> 0.32s rmmod dummy -> 0.12s make-dummies 0 9999 -> 1m17s rmmod dummy -> 17s Benchmark after: make-dummies 0 999 -> 0.074s rmmod dummy -> 0.070s make-dummies 0 9999 -> 3.4s rmmod dummy -> 0.44s Benchmark after (without dev_snmp6): make-dummies 0 9999 -> 0.75s rmmod dummy -> 0.44s make-dummies 0 99999 -> 11s rmmod dummy -> 4.3s At 10,000 dummy devices the bottleneck becomes the time to add and remove the files under /proc/sys/net/dev_snmp6. I have commented out the code that adds and removes files under /proc/sys/net/dev_snmp6 and taken measurments of creating and destroying 100,000 dummies to verify the sysctl continues to scale. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'include')
-rw-r--r--include/linux/sysctl.h10
1 files changed, 8 insertions, 2 deletions
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 36dec756ef9d..35c50ed36fc9 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -932,6 +932,7 @@ enum
932#include <linux/list.h> 932#include <linux/list.h>
933#include <linux/rcupdate.h> 933#include <linux/rcupdate.h>
934#include <linux/wait.h> 934#include <linux/wait.h>
935#include <linux/rbtree.h>
935 936
936/* For the /proc/sys support */ 937/* For the /proc/sys support */
937struct ctl_table; 938struct ctl_table;
@@ -1023,6 +1024,11 @@ struct ctl_table
1023 void *extra2; 1024 void *extra2;
1024}; 1025};
1025 1026
1027struct ctl_node {
1028 struct rb_node node;
1029 struct ctl_table_header *header;
1030};
1031
1026/* struct ctl_table_header is used to maintain dynamic lists of 1032/* struct ctl_table_header is used to maintain dynamic lists of
1027 struct ctl_table trees. */ 1033 struct ctl_table trees. */
1028struct ctl_table_header 1034struct ctl_table_header
@@ -1030,7 +1036,6 @@ struct ctl_table_header
1030 union { 1036 union {
1031 struct { 1037 struct {
1032 struct ctl_table *ctl_table; 1038 struct ctl_table *ctl_table;
1033 struct list_head ctl_entry;
1034 int used; 1039 int used;
1035 int count; 1040 int count;
1036 int nreg; 1041 int nreg;
@@ -1042,12 +1047,13 @@ struct ctl_table_header
1042 struct ctl_table_root *root; 1047 struct ctl_table_root *root;
1043 struct ctl_table_set *set; 1048 struct ctl_table_set *set;
1044 struct ctl_dir *parent; 1049 struct ctl_dir *parent;
1050 struct ctl_node *node;
1045}; 1051};
1046 1052
1047struct ctl_dir { 1053struct ctl_dir {
1048 /* Header must be at the start of ctl_dir */ 1054 /* Header must be at the start of ctl_dir */
1049 struct ctl_table_header header; 1055 struct ctl_table_header header;
1050 struct list_head list; 1056 struct rb_root root;
1051}; 1057};
1052 1058
1053struct ctl_table_set { 1059struct ctl_table_set {