From 94b184f0c770e1dc5c78fa062f82f41cf04fd2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A8=D0=BB=D1=8F=D0=BF=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=9D=D0=B8=D0=BA=D0=BE?= =?UTF-8?q?=D0=BB=D0=B0=D0=B5=D0=B2=D0=B8=D1=87?= Date: Sat, 1 Mar 2025 14:44:45 +0300 Subject: [PATCH 1/3] iter 1 --- Makefile | 5 ++++ client.rb | 75 +++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7f8e2d0 --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +start-server: + bundle exec falcon serve -c config.ru --threaded + +start-client: + ruby client.rb \ No newline at end of file diff --git a/client.rb b/client.rb index e001ba3..9bee81a 100644 --- a/client.rb +++ b/client.rb @@ -1,8 +1,20 @@ require 'openssl' require 'faraday' +require 'async' +require 'async/barrier' +require 'async/semaphore' + OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE +class TimeIsOverError < StandardError; end + +class ResultIsNotEq < StandardError; end + +expected_result = "0bbe9ecf251ef4131dd43e1600742cfb" + +expected_time = 7 + # Есть три типа эндпоинтов API # Тип A: # - работает 1 секунду @@ -29,6 +41,35 @@ def c(value) Faraday.get("https://localhost:9292/c?value=#{value}").body end +func_a = proc { |v| a(v) } +func_b = proc { |v| b(v) } +func_c = proc { |v| c(v) } + +@result_task_a = [] + +def start_worker(values_a, value_b, worker_a, worker_b, worker_c) + barrier = Async::Barrier.new + @results_a = [] + @result_b = "" + threads = [] + Sync do + semaphore = Async::Semaphore.new(4, parent: barrier) + values_a.each do |value| + threads << semaphore.async do + @results_a << worker_a.call(value) + end + end + threads << semaphore.async do + @result_b = worker_b.call(value_b) + end + threads.map(&:wait) + ensure + barrier.stop + end + result_ab = "#{@results_a.sort.join('-')}-#{@result_b}" + worker_c.call(result_ab) +end + # Референсное решение, приведённое ниже работает правильно, занимает ~19.5 секунд # Надо сделать в пределах 7 секунд @@ -38,34 +79,25 @@ def collect_sorted(arr) start = Time.now -a11 = a(11) -a12 = a(12) -a13 = a(13) -b1 = b(1) -ab1 = "#{collect_sorted([a11, a12, a13])}-#{b1}" + +ab1 = start_worker(val, 1, func_a, func_b) puts "AB1 = #{ab1}" c1 = c(ab1) puts "C1 = #{c1}" -a21 = a(21) -a22 = a(22) -a23 = a(23) -b2 = b(2) +val = [21, 22, 23] -ab2 = "#{collect_sorted([a21, a22, a23])}-#{b2}" +ab2 = start_worker(val, 2, func_a, func_b) puts "AB2 = #{ab2}" c2 = c(ab2) puts "C2 = #{c2}" -a31 = a(31) -a32 = a(32) -a33 = a(33) -b3 = b(3) +val = [31, 32, 33] -ab3 = "#{collect_sorted([a31, a32, a33])}-#{b3}" +ab3 = start_worker(val, 3, func_a, func_b) puts "AB3 = #{ab3}" c3 = c(ab3) @@ -74,5 +106,16 @@ def collect_sorted(arr) c123 = collect_sorted([c1, c2, c3]) result = a(c123) -puts "FINISHED in #{Time.now - start}s." + +time = Time.now - start + +puts "FINISHED in #{time}s." puts "RESULT = #{result}" # 0bbe9ecf251ef4131dd43e1600742cfb + +if result != expected_result + raise ResultIsNotEq, "#{result} != #{expected_result}" +end + +if time > expected_time + raise TimeIsOverError, "#{time}" +end From 19d4946ce476deedb1433ba6b2ece69840ff471d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A8=D0=BB=D1=8F=D0=BF=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=9D=D0=B8=D0=BA=D0=BE?= =?UTF-8?q?=D0=BB=D0=B0=D0=B5=D0=B2=D0=B8=D1=87?= Date: Sat, 1 Mar 2025 20:09:26 +0300 Subject: [PATCH 2/3] iter 2 --- client.rb | 142 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 99 insertions(+), 43 deletions(-) diff --git a/client.rb b/client.rb index 9bee81a..f84ced1 100644 --- a/client.rb +++ b/client.rb @@ -27,18 +27,24 @@ class ResultIsNotEq < StandardError; end # - одновременно можно запускать не более одного # def a(value) - puts "https://localhost:9292/a?value=#{value}" - Faraday.get("https://localhost:9292/a?value=#{value}").body + Thread.new do + puts "https://localhost:9292/a?value=#{value}" + Faraday.get("https://localhost:9292/a?value=#{value}").body + end end def b(value) - puts "https://localhost:9292/b?value=#{value}" - Faraday.get("https://localhost:9292/b?value=#{value}").body + Thread.new do + puts "https://localhost:9292/b?value=#{value}" + Faraday.get("https://localhost:9292/b?value=#{value}").body + end end def c(value) - puts "https://localhost:9292/c?value=#{value}" - Faraday.get("https://localhost:9292/c?value=#{value}").body + Thread.new do + puts "https://localhost:9292/c?value=#{value}" + Faraday.get("https://localhost:9292/c?value=#{value}").body + end end func_a = proc { |v| a(v) } @@ -47,27 +53,18 @@ def c(value) @result_task_a = [] -def start_worker(values_a, value_b, worker_a, worker_b, worker_c) +def start_worker(values, worker, count, result) barrier = Async::Barrier.new - @results_a = [] - @result_b = "" - threads = [] - Sync do - semaphore = Async::Semaphore.new(4, parent: barrier) - values_a.each do |value| - threads << semaphore.async do - @results_a << worker_a.call(value) + Async do + semaphore = Async::Semaphore.new(count, parent: barrier) + values.map do |value| + semaphore.async do + result[value] = worker.call(value).value end - end - threads << semaphore.async do - @result_b = worker_b.call(value_b) - end - threads.map(&:wait) + end.map(&:wait) ensure barrier.stop end - result_ab = "#{@results_a.sort.join('-')}-#{@result_b}" - worker_c.call(result_ab) end # Референсное решение, приведённое ниже работает правильно, занимает ~19.5 секунд @@ -77,34 +74,93 @@ def collect_sorted(arr) arr.sort.join('-') end +val1 = [11, 12, 13] +val2 = [21, 22, 23] +val3 = [31, 32, 33] + +@all_vall_a = [val1, val2, val3] +@all_vall_b = [1, 2, 3] + +@results_task_a = {} +@results_task_b = {} +@results_task_c = {} + +@threads = [] + +@threads << Thread.new { + @all_vall_a.each do |v| + start_worker(v, func_a, 3, @results_task_a) + end +} +@threads << Thread.new { start_worker(@all_vall_b, func_b ,2, @results_task_b) } + +@threads << Thread.new do + index_fetch = 0 + exists = [] + process = true + while process do + keys = @results_task_b.keys + unless keys.empty? + keys.each do |key| + next if exists.include?(key) + if key == 1 + if @results_task_a[11] && @results_task_a[12] && @results_task_a[13] + payload = "#{[@results_task_a[11], @results_task_a[12], @results_task_a[13]].sort.join("-")}-#{@results_task_b[key]}" + start_worker([payload], func_c ,1, @results_task_c) + exists << key + index_fetch += 1 + end + elsif key == 2 + if @results_task_a[21] && @results_task_a[22] && @results_task_a[23] + payload = "#{[@results_task_a[21], @results_task_a[22], @results_task_a[23]].sort.join("-")}-#{@results_task_b[key]}" + start_worker([payload], func_c ,1, @results_task_c) + exists << key + index_fetch += 1 + end + elsif key == 3 + if @results_task_a[31] && @results_task_a[32] && @results_task_a[33] + payload = "#{[@results_task_a[31], @results_task_a[32], @results_task_a[33]].sort.join("-")}-#{@results_task_b[key]}" + start_worker([payload], func_c ,1, @results_task_c) + exists << key + index_fetch += 1 + end + end + end + end + if index_fetch >= 3 + process = false + break + end + end +end start = Time.now +@threads.map(&:join) +result = a(@results_task_c.values.sort.join("-")).value +# ab1 = start_worker(val1, 1, func_a, func_b) +# # puts "AB1 = #{ab1}" +# c1 = c(ab1) +# # puts "C1 = #{c1}" -ab1 = start_worker(val, 1, func_a, func_b) -puts "AB1 = #{ab1}" - -c1 = c(ab1) -puts "C1 = #{c1}" +# # val = [21, 22, 23] -val = [21, 22, 23] +# ab2 = start_worker(val2, 2, func_a, func_b) +# # puts "AB2 = #{ab2}" -ab2 = start_worker(val, 2, func_a, func_b) -puts "AB2 = #{ab2}" +# c2 = c(ab2) +# # puts "C2 = #{c2}" -c2 = c(ab2) -puts "C2 = #{c2}" +# # val = [31, 32, 33] -val = [31, 32, 33] +# ab3 = start_worker(val3, 3, func_a, func_b) +# # puts "AB3 = #{ab3}" -ab3 = start_worker(val, 3, func_a, func_b) -puts "AB3 = #{ab3}" +# c3 = c(ab3) +# # puts "C3 = #{c3}" -c3 = c(ab3) -puts "C3 = #{c3}" - -c123 = collect_sorted([c1, c2, c3]) -result = a(c123) +# c123 = collect_sorted([c1, c2, c3]) +# result = a(c123) time = Time.now - start @@ -116,6 +172,6 @@ def collect_sorted(arr) raise ResultIsNotEq, "#{result} != #{expected_result}" end -if time > expected_time - raise TimeIsOverError, "#{time}" -end +# if time > expected_time +# raise TimeIsOverError, "#{time}" +# end From fa401846639150b6cad90b256df128eb93ff2705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A8=D0=BB=D1=8F=D0=BF=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B9=20=D0=9D=D0=B8=D0=BA=D0=BE?= =?UTF-8?q?=D0=BB=D0=B0=D0=B5=D0=B2=D0=B8=D1=87?= Date: Sun, 2 Mar 2025 11:26:49 +0300 Subject: [PATCH 3/3] Final optimisation tesk 5 --- client.rb | 35 +++++++---------------------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/client.rb b/client.rb index f84ced1..7316ba8 100644 --- a/client.rb +++ b/client.rb @@ -81,8 +81,11 @@ def collect_sorted(arr) @all_vall_a = [val1, val2, val3] @all_vall_b = [1, 2, 3] +# канал для метода a @results_task_a = {} +# канал для метода b @results_task_b = {} +# канал для метода c @results_task_c = {} @threads = [] @@ -94,6 +97,7 @@ def collect_sorted(arr) } @threads << Thread.new { start_worker(@all_vall_b, func_b ,2, @results_task_b) } +# тред который наблюдает за каналами и помере того как в них начинают приходить данные, начинает обращатся к ендпоинту `c` @threads << Thread.new do index_fetch = 0 exists = [] @@ -137,31 +141,6 @@ def collect_sorted(arr) @threads.map(&:join) result = a(@results_task_c.values.sort.join("-")).value -# ab1 = start_worker(val1, 1, func_a, func_b) -# # puts "AB1 = #{ab1}" - -# c1 = c(ab1) -# # puts "C1 = #{c1}" - -# # val = [21, 22, 23] - -# ab2 = start_worker(val2, 2, func_a, func_b) -# # puts "AB2 = #{ab2}" - -# c2 = c(ab2) -# # puts "C2 = #{c2}" - -# # val = [31, 32, 33] - -# ab3 = start_worker(val3, 3, func_a, func_b) -# # puts "AB3 = #{ab3}" - -# c3 = c(ab3) -# # puts "C3 = #{c3}" - -# c123 = collect_sorted([c1, c2, c3]) -# result = a(c123) - time = Time.now - start @@ -172,6 +151,6 @@ def collect_sorted(arr) raise ResultIsNotEq, "#{result} != #{expected_result}" end -# if time > expected_time -# raise TimeIsOverError, "#{time}" -# end +if time > expected_time + raise TimeIsOverError, "#{time}" +end