Skip to content

[BEAM-2724] Preparing statesampler to work with structured names#3786

Closed
pabloem wants to merge 7 commits intoapache:masterfrom
pabloem:ssampler-structured
Closed

[BEAM-2724] Preparing statesampler to work with structured names#3786
pabloem wants to merge 7 commits intoapache:masterfrom
pabloem:ssampler-structured

Conversation

@pabloem
Copy link
Copy Markdown
Member

@pabloem pabloem commented Aug 29, 2017

No description provided.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage remained the same at 69.968% when pulling 9375dd6 on pabloem:ssampler-structured into 6280d49 on apache:master.

@pabloem
Copy link
Copy Markdown
Member Author

pabloem commented Aug 30, 2017

Note: This PR is not yet ready for review and merge.

@pabloem pabloem force-pushed the ssampler-structured branch 2 times, most recently from fc6a119 to 9e6f3c0 Compare September 21, 2017 16:15
@pabloem pabloem changed the title Preparing statesampler to work with structured names [BEAM-2724] Preparing statesampler to work with structured names Sep 21, 2017
@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage decreased (-0.01%) to 69.546% when pulling 9e6f3c0 on pabloem:ssampler-structured into a92c45f on apache:master.

@pabloem
Copy link
Copy Markdown
Member Author

pabloem commented Sep 21, 2017

r: @charlesccychen
cc: @bjchambers
This changes the state sampler to rely on structured names for MSEC counters.

The new io_target argument allows states to track time spent in IO such as side inputs, shuffle and state. Tests have passed , and the latest commit only updates documentation.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage decreased (-0.02%) to 69.54% when pulling b3d629f on pabloem:ssampler-structured into a92c45f on apache:master.

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage decreased (-0.03%) to 69.525% when pulling b6e7964 on pabloem:ssampler-structured into a92c45f on apache:master.

Copy link
Copy Markdown
Contributor

@charlesccychen charlesccychen left a comment

Choose a reason for hiding this comment

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

Thanks!

stage_name=self.prefix,
step_name=step_name,
io_target=io_target)
scoped_state = self.scoped_states_by_name.get(counter_name, None)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We are conflating the type of what can be used as keys in self.scoped_states_by_name. Previously, this was just strings, but now, you are using this CounterName object, which doesn't seem correct. The CounterName class doesn't define __hash__() or even __cmp__() / __eq__(), so it is possible for you to create two semantically identical CounterName objects which do not compare as equal, and are not considered the same key by the self.scoped_states_by_name dict object.

This is related to the comment above noting that sometimes counter_name in this code is a CounterName, and at other times, it is a string. We should make this code unambiguous in this respect.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The CounterName class is a subclass of a namedtuple (which, itself contains only strings or other namedtuples) - therefore it does implement the __hash__, __eq__, and __cmp__. So two objects that are semantically equal will hash to the same value. So this should be safe.

Does that make sense? What do you think?

if state_name is None:
# If state_name is None, the worker is still using old style
# msec counters.
counter_name = '%s-%s-msecs' % (self.prefix, step_name)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be '%s%s-msecs' to preserve the old behavior?

Also, there is some confusion in this code, in this legacy case where only step_name is provided, in what is used to index into self.scoped_states_by_name (i.e., is it step_name as you do on line 203, or is it counter_name, as done on line 223?).

It is also a little messy that counter_name can be either a string (this branch) or a CounterName object (the else branch)...

Copy link
Copy Markdown
Member Author

@pabloem pabloem Sep 25, 2017

Choose a reason for hiding this comment

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

  1. You can see on line 117 that we're chopping off the dash from prefixes, so now we add the dash here. I'm doing this to add the dash-free prefix to the CounterStructuredName that's reported to the service. This is only necessary while the clients stop using the legacy path.

  2. You are completely right about the confusion. Good catch. I've updated the code to reflect this.

  3. I understand. This is temporary while all the clients start providing state_name. This should take less than a couple weeks once this change is pulled in - and then the legacy path can be removed fully.

def scoped_state(self, name):
"""Returns a context manager managing transitions for a given state."""
cdef ScopedState scoped_state = self.scoped_states_by_name.get(name, None)
def scoped_state(self, step_name, state_name=None, io_target=None):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please add TODO to make state_name a required parameters after all callers have migrated.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

counter_name = '%s-%s-msecs' % (self.prefix, step_name)
scoped_state = self.scoped_states_by_name.get(step_name, None)
else:
counter_name = CounterName(state_name+'-msecs',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: space before and after +.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

scoped_state.nsecs = 0
pythread.PyThread_release_lock(self.lock)
self.scoped_states_by_name[name] = scoped_state
self.scoped_states_by_name[counter_name] = scoped_state
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please see above comments regarding the actual type of counter_name.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Addressed.

Copy link
Copy Markdown
Member Author

@pabloem pabloem left a comment

Choose a reason for hiding this comment

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

Comments addressed. Thanks for your time. Let me know what you think.

def scoped_state(self, name):
"""Returns a context manager managing transitions for a given state."""
cdef ScopedState scoped_state = self.scoped_states_by_name.get(name, None)
def scoped_state(self, step_name, state_name=None, io_target=None):
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

if state_name is None:
# If state_name is None, the worker is still using old style
# msec counters.
counter_name = '%s-%s-msecs' % (self.prefix, step_name)
Copy link
Copy Markdown
Member Author

@pabloem pabloem Sep 25, 2017

Choose a reason for hiding this comment

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

  1. You can see on line 117 that we're chopping off the dash from prefixes, so now we add the dash here. I'm doing this to add the dash-free prefix to the CounterStructuredName that's reported to the service. This is only necessary while the clients stop using the legacy path.

  2. You are completely right about the confusion. Good catch. I've updated the code to reflect this.

  3. I understand. This is temporary while all the clients start providing state_name. This should take less than a couple weeks once this change is pulled in - and then the legacy path can be removed fully.

counter_name = '%s-%s-msecs' % (self.prefix, step_name)
scoped_state = self.scoped_states_by_name.get(step_name, None)
else:
counter_name = CounterName(state_name+'-msecs',
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done.

stage_name=self.prefix,
step_name=step_name,
io_target=io_target)
scoped_state = self.scoped_states_by_name.get(counter_name, None)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The CounterName class is a subclass of a namedtuple (which, itself contains only strings or other namedtuples) - therefore it does implement the __hash__, __eq__, and __cmp__. So two objects that are semantically equal will hash to the same value. So this should be safe.

Does that make sense? What do you think?

scoped_state.nsecs = 0
pythread.PyThread_release_lock(self.lock)
self.scoped_states_by_name[name] = scoped_state
self.scoped_states_by_name[counter_name] = scoped_state
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Addressed.

Copy link
Copy Markdown
Contributor

@charlesccychen charlesccychen left a comment

Choose a reason for hiding this comment

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

Thanks, this LGTM after nit.

def scoped_state(self, name):
"""Returns a context manager managing transitions for a given state."""
cdef ScopedState scoped_state = self.scoped_states_by_name.get(name, None)
# TODO(pabloem) - Make state_name required once all callers migrate,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: Can you change this to follow the project style of # TODO(XXX): YYY?

stage_name=self.prefix,
step_name=step_name,
io_target=io_target)
scoped_state = self.scoped_states_by_name.get(counter_name, None)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

pabloem wrote:
The CounterName class is a subclass of a namedtuple (which, itself contains only strings or other namedtuples) - therefore it does implement the __hash__, __eq__, and __cmp__. So two objects that are semantically equal will hash to the same value. So this should be safe.

Does that make sense? What do you think?

Thanks! I missed the inheritance--this makes sense. It will be much less confusing once we remove the first branch so that we can say that self.scoped_states_by_name is always keyed by CounterName.

@charlesccychen
Copy link
Copy Markdown
Contributor

R: @bjchambers for merge

@pabloem pabloem closed this Sep 26, 2017
@pabloem pabloem reopened this Sep 26, 2017
@pabloem pabloem closed this Sep 26, 2017
@pabloem pabloem reopened this Sep 26, 2017
@pabloem pabloem closed this Sep 26, 2017
@pabloem pabloem reopened this Sep 26, 2017
@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage decreased (-0.02%) to 69.537% when pulling 8cf66aa on pabloem:ssampler-structured into a92c45f on apache:master.

@pabloem pabloem closed this Sep 27, 2017
@pabloem pabloem reopened this Sep 27, 2017
@pabloem pabloem closed this Sep 27, 2017
@pabloem pabloem reopened this Sep 27, 2017
@pabloem pabloem force-pushed the ssampler-structured branch from 8cf66aa to 1454095 Compare September 27, 2017 17:34
@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.03%) to 69.572% when pulling 1454095 on pabloem:ssampler-structured into 41239d8 on apache:master.

@pabloem pabloem force-pushed the ssampler-structured branch from 1454095 to 29829fe Compare October 2, 2017 20:26
@pabloem
Copy link
Copy Markdown
Member Author

pabloem commented Oct 2, 2017

Run Python PostCommit

@pabloem
Copy link
Copy Markdown
Member Author

pabloem commented Oct 2, 2017

jenkins: retest this please

@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage remained the same at 69.568% when pulling 29829fe on pabloem:ssampler-structured into 4a5b3c0 on apache:master.

@asfgit asfgit closed this in f9bc763 Oct 3, 2017
@pabloem pabloem deleted the ssampler-structured branch October 3, 2017 18:08
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

Successfully merging this pull request may close these issues.

4 participants