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