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

Minor performance tweaks #158

Merged
merged 1 commit into from
Jun 10, 2016
Merged

Minor performance tweaks #158

merged 1 commit into from
Jun 10, 2016

Conversation

virtuald
Copy link
Contributor

@virtuald virtuald commented Jun 6, 2016

The first one is pretty self-explanatory (maybe needs another PR?) -- only call time.time() once, the extra function overhead (despite how small it is) isn't necessary.

The second one we can debate, in the reader it now immediately calls _start_read() instead of going through the IOLoop to call it. This results in a ~1s improvement in my rawperf script. I think I understand why it was done this way originally -- presumably don't want to starve the IOLoop if messages just happen to come in at the perfect rate where the socket buffer can keep feeding messages... since the read functions will call each other continuously in a loop without yielding to the IOLoop.

But... I wonder if that can actually happen?

If it can happen... then perhaps it should only use add_callback every once in awhile, or if it detects a cycle... or some other probably terrible thing? At the very least, should add a note as to why the code is using add_callback here.

@mreiferson
Copy link
Member

@virtuald same question here - any statistically significant improvement here?

I worry about chasing micro-optimizations...

@mreiferson
Copy link
Member

Above question was w/r/t the time.time change, sorry.

re: the deferred read, I think the change is safe because _read_bytes just calls self.stream.read_bytes, which defers if necessary.

👍

@virtuald
Copy link
Contributor Author

virtuald commented Jun 6, 2016

The time.time change isn't significant.

Heh, well, it's clear that whomever wrote that code originally really wanted to make sure that it defers to the ioloop, since the test checks for it. I'll fix the test later today.

@@ -277,7 +277,7 @@ def _read_body(self, data):
self.trigger(event.DATA, conn=self, data=data)
except Exception:
logger.exception('uncaught exception in data event')
self.io_loop.add_callback(self._start_read)
Copy link
Member

Choose a reason for hiding this comment

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

I have several spots where i use several independent reader's on the same IOLoop so yielding is important to me. It's also important because calling things directly can lead to infinite call stacks. I think that makes me 👎 for this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that seems reasonable enough. I wonder if there's a more efficient way of doing this then?

Copy link
Member

Choose a reason for hiding this comment

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

I'm pretty sure it won't "block", it'll either immediately handle unprocessed (but read) bytes or it will defer and setup a callback.

http://www.tornadoweb.org/en/stable/_modules/tornado/iostream.html#BaseIOStream.read_bytes

This just skips an additional deferment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right -- the question I have is whether it's possible that enough data could be fed in at the right rhythm that would cause it to never defer. That's something I'm a bit unsure about.

Copy link
Member

Choose a reason for hiding this comment

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

From my scanning of the tornado code, I think it's functionally equivalent with one less deferment.

Copy link
Member

Choose a reason for hiding this comment

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

@mreiferson thanks for digging a little further. I agree, and that addresses my previous concern.

@mreiferson
Copy link
Member

Let's drop the time.time change if you don't mind.

Assuming @jehiah is amenable to the other change and we fix the failing test, this LGTM!

@virtuald
Copy link
Contributor Author

I fixed the tests... it looks like one of the tests on Travis failed with a spurious error (connection refused to nsqd), not totally sure what caused that.

@mreiferson
Copy link
Member

restarted those individual tests, let's see if we get a 🍏

@mreiferson
Copy link
Member

LGTM

@mreiferson mreiferson merged commit 55ea759 into nsqio:master Jun 10, 2016
@mreiferson
Copy link
Member

thanks!

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

Successfully merging this pull request may close these issues.

3 participants