PageRenderTime 34ms CodeModel.GetById 2ms app.highlight 29ms RepoModel.GetById 1ms app.codeStats 0ms

/utils/latency/latency.rb

http://github.com/AF83/ucengine
Ruby | 152 lines | 100 code | 24 blank | 28 comment | 6 complexity | 41589ee9c0a64ae4bbf7817280342008 MD5 | raw file
  1#!/usr/bin/env ruby
  2# coding: utf-8
  3
  4require "em-ucengine"
  5require "./lib/score"
  6
  7# The purpose of this script is to mesure two things:
  8#
  9#  - The time an event take to be received via the streaming API
 10#  - The time an event take to be published
 11#
 12# To do so, we run multiple batches which sent events.
 13#
 14# The COUNTER_LIMIT and EVENTS_LIMIT constants configure the number of batch to
 15# run. For instance, if COUNTER_LIMIT equals 5 and EVENTS_LIMIT equals 8 we
 16# got the following:
 17#
 18# First 1 event is sent every 1 second 5 times
 19# Then 2 events is sent every 1 second 5 times
 20# Then 4 events is sent every 1 second 5 times
 21# Then 8 events is sent every 1 second 5 times
 22# Here we stop because we reached EVENTS_LIMIT
 23
 24COUNTER_LIMIT = 5 # Number of runs per batch
 25EVENTS_LIMIT = 100 # Maximum number of event sent per batch
 26
 27$test_number = 0
 28
 29def latency(filters={})
 30    filters[:types] ||= 'test.latency'
 31    filters[:event_generator] ||= Proc.new do |cpt|
 32        'test.latency'
 33    end
 34    filters[:parent] ||= false
 35
 36    EventMachine::UCEngine.run('localhost', 5280) do |uce|
 37        broadcast_scores = Score.new
 38        publishing_scores = Score.new
 39        parent_event = nil
 40
 41        uce.connect("participant", "pwd") do |error, session|
 42            session.publish("parent_event", "demo") do |err, event_id|
 43                parent_event = (filters[:parent]) ? event_id : nil
 44                params = {
 45                    :type => filters[:types],
 46                    :parent => parent_event,
 47                }
 48
 49                subcription = session.subscribe("demo", params) do |err, events|
 50                    events.each do |event|
 51                        received = Time.new
 52                        batch = event['metadata']['batch']
 53                        score = (received.to_f * 1000000).to_i - event['metadata']['timer']
 54                        broadcast_scores[batch] << score
 55                    end
 56                end
 57
 58                nb_events = 1
 59                repeat = 0
 60                timer = EM::PeriodicTimer.new(1) do
 61                    nb_events.times do |i|
 62                        sent = Time.new
 63                        event =filters[:event_generator].call(repeat + i, parent_event)
 64                        metadata = {
 65                            :timer => (sent.to_f * 1000000).to_i,
 66                            :batch => nb_events
 67                        }.merge(event[:metadata] || {})
 68
 69                        session.publish(event[:type], "demo", metadata, event[:parent]) do |err, event_id|
 70                            score = ((Time.new - sent) * 1000000).to_i
 71                            publishing_scores[nb_events] << score
 72                            last_event = event_id
 73                        end
 74
 75                        print "."
 76                    end
 77
 78                    # We reached the event limit, so we stop
 79                    if nb_events >= EVENTS_LIMIT
 80                        # Waiting for the last events
 81                        EM::add_timer 2 do
 82                            $test_number += 1
 83                            broadcast_scores.sort!
 84                            File.open("scores#{$test_number}.csv",'w') do |f|
 85                                f.write broadcast_scores.to_all_csv
 86                            end
 87                            broadcast_scores.each do |batch, scores|
 88                                p "90% of #{batch} events travel in less than #{broadcast_scores.get_9_decile(batch)} µs, min: #{scores[0]} µs, max: #{scores[-1]} µs"
 89                            end
 90
 91                            puts
 92                            publishing_scores.sort!
 93                            File.open("publishing#{$test_number}.csv",'w') do |f|
 94                                f.write publishing_scores.to_csv
 95                            end
 96
 97                            #publishing_scores.values.map(&:sort).each_with_index do |score, n|
 98                            #    p "90% of #{n*10} events were published in less than #{score[score.length * 0.9]} µs, min: #{score[0]} µs, max: #{score[-1]} µs"
 99                            timer.cancel
100                            subcription.cancel { EM.stop }
101
102                            #end
103
104                        end
105                    end
106
107                    repeat += 1
108
109                    # We reached the end of a batch
110                    if repeat == COUNTER_LIMIT
111                        nb_events += 10
112                        repeat = 0
113                        puts
114                    end
115
116                end
117            end
118        end
119    end
120end
121
122#latency()
123
124## Test with a single type
125latency({
126    :types => 'test.latency',
127    :parent => false,
128    :event_generator => Proc.new do |cpt|
129        { :type => (cpt % 2 == 1 ) ? 'test.latency' : 'test.doomed' }
130    end
131})
132
133## Test with two types
134latency({
135    :types => 'test.latency,test.again',
136    :event_generator => Proc.new do |cpt, last_event|
137        { :type =>
138            ['test.latency', 'test.doomed', 'test.again'][cpt % 3]
139        }
140    end
141})
142
143## Test with parent
144latency({
145    :types => 'test.latency',
146    :event_generator => Proc.new do |cpt, parent|
147        { :type   => 'test.latency',
148          :parent => ((cpt %2) == 0) ? parent : nil
149        }
150    end
151})
152