Git Product home page Git Product logo

Comments (4)

BMorearty avatar BMorearty commented on May 21, 2024 2

@ioquatix I noticed you wrote code like this in your Ruby Gems Source Code Analysis and was thinking it'd be useful if this were documented.

My feedback is that I think we would have a need for this. It's useful to be able to set a limit on the number of simultaneous async operations, for various reasons including:

  • prevent DOS on myself by creating an arbitrarily large number of fibers
  • prevent DOS on servers that my code calls

I do find this API pretty hard to wrap my head around, though. I see how it works but I'd have to think about it every time I see the code.

from async.

bryanp avatar bryanp commented on May 21, 2024

I do find this API pretty hard to wrap my head around, though. I see how it works but I'd have to think about it every time I see the code.

This was my first impression as well. If this is expected to be a common pattern, would it be worth supporting it more directly? Maybe some new object that behaves like a queue but also has a Barrier and Semaphore internally:

instance = Async::QueueLikeObject.new(10)

instance.async do |item|
  ...
end

instance.wait

from async.

ioquatix avatar ioquatix commented on May 21, 2024

I'm definitely a fan of composition of simple objects, so I'd avoid things like QueueLikeObject in the core async code, but have no issue of building those more complex abstractions in user code where it makes sense.

The reason why I ended up with this kind of composition is it naturally emerged from the need to control flow and limits...

The reason why I was unsure about it, is because injecting a barrier into a semaphore kind of seems odd to me. It's actually not necessary as long as you only want to go one level deep, e.g.

barrier = Async::Barrier.new
semaphore = Async::Semaphore.new(10)

queue.each do |item|
	semaphore.async(parent: barrier) do	
		# Do something with item...
	end
end

# Wait for all outstanding tasks.
barrier.wait

But as soon as you want to do more complex things, or even just inject a barrier into code that takes a parent task, it can get more complicated:

	x.report("async-http (pipelined)") do
		Async do |task|
			internet = Async::HTTP::Internet.new
			semaphore = Async::Semaphore.new(100, parent: task)
			barrier = Async::Barrier.new(parent: semaphore)
			
			# Warm up the connection pool...
			response = internet.get(URL)
			response.read
			
			i = 0
			while i < REPEATS
				barrier.async do
					response = internet.get(URL)
					
					response.read
				end
				
				i += 1
			end
			
			barrier.wait
		ensure
			internet&.close
		end
	end

In the above benchmark, we bind the semaphore to the task. Then we bind the barrier to the semaphore.

That way, we avoid dynamically looking up Task.current for every iteration, and we also bind to a specific task from the POV of the task hierarchy. It's suggested that most top level entry points take a parent: Task.current keyword argument, which allows users to control the task tree and resource usage, and now it's relatively trivial to provide a semaphore or barrier or any kind of nested task allocation strategy.

from async.

ioquatix avatar ioquatix commented on May 21, 2024

Okay, I am planning to merge this.

from async.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.