#!/usr/bin/perl #============================================================================== # Copyright and license info is available in the LICENSE file included with # the Server Deployment Package (SDP), and also available online: # https://swarm.workshop.perforce.com/projects/perforce-software-sdp/view/main/LICENSE #------------------------------------------------------------------------------ # Author: jhalbig@perforce.com # Date: November 10, 2020 # After several years of successful implementation my plan is to render this # ready for prime-time usage by cleaning up and fully documenting the settings # with an internal KB that will one day be presentable to a wider audience; for # now this will be useful for support engineers for cases where the server loads # don't appear to be utilizing all Linux OS hardware, networking resources in # particular. # # Usage: ./parse_sysctl.pl {-a} {/path to/}sysctl.out # # -a: # # Check rarely tweaked kernel settings. # # {/path to/}sysctl.out: # # The 'sysctl -a' output file to parse. # # Or change this sysctl_file value to a file containing "sysctl -a" output: my $sysctl_file = "sysctl.out"; # List of recommended kernel values: my $rec_k_vals = <<KERNEL_VALS; net.ipv4.tcp_syncookies : 0 net.ipv4.tcp_timestamps : 1 net.ipv4.tcp_window_scaling : 1 net.core.somaxconn : 2048 net.core.netdev_max_backlog : 5000 net.ipv4.tcp_max_syn_backlog : 2048 net.ipv4.ip_local_port_range : 10000 65535 net.ipv4.tcp_fin_timeout : 30 net.ipv4.tcp_keepalive_intvl : 30 net.ipv4.tcp_keepalive_probes : 20 net.ipv4.tcp_keepalive_time : 890 net.core.netdev_budget : 600 net.core.rmem_max : 16777216 net.core.wmem_max : 16777216 net.core.optmem_max : 16777216 net.ipv4.tcp_mem : 1528512 2038016 8388608 net.ipv4.tcp_rmem : 4096 87380 16777216 net.ipv4.tcp_wmem : 4096 65536 16777216 net.ipv4.tcp_no_metrics_save : 1 net.ipv4.tcp_sack : 0 net.ipv4.conf.all.accept_redirects : 0 net.ipv4.conf.all.rp_filter : 1 net.ipv4.conf.all.secure_redirects : 0 net.ipv4.conf.all.send_redirects : 0 net.ipv4.conf.all.accept_source_route : 0 net.ipv4.icmp_echo_ignore_broadcasts : 1 net.ipv4.ip_forward : 0 KERNEL_VALS my $rare_k_vals = <<KERNEL_VALS; kernel.nmi_watchdog : 0 kernel.soft_watchdog : 1 kernel.watchdog_thresh : 180 kernel.softlockup_all_cpu_backtrace : 1 kernel.hardlockup_all_cpu_backtrace : 0 kernel.sysrq : 0 kernel.core_uses_pid : 1 kernel.msgmnb : 65536 kernel.msgmax : 65536 kernel.shmmax : 68719476736 kernel.shmall : 4294967296 KERNEL_VALS # OS command to change/write values: my $sysctl_cmd = "sysctl -w"; # List of recommended Perforce server configurables: my %p4d_vals = qw( net.tcpsize 524288 net.backlog 2048 filesys.bufsize 512K net.bufsize 512K filesys.bufsize 512K lbr.bufsize 512K ); # Perforce command to change/write values: my $p4_cmd = "p4 configure set"; # Those are the text sections that allow the Perforce VCS admin to adapt this # script to their particular needs: my $txt_1 = <<PREAMBLE_TEXT; Some key performance related kernel settings are at the defaults, which means that some of your server resources are likely under utilized. Here is a list of the settings that, based on past experience, improve server performance, in some cases dramatically: Setting New Value (Old Value) --------------------------------------- PREAMBLE_TEXT my $txt_2 = <<CHG_KERNEL_HEADER; To change those settings, run those commands as a privileged user: CHG_KERNEL_HEADER my $txt_3 = <<UPDATESYSCTL_TEXT; Note: Always make a copy of your sysctl.conf file prior to making any changes, whether by editing the file directly or using the sysctl command: sudo mv /etc/sysctl.conf /etc/sysctl.conf.BAK Once you've backed up this file and determined that there are no issues with the new settings, make those changes to the same values listed in that file. To test the new sysctl.conf file, use the command: sudo sysctl -p This will re-load all kernel settings directly from sysctl.conf file. Important note: If things appear "broken" after this point, *do not reboot*; Make a copy of the edited sysctl.conf file and replace it from the backup you created earlier, and reload the file using the same command. UPDATESYSCTL_TEXT my $txt_4 = <<CHG_P4_HEADER; Next, run those commands against your Perforce server: CHG_P4_HEADER my $txt_5 = <<P4_RESTART; p4 admin restart P4_RESTART my $txt_6 = <<CLOSING_TEXT; The last command is needed for the new values to take effect for the Perforce server as several of those configurables are not dynamically change upon setting. CLOSING_TEXT my $usage_txt = <<USAGE; Usage: ./parse_sysctl.pl {-a} {/path to/}sysctl.out Arguments: -a: Check rarely tweaked kernel settings. -h/-? This message. {/path to/}sysctl.out: The 'sysctl -a' output file to parse. Note: If no file argument is given the script looks for "$sysctl_file" by default. Modify the sysctl_file variable in the script to change this. For more information, see: Using parse_sysctl.pl Script To Diagnose Linux Performance Issues https://perforce.my.salesforce.com/kA02I000000bn4u USAGE ## End user settings. # Check for -a option: if ($ARGV[0] =~ "-a") { shift; $rec_k_vals .= $rare_k_vals; } elsif ($ARGV[0] =~ m/-(h|\?)/) { shift; print $usage_txt; exit(0); } # Check for file argument: if ($ARGV[0]){ $sysctl_file = $ARGV[0]; } my %k_vals; my $q = ""; my $a = 0; @l = ("aa" .. "zz"); # I wanted to keep kernel settings groups as they are to keep related settings # grouped together. After considerable mucking about it was clear that sorting # a hash based on order of entry was not possible without adding an index. # # Which was promptly sorted in that annoying "1,11,12,2,3..." pattern. I REALLY # just wanted to sort it in order, so I created an array of labels from aa through zz, # Which covers 676 possible entries. Likely overkill. :-) However, if it's not enough I # can always add a letter. :P # # Just know I won't be the one populating that many kernel tweaks. ;-) # # The upshot is I can preserve the original order by sorting the hash keys, instead # of iterating through arrays and messing with hash slices. W00t! # # I parse the text block to create a hash to track kernel settings: while ($rec_k_vals =~ m/.+?(.+?)\s*\:\s*(.+)\s*?\n/g) { $k_vals{$l[$a]} = {'name' => $1, 'old_val' => "none", 'new_val' => $2}; $a++; } # Parse the sysctl output file to determine if there are any values that need to # be changed or added: open (SYSCTL, "< " . $sysctl_file) or die $usage_txt . "ERROR: Can't read file " . $sysctl_file .":\n" . $!; while (<SYSCTL>) { chomp; foreach my $val (keys %k_vals) { if (/^.*?$k_vals{$val}{'name'}\s+?=\s+?(.*)$/) { $k_vals{$val}{'old_val'} = $1; } } } close SYSCTL; ## Create the pretty table with comparison values print $txt_1; foreach my $val (sort keys %k_vals) { $k_vals{$val}{'old_val'} =~ s/\t/\x20/g; # normalize tabs to spaces unless ($k_vals{$val}{'old_val'} =~ $k_vals{$val}{'new_val'}) { if ($k_vals{$val}{'old_val'} =~ "none") { next; } if ( $k_vals{$val}{old_val} == 0 || $k_vals{$val}{old_val } ) { print "\t" . $k_vals{$val}{'name'} . "\t\t" . $k_vals{$val}{new_val} . "\t" . "(" . $k_vals{$val}{old_val} . ")\n"; } } } ## Create the ready to paste OS commands to change those settings: print $txt_2; foreach my $val (sort keys %k_vals) { unless ($k_vals{$val}{old_val} =~ $k_vals{$val}{new_val}) { if ($k_vals{$val}{'old_val'} =~ "none") { next; } unless ($k_vals{$val}{old_val}) { next; } if ($k_vals{$val}{new_val} =~ m/\s/g) { $q = "\""; } print "\t" . $sysctl_cmd . " " . $k_vals{$val}{'name'} . "=" . $q . $k_vals{$val}{new_val} . $q . "\n"; $q = ""; } } print $txt_3; print $txt_4; ## Create the ready to paste Perforce server commands: foreach my $val (keys %p4d_vals) { print "\t" . $p4_cmd . " " . $val . "=" . $p4d_vals{$val} . "\n"; } ## Print "p4 admin restart" command: print $txt_5; ## Closing text. print $txt_6; # WARNING: While this detects differences in values, the original values might # already have been tweaked! Remember to remove those lines that are already # at good values, taking care to remove the associated "sysctl -w" entry.
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 27246 | Jessie Fernandez | Branch for Jessie Fernandez | ||
//guest/perforce_software/sdp/dev/Server/Unix/setup/parse_sysctl.pl | |||||
#1 | 27079 | C. Thomas Tyler |
Add Support utility to simplify adopting sysctl best practices. To Do: Add guidance on when this should be run, e.g. "These settings should work on hardware with 16G+ RAM" or something to that effect. Or add logic in the script to smartly decide which settings to apply based on RAM. #review @jhalbig @michael_shields @jason_gibson |