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

Make it easier to avoid profiling startup code #329

Open
paddor opened this issue Jan 12, 2024 · 8 comments
Open

Make it easier to avoid profiling startup code #329

paddor opened this issue Jan 12, 2024 · 8 comments

Comments

@paddor
Copy link

paddor commented Jan 12, 2024

Suggestion:
It would be nice if the currently running RubyProf::Profile instance was available somehow, maybe through RubyProf::Profile.current, so it can be paused during startup of an application and resumed when the application is started (warmed up). That way, an app could do RubyProf::Profile.current.pause if defined?(RubyProf) before warmup and RubyProf::Profile.current.resume if defined?(RubyProf) after warmup.

Alternative suggestion:
Alternatively, a new option --start-paused could be introduced, which then can be resumed by the application after warmup using RubyProf::Profile.current.resume if defined?(RubyProf).

Reason:
Personally, I think that would be way more elegant than using -R, --require-noprof=lib or -E, --eval-noprof=code, which make it clumsy to preload something and use it later. You'd have to store the preloaded object in some global.
I noticed that the constant RubyProf is defined when running a script with ruby-prof my_script.rb. So there should be a way. Unfortunately @profile is not set in RubyProf if the CLI is used.

Advantage:
The advantage would be that the application does not need to manually/intrusively create a RubyProf::Profile after warmup. It could be done on the command line with ruby-prof and all profiling and output/formatting options would be available for free.

@cfis
Copy link
Member

cfis commented Jan 12, 2024

So the old/deprecated API more or less worked like that.

RubyProf.start
RubyProf.running?
RubyProf.pause
RubyProf.resume

But I wanted to move away from the shared global object instance.

@paddor
Copy link
Author

paddor commented Jan 12, 2024

Can there ever be more than one Profiles running at the same time in the same thread?

Tbh, I already fixed the problem using -R mygem/application/warmup. It'll warm up the app and store the preloaded object in MyGem::Application.preloaded_thing which is then later reused by the actual my_gem start. It's clumsy, but it works and allows me to remove the dedicated module MyGem::Profiling which would be called after warmup and just starts profiling, if and only if RubyProf is defined. So less clumsy, but still clumsy.

This does not have a high priority, of course.

@cfis
Copy link
Member

cfis commented Jan 13, 2024

Right, only one profile per thread. Probably only one profile period, never tested with having different threads with different profiles.

I don't think I'm really understanding your issue though. Since you have to write code to call profile.resume anyway, then why not just create and start the profile at that point (ie, after warmup)? Or are you profiling using the ruby-prof script and want it to start paused?

Edit - Just reread your original description:

Alternatively, a new option --start-paused could be introduced, which then can be resumed by the application after warmup using RubyProf::Profile.current.resume if defined?(RubyProf).

That works for me - happy to take a MR.

@paddor
Copy link
Author

paddor commented Jan 13, 2024

It's not a big issue, tbh. I'd have liked getting all the CLI options for free, instead of hardcoding a single mode and profiler.

MR = merge request? I'll have to take a look at the source of this gem first. Not familiar with it yet.

I'd have to:

  • make the current profile available through RubyProf::Profile.current
  • add an option --start-paused to the CLI which starts the profile as paused

My C isn't amazing...

@cfis
Copy link
Member

cfis commented Jan 13, 2024

I don't think there is any c code involved. You'd update the ruby-prof script to take a --start-paused parameter. The script creates a RubyProf::Cmd instance which has getter :profile.

So the then question is how to get that profile instance from some random place in your code base. One possible way is store it in a thread local variable (of course if your code has multiple threads, any child thread won't be able to get at it.

Another way I suppose is store it in a global constant:

class CMD
PROFILE = ..
end

You'll get warnings from Ruby setting a constant. Or you could store the profile at the class level:

def self.profile=(value)
@Profile = value
end

Etc...you get the idea.

@cfis
Copy link
Member

cfis commented Feb 13, 2024

Hi @paddor - just wondering how you want to proceed? Sorry this got bogged down a bit.

@paddor
Copy link
Author

paddor commented Feb 14, 2024

Sorry, couldn't find the time anymore. To me this is now low priority as I've solved it in the meantime. Should I close these for now?

@cfis
Copy link
Member

cfis commented Feb 15, 2024

No worries. I'll keep this open for now. Thanks for using ruby-prof!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants