Coder Social home page Coder Social logo

Comments (17)

ohler55 avatar ohler55 commented on June 11, 2024 3

Both sound like good ideas. Look for those additions in the near future.

from agoo.

frvade avatar frvade commented on June 11, 2024 2

Hi there!
I came across from the web page benchmark page (congrats with being the fastest in ruby). Running the Rails app in clustered mode would require to have at least before_fork hook as normally this is the place to close any connections that would be corrupted in the parent on child process exit. Like that

before_fork do
  Sequel::DATABASES.each(&:disconnect)
end

Also it would be nice to have some kind of an after_worker_fork callback to have the opportunity to do some work in the context of new spawned worker

from agoo.

ohler55 avatar ohler55 commented on June 11, 2024 1

I'll look into it this weekend. My unit tests worked last time I check so with any luck there is some configuration addition that is needed.

from agoo.

ohler55 avatar ohler55 commented on June 11, 2024

It worked for me on dedicated hardware, my laptop. Does ./bin/agoo -p 8080 -t 8 work on on one of you machines when not using docker?

A couple of points though. You will probably find that making the thread count too high actually decreases performance. The bottleneck on a single process is the Ruby global lock. Having more than somewhere around 8 just mean more context switching and threads tied up waiting. I usually do some benchmarking with an app and try to find the optimum number. Then increase the worker count.

from agoo.

stakach avatar stakach commented on June 11, 2024

Our app is IO bound so more threads mean we can do processing while waiting for IO to complete

I'm thinking the issue might be related to database connections and forking - I think puma forks before rails is loaded unless preload_app! is called and we're not calling that as it was too challenging to coordinate various gems initialisation

Which basically means we're sacrificing memory savings that can be gained with forking

from agoo.

ohler55 avatar ohler55 commented on June 11, 2024

IO bound outside Ruby I take it. Makes sense.

If the database connection is being made before forking I could see how that could be a problem. Agoo is independent of rails so I'm not sure when it gets initialized relative to Agoo. Depends on how it is started I suppose. I would be interested in exploring options that would make it work for you if you want to pursue this. I think the next step might be instrumenting the code with some print statements to figure out when database connections are made and when forking occurs. See if your theory is correct and after that figure out what can be added to Agoo to allow the database connections to be made after forking.

from agoo.

ohler55 avatar ohler55 commented on June 11, 2024

A fork_wrap option was added in the develop branch. Please give it a try.

from agoo.

ohler55 avatar ohler55 commented on June 11, 2024

No response, closing.

from agoo.

xenyal avatar xenyal commented on June 11, 2024

Hi @ohler55!

I was wondering if it might be possible to differentiate between when a worker is forked vs. when a worker is booted - I'm trying to migrate from Puma to Agoo, and in my containerized Rails environment, we have the following:

before_fork do
  ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord)
end

on_worker_boot do
  ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
end

Do you have any examples on how that can be migrated to use the new fork_wrap option?
Thanks!

from agoo.

ohler55 avatar ohler55 commented on June 11, 2024

What does it mean to have a worker booted versus the app being forked?

from agoo.

xenyal avatar xenyal commented on June 11, 2024

Based on the puma documentation:

before_fork - If you are preloading your application and using Active Record, it's recommended that you close any connections to the database before workers are forked to prevent connection leakage.

on_worker_boot - The code in the on_worker_boot will be called if you are using clustered mode by specifying a number of workers. After each worker process is booted, this block will be run. If you are using the preload_app! option, you will want to use this block to reconnect to any threads or connections that may have been created at application boot, as Ruby cannot share connections between processes.

So both options seem to account for the possibility of the app being preloaded when running in clustered mode, where the app boot and code loading happens before the workers are forked, as a means to reduce memory footprint - however without setting the on_worker_boot, leaves the possibility of threads not being connected to the database yet

from agoo.

xenyal avatar xenyal commented on June 11, 2024

Since we wouldn't be preloading the app with agoo, I guess the on_worker_boot doesn't matter - we would only need to ensure that ActiveRecord is disconnected before_fork, and that it's connected after_fork between the master and worker processes: https://devcenter.heroku.com/articles/concurrency-and-database-connections#multi-process-servers - can that be achieved in the fork_wrap option?

from agoo.

ohler55 avatar ohler55 commented on June 11, 2024

If a forker object is set the before method will be called before forking and the after will be called after forking. I think that should work for you, yes?

from agoo.

xenyal avatar xenyal commented on June 11, 2024

@ohler55 that would be perfect!

from agoo.

ohler55 avatar ohler55 commented on June 11, 2024

Right, that is the current behavior.

from agoo.

xenyal avatar xenyal commented on June 11, 2024

Where might the before block be defined for agoo's config if running as part of Rails through rackup?

from agoo.

ohler55 avatar ohler55 commented on June 11, 2024

Look at example/quux.rb.

from agoo.

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.