Created
November 5, 2009 16:33
-
-
Save koshigoe/227178 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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