Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
#!/usr/bin/env ruby
# 1. my.cnf か SHOW VARIABLES の結果を入力にとる
# 2. 入力を解析し、必要なパラメータ値を取得する
# 3. 計算
# 4. 結果を標準出力に出力する
require 'optparse'
require 'bigdecimal'
Version = '0.0.1'
class String
def to_byte
return unless /(\d+)([KMG]?)/ =~ self
value, unit = $1.to_i, $2
case unit
when 'K'
value * 1024
when 'M'
value * 1048576
when 'G'
value * 1073741824
end
value
end
end
class Fixnum
def to_s_with_byte_unit(base = 10)
if base.to_sym == :byte
raise "Too large value: #{self}" if self >= 1099511627776 # supported units are ['', 'K', 'M', 'G'].
border = BigDecimal('1024')
value = BigDecimal(self.to_s)
unit = 0
while value >= border
value /= border
unit += 1
end
"%3.2f%s" % [value, ['', 'K', 'M', 'G'][unit]]
else
to_s_without_byte_unit(base)
end
end
alias_method :to_s_without_byte_unit, :to_s
alias_method :to_s, :to_s_with_byte_unit
end
class MyMemCheck
@@global_buffers = %w(key_buffer_size innodb_additional_mem_pool_size innodb_buffer_pool_size innodb_log_buffer_size)
@@thread_buffers = %w(net_buffer_length read_buffer_size read_rnd_buffer_size sort_buffer_size myisam_sort_buffer_size join_buffer_size thread_stack)
def initialize
@cmd_options = parse_cmd_options
@variables = {}
end
def run
read_variables
validate_variables
report_minimal_memory
report_innodb_log_file
end
private
def parse_cmd_options
options = {}
OptionParser.new do |opt|
opt.on('-f path', 'パラメータを path から読み込む(書式は my.cnf に従う)') do |v|
raise "No such file: #{v}" unless File.exists?(v)
options[:file] = v
end
opt.parse!(ARGV)
end
options
end
def read_variables
@variables = {}
@cmd_options[:file] ? read_variables_from_conf : read_variables_from_mysql
end
def read_variables_from_conf
open(@cmd_options[:file]) do |input|
in_mysqld = false
input.each do |line|
line.chomp!
in_mysqld = (line == '[mysqld]') if line[0,1] == '['
next if line.empty? or /\A#/ =~ line or line[0,1] == '['
next unless in_mysqld
next unless /\A(.+)=(.+)\z/ =~ line
name, value = $1.strip, $2.strip
if bytes = value.to_byte
@variables[name] = bytes
end
end
end
end
def read_variables_from_mysql
while line = ARGF.gets
line.chomp!
name, value = line.split("\t")
if value and bytes = value.to_byte
@variables[name] = bytes
end
end
end
def validate_variables
missing_variables = (@@global_buffers + @@thread_buffers) - @variables.keys
unless missing_variables.empty?
raise "[ABORT] missing variables:\n" + missing_variables.map{|name| "\t* #{name}" }.join("\n")
end
end
def report_minimal_memory
global_memory = @variables.values_at(*@@global_buffers).inject(0) {|r,v| r += v}
thread_memory = @variables.values_at(*@@thread_buffers).inject(0) {|r,v| r += v}
all_thread_memory = thread_memory * @variables['max_connections']
total = global_memory + all_thread_memory
puts <<EOS
GLOBAL BUFFERS:
#{@@global_buffers.map{|name| "\t%-40s = %7sB" % [name, @variables[name].to_s(:byte)] }.join("\n")}
#{"\t%-40s = %7sB" % ['', global_memory.to_s(:byte)]}
THREAD BUFFERS:
#{@@thread_buffers.map{|name| "\t%-40s = %7sB" % [name, @variables[name].to_s(:byte)] }.join("\n")}
#{"\t%-40s = %7sB * max_connections(=%d)" % ['', thread_memory.to_s(:byte), @variables['max_connections']]}
#{"\t%-40s = %7sB" % ['', all_thread_memory.to_s(:byte)]}
#{"\t%40s = %7sB" % ['TOTAL', total.to_s(:byte)]}
EOS
end
def report_innodb_log_file
innodb_log_file_size = @variables['innodb_log_file_size']
max_innodb_log_file_size = @variables['innodb_buffer_pool_size'] / @variables['innodb_log_files_in_group']
safe_mark = (1048576..4294967296).include?(innodb_log_file_size) && (innodb_log_file_size <= max_innodb_log_file_size) ? 'safe' : 'out of safety range (too small or too large)'
puts <<EOS
InnoDB log file:
\t1MB < innodb_log_file_size < MAX_innodb_log_file_size < 4GB
\tMAX_innodb_log_file_size = innodb_log_buffer_pool_size / innodb_log_files_in_group
#{"\t%-40s = %7sB" % ['innodb_log_buffer_size', @variables['innodb_log_buffer_size'].to_s(:byte)]}
#{"\t%-40s = %8d" % ['innodb_log_files_in_group', @variables['innodb_log_files_in_group']]}
#{"\t%-40s = %7sB" % ['innodb_log_file_size', @variables['innodb_log_file_size'].to_s(:byte)]}
#{"\t%-40s = %7sB .. %s" % ['MAX_innodb_log_file_size', max_innodb_log_file_size.to_s(:byte), safe_mark]}
EOS
end
end
begin
mymemcheck = MyMemCheck.new
mymemcheck.run
rescue
puts $!
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment