motion
motion copied to clipboard
Slow application startup times in some projects
Hey, awesome work with motion. After spending so much time on React and the 'front end rendering revolution' i think it's about time for a 'back end rendering revolution' :)
Front end code via back end ruby, that's just pure magic :D
Anyway, I'm not sure if this is normal or something wrong with my setup, but it takes at least 5 minutes to start the rails server locally.
Before I installed motion it was about 5 seconds or so.
Wondering this is so long and if normal, will there be speed improvement in this in the future?
Thanks.
Hmm, that has not been my experience. It sounds like a bug.
@ernest4 Does this happen for you locally with the motion-demos project?
Cool. I'll try to get those running and see.
So the the motion-demos start up quick for me, in a few seconds as normal. But my own project takes minutes.
@ernest4 Are you able to reproduce the problem in a minimal project that you are willing to share publicly so that I can take a look?
I'm a long time lurker, first time issue poster on Github, so I'll give it a try :D
I just basically fork my own project repo and strip out as much as I can while the issue still appears to happen right.
Could be a while, since i'll need to strip out bit by bit until I see the issue disappears.
I'll try that later today 👍
So good news is my start up time is quick again. Bad news is I don't know what the issue was.
All I did was pull down my own repo into another folder in preparation to take things out. Then ran rails server and started up in seconds.
Tried the same with the old project folder - still slow.
Something other must be up with that old project folder, just noticed that sidekiq was also unable to start quickly (or at all, didn't wait forever to find out), while it started fine on the new folder.
So, while still a mystery, I guess it's not a motion specific issue. Sorry about about that :D
@ernest4 one thing I've noticed can have an effect on startup time is your bootsnap cache. Especially if you've upgraded ruby versions without clearing it out. You can safely delete the bootsnap folder and file inside #{Rails.root}/tmp/cache
and retry to see if it was that. A fresh checkout to a new directory would definitely act like you describe - faster for no reason.
Seems like a good theory, especially as the repo doesn't have the tmp folder and neither does the new project folder.
But I've deleted tmp and it didn't seem improve the situation.
I try to ls -lah and delete any other extra file I've found that the old repo has an new one doesnt, but no luck.
Not sure if mine is a version compatibility issue (running rails 5.2.2 with ruby 2.5.1 for reference) the readme makes reference to rails 6.1, but doesn't explicitly state it as a requirement (if it is, please correct me) -- but I experience the same issue @ernest4 described. I'm still testing, but as soon as I delete the motion initializer config my web server launches in ~5 seconds (compared to several minutes with it included).
That's interesting. At first I thought that was gonna be the issue too.
Originally I was running ruby 2.6.3 with rails ~> 6.0.
When I pulled down the motion-demos and saw ruby 2.7.1 thought that was gonna be it.
So then I update the old project to ruby 2.7.1 but still no joy.
So not sure if it's the version issue specifically. But you should try just cloning your own repo fresh and see if that fixes it :D
If it does, I'd call that the real rails magic :D
Ok so w.e. is going, must be motion related. I just did what @spencersteiner just said, comment out the motion initializer in the old project and now it's booting in seconds again.
Uncomment the motion initializer and back to minutes.
Running the default motion initializer, haven't changed it at all and looks like it's doing nothing anyway since the block inside is all commented out? So really bizarre.
@ernest4 and/or @spencersteiner : Does adding config.revision = "dummy"
to your Motion.configure
block remove the lag?
@alecdotninja Yeah it does, ha! I wonder why the empty config leaves it hanging.
Can confirm, that fixes it @alecdotninja
but then the real question is, why does pulling down the same repo and without setting config.revision in motion initializer still work as well :D ?
Okay, the problem must be related to computing the revision hash then.
If you are using git and have it available in production (make sure to check!), a better workaround would be to use:
config.revision = `git rev-parse HEAD`.chomp
@ernest4 Setting the revision
to a constant string only looks like it works. It breaks Motion's ability to detect when a deployment has occurred in production. This matters because, if you don't handle this explicitly, you can end up with old state and new code which often leads to unexpected behavior.
If you want your component to survive deployments, you can provide a custom implementation for the upgrade_from
class method.
@ernest4 and/or @spencersteiner : Do you have any large files in your project directory? Also, do you mind sharing the output of du -a | sort -n -r | head
?
So setting config.revision = `git rev-parse HEAD`.chomp
is prefered if using git then?
Not sure what constitutes as 'large' file exactly?

this is the old repo.
This is the new repo.

Some things look suspiciously large in the old repo huh?
-
Isn't using
config.revision = `git rev-parse HEAD`.chomp
not potentially problematic in development as changes in code won't stop old components from connecting? -
the initializer mentions:
# Motion needs to be able to uniquely identify the version of the running
# version of your application. By default, the commit hash from git is used,
# but depending on your deployment, this may not be available in production.
But it seems only Motion::Serializer is being used? (Doubling Rails startup time in my case)
- Is there a reason not to put
config.revision = Time.now.to_i.to_s unless Rails.env.production?
in the initializer? At first sight it seems to solve the risk in dev env, the speed issue in dev and test environment and lets the default handle production.
Oh, "By default, the commit hash from git is used, but depending on your deployment, this may not be available in production." is no longer true since #12 . However, what Motion does by default is correctly described in the immediately following paragraph:
# Motion automatically calculates your revision by hashing the contents of
# files in `revision_paths` The defaults revision paths are:
# rails paths, bin, and Gemfile.lock.
@caifara
Isn't using config.revision =
git rev-parse HEAD
.chomp not potentially problematic in development as changes in code won't stop old components from connecting?
Development is a bit of a special case because of live reloading. Since channels are long-lived, you don't get the new version of the component in development until you refresh the page (which forces the connection to close and reopen). I actually like this personally. It corresponds to my intuition that refreshing the page gets the new code.
That said, you are right: If you manually restart your server while you have an old component mounted (this is analogous to a production deployment), config.revision = `git rev-parse HEAD`.chomp
could cause problems when your working directory is not clean. The default behavior of recalculating the hash when the server starts up does handle this correctly though since the revision will change.
Is there a reason not to put
config.revision = Time.now.to_i.to_s unless Rails.env.production?
in the initializer? At first sight it seems to solve the risk in dev env, the speed issue in dev and test environment and lets the default handle production.
This is a very interesting idea! As a temporary workaround, I think it is fine. The only downside that comes to mind is that it will never allow components to recover when restarting your dev server. It also depends on git being available in production (this is not true in Heroku, Mina/Capistrano-based deploys, and every container setup I have seen.
I still think the ideal solution here is to figure out why this is slow for some projects and correct it. There is no reason it should slow down production startup.
@alecdotninja I don't know whether we have slow startup times in production. Problem was more that testing and development became really slow as every bin/rails s
or bin/rspec …
took double the time. As long as this may be the case when motion gets added to new projects, I guess adoption rates will suffer. (Which really would be a shame!)
config.revision = Time.now.to_i.to_s unless Rails.env.production?
will, in production, use the normal revision calculator, so there actually wouldn't be a git dependency?
Of course, if the revision calculator wouldn't take up so much time, it would be a no brainer to use it in all environments. I'll try to find some time and find what takes so long in our project using the revision calculator.
@alecdotninja The paths include logs and tmp. Wouldn't it be better to ignore paths that are added to gitignore? Maybe with https://github.com/highb/pathspec-ruby?