Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slow application startup times in some projects #46

Open
ernest4 opened this issue Sep 8, 2020 · 24 comments
Open

Slow application startup times in some projects #46

ernest4 opened this issue Sep 8, 2020 · 24 comments
Labels
bug Something isn't working

Comments

@ernest4
Copy link

ernest4 commented Sep 8, 2020

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.

@alecdotninja alecdotninja self-assigned this Sep 8, 2020
@alecdotninja alecdotninja added bug Something isn't working question Further information is requested and removed question Further information is requested labels Sep 8, 2020
@alecdotninja
Copy link
Contributor

alecdotninja commented Sep 8, 2020

Hmm, that has not been my experience. It sounds like a bug.

@ernest4 Does this happen for you locally with the motion-demos project?

@alecdotninja alecdotninja added question Further information is requested and removed bug Something isn't working labels Sep 8, 2020
@ernest4
Copy link
Author

ernest4 commented Sep 8, 2020

Cool. I'll try to get those running and see.

@ernest4
Copy link
Author

ernest4 commented Sep 8, 2020

So the the motion-demos start up quick for me, in a few seconds as normal. But my own project takes minutes.

@alecdotninja
Copy link
Contributor

alecdotninja commented Sep 9, 2020

@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?

@ernest4
Copy link
Author

ernest4 commented Sep 9, 2020

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 👍

@ernest4
Copy link
Author

ernest4 commented Sep 9, 2020

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

@latortuga
Copy link
Member

@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.

@ernest4
Copy link
Author

ernest4 commented Sep 9, 2020

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.

@spencersteiner
Copy link

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).

@ernest4
Copy link
Author

ernest4 commented Sep 9, 2020

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

@ernest4
Copy link
Author

ernest4 commented Sep 9, 2020

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.

@alecdotninja alecdotninja added bug Something isn't working and removed question Further information is requested labels Sep 9, 2020
@alecdotninja alecdotninja changed the title Start up time question. Slow bootup time with some versions of Rails and Ruby Sep 9, 2020
@alecdotninja
Copy link
Contributor

@ernest4 and/or @spencersteiner : Does adding config.revision = "dummy" to your Motion.configure block remove the lag?

@spencersteiner
Copy link

@alecdotninja Yeah it does, ha! I wonder why the empty config leaves it hanging.

@ernest4
Copy link
Author

ernest4 commented Sep 9, 2020

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 ?

@alecdotninja alecdotninja changed the title Slow bootup time with some versions of Rails and Ruby Performance cliff when automatically calculating revision Sep 9, 2020
@alecdotninja
Copy link
Contributor

alecdotninja commented Sep 9, 2020

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.

@alecdotninja
Copy link
Contributor

@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?

@ernest4
Copy link
Author

ernest4 commented Sep 9, 2020

So setting config.revision = `git rev-parse HEAD`.chomp is prefered if using git then?

@ernest4
Copy link
Author

ernest4 commented Sep 9, 2020

Not sure what constitutes as 'large' file exactly?

@ernest4
Copy link
Author

ernest4 commented Sep 9, 2020

Screenshot 2020-09-09 at 21 24 28

this is the old repo.

@ernest4
Copy link
Author

ernest4 commented Sep 9, 2020

This is the new repo.

Screenshot 2020-09-09 at 21 25 26

Some things look suspiciously large in the old repo huh?

@alecdotninja alecdotninja removed their assignment Sep 10, 2020
@caifara
Copy link

caifara commented Sep 23, 2020

  • 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.

@alecdotninja
Copy link
Contributor

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 alecdotninja changed the title Performance cliff when automatically calculating revision Slow application startup times in some projects Sep 23, 2020
@caifara
Copy link

caifara commented Sep 24, 2020

@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.

@caifara
Copy link

caifara commented Sep 24, 2020

@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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants