activegraph icon indicating copy to clipboard operation
activegraph copied to clipboard

Migration check affects rails performance in test and production

Open yourpalal opened this issue 3 years ago • 0 comments

When used in rails, a middleware is added to the rack server which negatively affects performance.

CheckPending performance

On every rails request, including in production, the list of migrations is found via ActiveGraph::Migrations::Runner#latest_migration. This method transitively calls the files method, which checks the filesystem for migration files and parses the name of each migration.

In a production setting, the actual pending migrations check will only happen the first time the middleware runs, but the performance hit of calling latest_migration will be added to every request.

I noticed the performance hit of this call while profiling a test suit with stackprof flamegraphs. It seems to take more time than many queries! By instrumenting the call to latest_migration and measuring it with stackprof, I found that it accounted for 3.5% of the duration of one of our api request spec files. Each call takes approximately 5-7ms on my machine - longer than most sql or neo4j queries.

Configuration

Pending migrations checks are configured according to two configuration options:

  • skip_migration_check : defaults to nil, set to true in rails test environments. This flag is checked before checking for pending migrations in check_for_pending_migrations!. Documented in readthedocs
  • fail_on_pending_migrations: defaults to true in rails (all environments). Adds the ActiveGraph::Migrations::CheckPending middleware, which causes the check to run on every request. Does not appear to be documented in readthedocs.

What could be improved

Rails.env == 'test'

In a rails test environment, skip_migration_check is set to nil (false), meaning no error will be raised, but fail_on_pending_migrations is set to true, meaning the middleware will be added anyway!

An improvement for this case would be to set fail_on_pending_migrations to false in rails test environments, or whenever skip_migration_check is set to false. There's really no need to run the middleware when it's never going to raise an error.

This will speed up rails test suites a bit, which is nice!

Rails.env == 'production'

Another improvement could be to modify the checkpending middleware to avoid repeated latest_migration calls in production. This could be done by either:

  • removing the middleware after the first check
  • caching latest_migration

Workaround

Setting config.neo4j.fail_on_pending_migrations to false will allow you to avoid the middleware altogether. This does however mean that you lose the protection it provides

yourpalal avatar Jun 28 '21 19:06 yourpalal