From: Robert Klemme Date: 2005-09-24T01:51:41+09:00 Subject: Re: Optimizing a single slow method ------=_NextPart_000_0006_01C5C06F.92A42160 Content-Type: text/plain; format=flowed; charset="iso-8859-1"; reply-type=response Content-Transfer-Encoding: 7bit Robert Klemme wrote: > Guess so. I thought it was cleaner to do this separately but if you > actually need this it's a minor change. You could integrate it into > #parse_ticks and remember if it was the first file. Untested but > cryptic: > def parse_ticks_2(io) > create = @contracts.nil? > @contracts = {} if create > > io.each_line do |line| > if %r{^ > (\w\d+\w), # contractid > (\d{6}), # date > (\d+(?:\.\d+)?), # open > (\d+(?:\.\d+)?), # high > (\d+(?:\.\d+)?), # low > (\d+(?:\.\d+)?), # close > }x =~ line > cid = $1.freeze > > contract = (@contracts[cid] || ( create && (@contracts[cid] = > Contract.new cid) ) ) and > contract.add_tick $2, $3.to_f, $4.to_f, $5.to_f, $6.to_f > end > end > end This is even more efficient as it pulls the boolean evaluation out of the loop *and* takes advantage of the fact that Hash and Proc both accept #[]: def parse_ticks_3(io) if @contracts cg = @contracts else @contracts = {} cg = lambda {|c_id| @contracts[c_id] ||= Contract.new c_id} end io.each_line do |line| if %r{^ (\w\d+\w), # contractid (\d{6}), # date (\d+(?:\.\d+)?), # open (\d+(?:\.\d+)?), # high (\d+(?:\.\d+)?), # low (\d+(?:\.\d+)?), # close }x =~ line cid = $1.freeze contract = cg[cid] and contract.add_tick $2, $3.to_f, $4.to_f, $5.to_f, $6.to_f end end end Kind regards robert ------=_NextPart_000_0006_01C5C06F.92A42160 Content-Type: application/octet-stream; name="parse_contracts.rb" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="parse_contracts.rb" #!/usr/bin/ruby=0A= =0A= =0A= # a single line:=0A= # A62005U,050909,0.7726,0.7758,0.7703,0.7737,12366,0=0A= =0A= class IllegalStateException < StandardError=0A= end=0A= =0A= # -------------------------------=0A= =0A= class Contract=0A= Tick =3D Struct.new :date, :open, :high, :low, :close=0A= =0A= class Tick=0A= include Comparable=0A= =0A= def <=3D> (tick) self.date <=3D> tick.date end=0A= end=0A= =0A= attr_reader :contract_id=0A= =0A= def initialize(contract_id)=0A= @contract_id =3D contract_id=0A= @ticks =3D []=0A= end=0A= =0A= def add_tick(date, open, high, low, close)=0A= @ticks << Tick.new( date, open, high, low, close )=0A= end=0A= =0A= def sort_ticks() @ticks.sort! end=0A= end=0A= =0A= # -------------------------------=0A= =0A= class ContractSet=0A= def parse_reference(io)=0A= @contracts =3D {}=0A= =0A= io.each_line do |line|=0A= if /^(\w\d+\w),/ =3D~ line=0A= cid =3D $1.freeze=0A= @contracts[cid] ||=3D Contract.new cid=0A= end=0A= end=0A= end=0A= =0A= def parse_ticks(io)=0A= raise IllegalStateException, "need to read reference first" unless = @contracts=0A= =0A= io.each_line do |line|=0A= if %r{^=0A= (\w\d+\w), # contractid=0A= (\d{6}), # date=0A= (\d+(?:\.\d+)?), # open=0A= (\d+(?:\.\d+)?), # high=0A= (\d+(?:\.\d+)?), # low=0A= (\d+(?:\.\d+)?), # close=0A= }x =3D~ line=0A= cid =3D $1.freeze=0A= =0A= contract =3D @contracts[cid] and=0A= contract.add_tick $2, $3.to_f, $4.to_f, $5.to_f, $6.to_f=0A= end=0A= end=0A= end=0A= =0A= def parse_ticks_2(io)=0A= create =3D @contracts.nil?=0A= @contracts =3D {} if create=0A= =0A= io.each_line do |line|=0A= if %r{^=0A= (\w\d+\w), # contractid=0A= (\d{6}), # date=0A= (\d+(?:\.\d+)?), # open=0A= (\d+(?:\.\d+)?), # high=0A= (\d+(?:\.\d+)?), # low=0A= (\d+(?:\.\d+)?), # close=0A= }x =3D~ line=0A= cid =3D $1.freeze=0A= =0A= contract =3D (@contracts[cid] || ( create && (@contracts[cid] = =3D Contract.new cid) ) ) and=0A= contract.add_tick $2, $3.to_f, $4.to_f, $5.to_f, $6.to_f=0A= end=0A= end=0A= end=0A= =0A= def parse_ticks_3(io)=0A= if @contracts=0A= cg =3D @contracts=0A= else=0A= @contracts =3D {}=0A= cg =3D lambda {|c_id| @contracts[c_id] ||=3D Contract.new c_id}=0A= end=0A= =0A= io.each_line do |line|=0A= if %r{^=0A= (\w\d+\w), # contractid=0A= (\d{6}), # date=0A= (\d+(?:\.\d+)?), # open=0A= (\d+(?:\.\d+)?), # high=0A= (\d+(?:\.\d+)?), # low=0A= (\d+(?:\.\d+)?), # close=0A= }x =3D~ line=0A= cid =3D $1.freeze=0A= =0A= contract =3D cg[cid] and=0A= contract.add_tick $2, $3.to_f, $4.to_f, $5.to_f, $6.to_f=0A= end=0A= end=0A= end=0A= =0A= def post_process=0A= @contracts.each_value do |contract|=0A= contract.sort_ticks=0A= end=0A= end=0A= end=0A= =0A= class Ticker=0A= def initialize()=0A= @t =3D Time.now.to_f=0A= @count =3D 0.0=0A= end=0A= =0A= def tick(msg)=0A= diff =3D Time.now.to_f - @t=0A= @count +=3D diff=0A= print diff, msg=0A= @t =3D Time.now.to_f=0A= end=0A= =0A= def total=0A= print @count, "total"=0A= end=0A= =0A= def print(diff, msg)=0A= printf "%8.3fs %s\n", diff, msg=0A= end=0A= end=0A= =0A= # = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=0A= # MAIN=0A= # = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=0A= =0A= t =3D Ticker.new=0A= cs =3D ContractSet.new=0A= =0A= # File.open(ARGV.shift, IO::RDONLY) {|io| cs.parse_reference io}=0A= # t.tick "read ref"=0A= =0A= ARGV.each do |f|=0A= File.open(f, IO::RDONLY) {|io| cs.parse_ticks_3 io}=0A= t.tick "read file #{f}"=0A= end=0A= =0A= cs.post_process=0A= =0A= t.tick "finished post processing"=0A= t.total=0A= ------=_NextPart_000_0006_01C5C06F.92A42160--