Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork185
Fix #338 os.writev() instead of os.write(b.join()) and sendmsg() instead of send()#339
Uh oh!
There was an error while loading.Please reload this page.
Conversation
gvanrossum commentedMay 2, 2016
Please don't submit a PR that fails the tests and has typos in it. At the very least run it against your test program with and without drain(). |
socketpair commentedMay 2, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@gvanrossum I have fix typo, and checked spped: Before my patch: After my patch: P.S. Thinking how to fix tests. Please point me.... |
gvanrossum commentedMay 2, 2016
I guess you have to mock os.writev too. Time to learn something! |
gvanrossum commentedMay 2, 2016
BTW great news on the speed! |
socketpair commentedMay 2, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@gvanrossum |
asyncio/unix_events.py Outdated
| # @mock.patch('os.writev') stores internal reference to _buffer, which is MODIFIED | ||
| # during this call. So, makeing deep copy :( | ||
| # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
| n = os.writev(self._fileno, self._buffer.copy()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
There must be a better way here. Adding a copy just for convenient testing isn't a good idea. Please also remove all exclamation marks, smiles, and fix typos.
socketpairMay 2, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@1st1
I consider you don't ever think to merge PR with such hack, so I added these comments to bring your attention. PR is not ready for merge. But I must point to this bad place.
If you know 'better way' please point me. I will fix immediatelly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
OK ;) Please try to find a saner approach. I'll myself try to take a look later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Has removed exclamation marks and other trash. But I stil don't know how to overcome that annoying bug inunittest.mock
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Finally, Have fixed test as@1st1 said.
gvanrossum commentedMay 2, 2016
I don't follow. Does the real |
socketpair commentedMay 2, 2016
@gvanrossum, in short code is: Note, that |
asyncio/unix_events.py Outdated
| self._buffer.append(data) # Try again later. | ||
| self._loop.remove_writer(self._fileno) | ||
| self._maybe_resume_protocol() # May append to buffer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Seems another bug. in sockets,self._maybe_resume_protocol() is called beforeif self._buffer. So, who is right ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I would trust the socket code more. So I'd remove line 544-545 above and see how it fares.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Fixed and make behaviour as in sockets.
1st1 commentedMay 2, 2016
@socketpair Here's my attempt to tame the mock:1st1@5b8e2dd |
socketpair commentedMay 2, 2016
@1st1 I think the most convenient way is to merge my PR in current state, and after that, merge you PR. Is it suitable workflow ? |
1st1 commentedMay 2, 2016
@socketpair You can just incorporate my change into your PR. Please add a comment to |
socketpair commentedMay 2, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Sorry, please don't merge PR. I have checked performance. Using just expanding bytearray is much faster. C is not Python. :( This is reproduced both for sockets and for pipes. In theory, writev() / sendmsg() should be faster. In reality - is not. I can not believe that this is true. I will investigate why this happen. Please don't merge PR until problem resolved. Program used to benchmark: |
1st1 commentedMay 2, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
This is very strange. Using |
gvanrossum commentedMay 2, 2016 via email
Honestly I'm not that surprised that bytearray performs better. Resizing abyte array is one of the fastest things you can do in CPython (because`realloc()` handles the copy for you). |
1st1 commentedMay 13, 2016
Hi@socketpair! Any progress on this PR? |
socketpair commentedMay 13, 2016
I'm online, will continue soon. I spent last week in another country, now I returned back to home, and today is a first working day at my job. |
1st1 commentedMay 13, 2016
Sure, no rush. 3.5.2 will happen relatively soon, would be nice to have this reviewed and merged before that. |
socketpair commentedMay 13, 2016
great news! Now I know why bytearray was faster. Now, my code is even faster than bytearray variant! since it true zerocopy! WOOHOO! |
socketpair commentedMay 13, 2016
|
asyncio/selector_events.py Outdated
| n -= len(chunk) | ||
| if n < 0: | ||
| # only part of chunk was written, so push unread part of it back to _buffer | ||
| # memoryview is required to eliminate memory copying while slicing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
This was a cause of slow throughput
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
fixed
1st1 commentedMay 13, 2016
Cool! Could you please fix the code style to 79 cars per line? |
asyncio/selector_events.py Outdated
| def get_write_buffer_size(self): | ||
| return len(self._buffer) | ||
| returnsum(len(data) for data inself._buffer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Maybe instead of runningsum each time, we can have an internal_buffer_length attribute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
maybe, but I copy-pasted it from another place. Yes I can fix that (and perform benchmarking).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I suspect most of the time thedata queue won't be large, so you really need to overwhelm the write buffer in your benchmarks to see the benefits of caching.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Sorry, I will not fix that. Code become too complex and error prone. Especially when exception occurs in some specific places. I tried.
socketpairMay 14, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
So, I have fixed anyway. I also added many asserts.
1st1 commentedMay 13, 2016
I've left some feedback. |
socketpair commentedMay 13, 2016
Also, Python3.5 does not support |
socketpair commentedJul 5, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
| return | ||
| try: | ||
| n = self._sock.send(self._buffer) | ||
| if compat.HAS_SENDMSG: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
HAS or HAVE ? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
HAS is better.
1st1 commentedJul 5, 2016
Sorry, Mark, I'm busy with other things. This is quite an intrusive change and it has to be merged with extra care. And we have plenty of time before 3.6. |
socketpair commentedJul 6, 2016
@1st1 I can split PR to small parts. After each part, everything will be consistent. Should I do that ? |
1st1 commentedJul 6, 2016
How do you want to split it? Actually, I was just looking at this PR again, and I think it's ready. I need to spend another hour playing with the code, but I'd say it's almost there. |
methane commentedJul 22, 2016
I think |
socketpair commentedJul 22, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@arthurdarcet can you benchmark asyncio streams with this patch applied, using included tool (in this PR) on Mac OS X ? This patch should speedup pipes significantly on that platform too. |
arthurdarcet commentedJul 22, 2016
@socketpair sure, do you have some code i could run? |
methane commentedJul 22, 2016
@socketpair I did it. |
socketpair commentedJul 24, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I have an idea: add to write functions parameters |
methane commentedJul 25, 2016
I feel it's a premature optimization. |
methane commentedJul 25, 2016
I've benchmarked on Ubuntu 16.04, with slightly modified master branch: socketpair:writev branch: |
socketpair commentedJul 25, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
cons:
cons:
@gvanrossum@1st1@methane |
methane commentedJul 25, 2016
Another cons of Checking "bytes-like" object without copy is very hard in pure Python. mv=memoryview(data)ifmv.itemsize!=1ornotmv.contiguous:raiseTypeError
|
methane commentedJul 25, 2016
My preference is, use bytearray() in pure Python. But make it replacable. Someone can implement more smart buffer like below in C. def__init__(self):self.queue=deque()def__iadd__(self,data):iftype(data)isbytesandlen(data)>200:self.queue.append(data)returnifnotself.queueortype(self.queue[-1])isbytes:self.queue.append(bytearray())self.queue[-1]+=data |
socketpair commentedAug 1, 2016
Copy-pasting here: small data: large data: |
socketpair commentedAug 1, 2016
@gvanrossum@1st1 What do you think about all that ? |
socketpair commentedAug 1, 2016 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I understand, that simplicity of code is important thing. In real use cases (i.e. small amount of data and small count of chunks) both implementations give the same performance. |
For pipes, use os.writev() instead of os.write(b.join()).For sockets, use sendmsg() instead of send(b''.join()).Also change plain list of buffers to deque() of buffers.This greatly improve performance on large buffers or onmany stream.write() calls.
1st1 commentedOct 5, 2016
Mark, I'm closing this PR. I think we'd want to have vectorized writes in 3.7, so when you have a new patch please open a new PR. |
No description provided.