Skip to content

mgr/vol: some improvements for async_job.py#60002

Closed
rishabh-d-dave wants to merge 2 commits intoceph:mainfrom
rishabh-d-dave:mgr-vol-stopping
Closed

mgr/vol: some improvements for async_job.py#60002
rishabh-d-dave wants to merge 2 commits intoceph:mainfrom
rishabh-d-dave:mgr-vol-stopping

Conversation

@rishabh-d-dave
Copy link
Contributor

@rishabh-d-dave rishabh-d-dave commented Sep 26, 2024

Contribution Guidelines

  • To sign and title your commits, please refer to Submitting Patches to Ceph.

  • If you are submitting a fix for a stable branch (e.g. "quincy"), please refer to Submitting Patches to Ceph - Backports for the proper workflow.

  • When filling out the below checklist, you may click boxes directly in the GitHub web UI. When entering or editing the entire PR message in the GitHub web UI editor, you may also select a checklist item by adding an x between the brackets: [x]. Spaces and capitalization matter when checking off items this way.

Checklist

  • Tracker (select at least one)
    • References tracker ticket
    • Very recent bug; references commit where it was introduced
    • New feature (ticket optional)
    • Doc update (no ticket needed)
    • Code cleanup (no ticket needed)
  • Component impact
    • Affects Dashboard, opened tracker ticket
    • Affects Orchestrator, opened tracker ticket
    • No impact that needs to be tracked
  • Documentation (select at least one)
    • Updates relevant documentation
    • No doc update is appropriate
  • Tests (select at least one)
Show available Jenkins commands
  • jenkins retest this please
  • jenkins test classic perf
  • jenkins test crimson perf
  • jenkins test signed
  • jenkins test make check
  • jenkins test make check arm64
  • jenkins test submodules
  • jenkins test dashboard
  • jenkins test dashboard cephadm
  • jenkins test api
  • jenkins test docs
  • jenkins render docs
  • jenkins test ceph-volume all
  • jenkins test ceph-volume tox
  • jenkins test windows
  • jenkins test rook e2e

The attribute self.stopping of class AsyncJob is an instance of
threading.Event that is only used to set and check if it is set. For
such a case, threading.Event is an overkill, using a boolean variable
instead would suffice perfectly.

Signed-off-by: Rishabh Dave <ridave@redhat.com>
Signed-off-by: Rishabh Dave <ridave@redhat.com>
@rishabh-d-dave
Copy link
Contributor Author

jenkins test api

@rishabh-d-dave
Copy link
Contributor Author

jenkins test windows

@rishabh-d-dave
Copy link
Contributor Author

jenkins test make check arm64

@rishabh-d-dave
Copy link
Contributor Author

jenkins test api

@rishabh-d-dave
Copy link
Contributor Author

jenkins test windows

1 similar comment
@rishabh-d-dave
Copy link
Contributor Author

jenkins test windows

@rishabh-d-dave
Copy link
Contributor Author

jenkins test make check arm64

@rishabh-d-dave rishabh-d-dave added the wip-rishabh-testing Rishabh's testing label label Oct 1, 2024
@rishabh-d-dave
Copy link
Contributor Author

This PR is under test in https://tracker.ceph.com/issues/68354.

Copy link
Member

@batrick batrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The attribute self.stopping of class AsyncJob is an instance of
threading.Event that is only used to set and check if it is set. For
such a case, threading.Event is an overkill, using a boolean variable
instead would suffice perfectly.

huh? Why is it overkill?

@rishabh-d-dave
Copy link
Contributor Author

The attribute self.stopping of class AsyncJob is an instance of
threading.Event that is only used to set and check if it is set. For
such a case, threading.Event is an overkill, using a boolean variable
instead would suffice perfectly.

huh? Why is it overkill?

Events are used for thread synchronization. And since we aren't doing anything even remotely close there's no reason to use Event. A boolean variable exactly the job.

@batrick
Copy link
Member

batrick commented Oct 3, 2024

The attribute self.stopping of class AsyncJob is an instance of
threading.Event that is only used to set and check if it is set. For
such a case, threading.Event is an overkill, using a boolean variable
instead would suffice perfectly.

huh? Why is it overkill?

Events are used for thread synchronization. And since we aren't doing anything even remotely close there's no reason to use Event. A boolean variable exactly the job.

Except shutdown is called by another thread, no? So using an Event is necessary to construct a memory barrier.

@rishabh-d-dave
Copy link
Contributor Author

rishabh-d-dave commented Oct 4, 2024

The attribute self.stopping of class AsyncJob is an instance of
threading.Event that is only used to set and check if it is set. For
such a case, threading.Event is an overkill, using a boolean variable
instead would suffice perfectly.

huh? Why is it overkill?

Events are used for thread synchronization. And since we aren't doing anything even remotely close there's no reason to use Event. A boolean variable exactly the job.

Except shutdown is called by another thread, no? So using an Event is necessary to construct a memory barrier.

Right. But we don't use any features that class Event provides (like wait()). We only set and clear it, so using Event instance is pointless and boolean instance would work just fine.

@batrick
Copy link
Member

batrick commented Oct 7, 2024

The attribute self.stopping of class AsyncJob is an instance of
threading.Event that is only used to set and check if it is set. For
such a case, threading.Event is an overkill, using a boolean variable
instead would suffice perfectly.

huh? Why is it overkill?

Events are used for thread synchronization. And since we aren't doing anything even remotely close there's no reason to use Event. A boolean variable exactly the job.

Except shutdown is called by another thread, no? So using an Event is necessary to construct a memory barrier.

Right. But we don't use any features that class Event provides (like wait()). We only set and clear it, so using Event instance is pointless and boolean instance would work just fine.

Yes, you do.

https://github.com/python/cpython/blob/c5df1cb7bde7e86f046196b0e34a0b90f8fc11de/Lib/threading.py#L620-L629

Simply notifying on a condition variable will create a memory barrier. That is essential so that Event.is_set is correctly true on other threads.

@vshankar
Copy link
Contributor

Events are used for thread synchronization. And since we aren't doing anything even remotely close there's no reason to use Event. A boolean variable exactly the job.

I really would not bother micro-optimizing this code.

@rishabh-d-dave
Copy link
Contributor Author

Events are used for thread synchronization. And since we aren't doing anything even remotely close there's no reason to use Event. A boolean variable exactly the job.

I really would not bother micro-optimizing this code.

@vshankar
It's not about micro-optimizing code but about not being confused while reading it. Using event gives an impression that we intend to do some waiting somewhere but it's nowhere to be found in this codebase.

Copy link
Contributor Author

@rishabh-d-dave rishabh-d-dave left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vshankar
Copy link
Contributor

@vshankar
It's not about micro-optimizing code but about not being confused while reading it. Using event gives an impression that we intend to do some waiting somewhere but it's nowhere to be found in this codebase.

The point to note here is that event uses its own internal lock. Switching to boolean for this specific case is fine since it's a validation check for the while .. loop and note that calling shutdown() is not taking any locks. As I mention, it does not have a negative effect in this case, but at times it might.


def shutdown(self):
self.stopping.set()
self.stopping = True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is called by module shutdown (which is not even used anymore) but, despite that, the shutdown method would be called from a separate thread. (I mean, that's the entire point of a stopping flag. Why would you need it if it's only set by the thread itself?)

It's entirely conventional for a stopping flag on a thread to be a threading.Event. I really don't understand the motivation to change this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's entirely conventional for a stopping flag on a thread to be a threading.Event.

It is conventional to have lock on a boolean value when multiple threads will attempt to modify the boolean value. But since there's only one thread in this case, a boolean value without a lock is equally fine and therefore usage of threading.Event is unnecessary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, no. Anyone coming in the future that wants to stop threads now must play roulette with the cache lines hoping that the shutdown method actually does what you would think in a properly multi-threaded class.

I urge you to consider this to be defensive programming and let the matter rest. There is no real performance gain to squeeze from this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I urge you to consider this to be defensive programming

Defensive programming from the POV of possible future attempt to extend use of self.stopping is a good point.

There is no real performance gain to squeeze from this.

Performance was never the main concern for this PR.

@rishabh-d-dave
Copy link
Contributor Author

What has come up through discussions is that it's fine to merge this patch since in this particular case it would have no negative effect. But in order to prevent accidental introduction of bugs in future, we would like to take the defensive approach and not merge this patch. Closing this PR.

@rishabh-d-dave rishabh-d-dave deleted the mgr-vol-stopping branch October 24, 2024 13:33
@rishabh-d-dave rishabh-d-dave restored the mgr-vol-stopping branch January 27, 2025 13:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants