magefile / mage

a Make/rake-like dev tool using Go
https://magefile.org
Apache License 2.0
4.12k stars 251 forks source link

Bug: Performance of Mage Dependent on Installation Style? #404

Closed sheldonhull closed 2 years ago

sheldonhull commented 2 years ago

Bug Description I'm seeing some long-run times in a few environments for a moderate sized monorepo I have.

What did you do?

run mage.

What did you expect to happen?

Run mage and it should be very quick to return list of tasks.

What actually happened?

macOS

Environment

Additional context

Low priority, just wanted to raise this up so I can update it if I run into any further issues on compile time that seem to point towards a specific environment or setup.

ladydascalie commented 2 years ago

Mage generates a cache on first run.

It is likely that without this cache, your first run was slow, and then subsequent uses, even with a different installation method, still made use of this cache.

If you run mage -h, you should see a -clean option allowing you to clean old generated binaries. I would consider trying this experiment again, but running -clean each time to see if this is cache related or not.

natefinch commented 2 years ago

The binary is still the same code, the way you install should not matter at all. IIs this something you were able to reproduce, @sheldonhull ?

sheldonhull commented 2 years ago

@natefinch Close it for now. If I can reproduce I'll reopen with more detail. Not sure if specific to mage or security scanning software is to blame.

sheldonhull commented 2 years ago

I'll add a follow-up that I need to investigate the caching behavior more in the near future since I use Mage so much. Without setting MAGEFILE_HASHFAST=1 it tends to take a while to run even normal commands despite no changes to the Magefiles. I haven't quantified this, but it's more experience oriented. No need to reopen, but if I find something concrete I'm going to add it here.

natefinch commented 2 years ago

My guess is that this is because your magefile imports so much stuff, that it just has a lot to compile. And unfortunately, the go compiler has to do kind of a lot of work even to tell that it doesn't need to do any more work.

If you run with -debug, it prints out timestamps as it runs, and you can see where the most time is taken. My guess is that it's all the go compiler, figuring out if it needs to recompile or not. It's not as fast as it probably should be.

sheldonhull commented 2 years ago

@natefinch if there are no magefile changes, isn't the cached file supposed to be used and operate the same as MAGEFILE_HASHFAST=1 though? That's the big question I guess. I get that rebuilding -f takes 5-10 seconds if it's a big monorepo. However, I'd though the cached output file already being ready to go would be used. I think I need to look into Mage's source so I'm less ignorant on that and might better understand it then.

edit: Is the caching purely the "output file" or is it also caching the binary?

natefinch commented 2 years ago

By default (with MAGEFILE_HASHFAST off), Mage generates the mainfile and runs go build <generated_main> <magefile1> <magefile2> <...> -o=<cached_binary>, relying on the go tool's built-in logic for determining when to rebuild or not.

Generating the main file is fast, so we don't bother caching/skipping that part. The slowness comes from the go tool itself doing whatever magic it does to determine if it needs to rebuild. This seems to be slower on some platforms than others. I have heard many people talking about go building slower on windows, for example.

With HASHFAST on, mage generates the main file and then hashes the contents of that with the contents of all the other magefiles that comprise package main for the magefile. This is very fast, but will 100% fail to rebuild if you change the code in an imported package.

It's a tough line to walk, because I don't want to try to reimplement the go tool's logic for whether or not to rebuild. That's why hashfast is so simplistic. It's completely obvious when it will rebuild and when it will not, rather than trying to get fancy about detecting changes in dependencies etc.

sheldonhull commented 2 years ago

Got you. So in my case then I'll stick with direnv setting my MAGEFILE_HASHFAST=1 always, because I'm pretty much the primary author of the magefiles and know whenever I need to tweak to run with -f flag. This helps. Thank you!

natefinch commented 2 years ago

I definitely would encourage you to look at the -debug output and make sure that the time is really being spent by the go tool... but I bet it is.