尝试在windows下做一些rails dev,我发现与postgres的初始连接最多需要60秒。我挖掘了activerecord postgresql适配器并在connect方法中添加了一些分析。
require 'ruby-prof'
GC::Profiler.enable
GC.start
RubyProf.start
p @connection_parameters
@connection = PGconn.connect(@connection_parameters)
result = RubyProf.stop
printer = RubyProf::FlatPrinter.new(result)
printer.print(STDOUT)
puts GC::Profiler.report
STDOUT.flush
这给出了以下输出:
测量模式:wall_time 线程ID:7790520 光纤ID:7613460 总计:52.288858 排序方式:self_time
%self total self wait child calls name
99.94 52.258 52.257 0.000 0.001 1 PG::Connection#initialize
0.06 0.031 0.031 0.000 0.000 1 Kernel#p
0.00 0.001 0.001 0.000 0.000 1 Array#pop
0.00 0.000 0.000 0.000 0.000 1 String#sub
0.00 0.000 0.000 0.000 0.000 1 Array#each
0.00 0.000 0.000 0.000 0.000 3 Symbol#to_s
0.00 0.000 0.000 0.000 0.000 1 Hash#each
0.00 0.000 0.000 0.000 0.000 1 Enumerable#map
0.00 0.000 0.000 0.000 0.000 1 Hash#merge!
0.00 0.000 0.000 0.000 0.000 1 Array#zip
0.00 0.000 0.000 0.000 0.000 3 String#to_s
0.00 0.000 0.000 0.000 0.000 36 Symbol#to_sym
0.00 0.000 0.000 0.000 0.000 3 <Class::PG::Connection>#quote_connstr
0.00 0.000 0.000 0.000 0.000 1 Enumerable#find
0.00 0.000 0.000 0.000 0.000 1 Module#instance_methods
0.00 0.000 0.000 0.000 0.000 3 String#gsub
0.00 0.000 0.000 0.000 0.000 1 Kernel#is_a?
0.00 0.000 0.000 0.000 0.000 1 Array#last
0.00 0.001 0.000 0.000 0.001 1 <Class::PG::Connection>#parse_connect_args
0.00 0.000 0.000 0.000 0.000 1 Array#join
0.00 52.258 0.000 0.000 52.258 1 <Class::PG::Connection>#connect
0.00 0.000 0.000 0.000 0.000 2 String#inspect
0.00 0.000 0.000 0.000 0.000 2 Symbol#inspect
0.00 0.000 0.000 0.000 0.000 1 Hash#inspect
0.00 0.000 0.000 0.000 0.000 1 String#%
0.00 52.289 0.000 0.000 52.289 1 ActiveRecord::ConnectionAdapters::PostgreSQLAdapter#connect
* indicates recursively called methods
GC 36 invokes.
Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)
1 12.609 12175480 22293120 557328 125.00000000000000000000
如果我剥离其他所有内容并将确切的一些连接参数传递给PGconn.connect而不加载rails或任何其他库,我可以在2秒内连接:
$ time PGUSER=username PGPASSWORD=password ruby -rpg -rruby-prof -e "GC::Profiler.enable; GC.start; RubyProf.start; settings = {:host => 'localhost', :dbname => 'dbname_development'}; PGconn.connect(settings); r=RubyProf.stop; RubyProf::FlatPrinter.new(r).print(STDOUT); puts GC::Profiler.report; STDOUT.flush"
Measure Mode: wall_time
Thread ID: 20316120
Fiber ID: 20135520
Total: 2.675508
Sort by: self_time
%self total self wait child calls name
100.00 2.676 2.676 0.000 0.000 1 PG::Connection#initialize
0.00 0.000 0.000 0.000 0.000 1 String#sub
0.00 0.000 0.000 0.000 0.000 3 String#to_s
0.00 0.000 0.000 0.000 0.000 3 <Class::PG::Connection>#quote_connstr
0.00 0.000 0.000 0.000 0.000 3 Symbol#to_s
0.00 0.000 0.000 0.000 0.000 1 Hash#each
0.00 0.000 0.000 0.000 0.000 1 Enumerable#map
0.00 0.000 0.000 0.000 0.000 1 Hash#merge!
0.00 0.000 0.000 0.000 0.000 1 Array#zip
0.00 0.000 0.000 0.000 0.000 3 String#gsub
0.00 0.000 0.000 0.000 0.000 46 Symbol#to_sym
0.00 0.000 0.000 0.000 0.000 1 Array#each
0.00 0.000 0.000 0.000 0.000 1 Enumerable#find
0.00 0.000 0.000 0.000 0.000 1 Module#instance_methods
0.00 0.000 0.000 0.000 0.000 1 Array#pop
0.00 0.000 0.000 0.000 0.000 1 Kernel#is_a?
0.00 0.000 0.000 0.000 0.000 1 Array#last
0.00 0.000 0.000 0.000 0.000 1 <Class::PG::Connection>#parse_connect_args
0.00 0.000 0.000 0.000 0.000 1 Array#join
0.00 2.676 0.000 0.000 2.676 1 <Class::PG::Connection>#connect
* indicates recursively called methods
GC 14 invokes.
Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)
1 0.562 895840 1338240 33456 15.62500000000000000000
real 0m3.795s
user 0m0.015s
sys 0m0.046s
随着我添加更多需要的库,连接时间增加。我认为包含本机组件的库可能会产生更大的影响,但不是100%。它使用了更多的内存,但没有达到交换,GC的时间也不多。
关于哪个兔子洞要进一步调查的任何指示?
正在运行的版本:
$ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x64-mingw32]
$ gem list pg --local
pg (0.19.0 x64-mingw32)