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

add fast-path optimizations for reading LibuvStreams #14667

Merged
merged 1 commit into from
Jan 14, 2016
Merged

Conversation

vtjnash
Copy link
Member

@vtjnash vtjnash commented Jan 13, 2016

fixes #14467 performance regression (and some).

these functions aren't supposed to be on the fast-path, but they were. adding appropriate short-circuit paths to those fixes the performance regression noted in #14467. moving them off of the fast-path (by providing a more optimal implementation of readbytes!) makes the simple echo server twice as fast. we should now be about 2x the 0mq speed on the provided test cases (about 10x the super-simple blocking C code).

fixes #14467 performance regression (and some)
@yuyichao yuyichao added the performance Must go faster label Jan 13, 2016
@yuyichao
Copy link
Contributor

👍 Does @nanosoldier have any IO performance tests now?

@jrevels
Copy link
Member

jrevels commented Jan 13, 2016

Does @nanosoldier have any IO performance tests now?

Not yet, but it will soon. The remotecall_fetch echo test from #14467 will get included in the next BaseBenchmarks.jl release (which will be tomorrow if everything passes tests tonight), and more IO tests will be available sometime next week.

vtjnash added a commit that referenced this pull request Jan 14, 2016
add fast-path optimizations for reading LibuvStreams
@vtjnash vtjnash merged commit 918f14e into master Jan 14, 2016
@vtjnash vtjnash deleted the jn/fast-io branch January 14, 2016 01:01
wait_readnb(s, nb)
nr = nb_available(s)
resize!(b, nr) # shrink to just contain input data if was resized
read!(s.buffer, b)
Copy link
Contributor

Choose a reason for hiding this comment

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

this won't work for UDPSocket or anything else without a buffer field

Copy link
Member Author

Choose a reason for hiding this comment

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

it also doesn't support read or write (it uses send and recv), so i'm not too worried about that. we could extend the type-hierarchy to exclude it (because it isn't a stream) explicitly, but to what end?

Copy link
Contributor

Choose a reason for hiding this comment

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

it's a buggy type because of this field assumption. I forget the issue number, but sounds like this abstract type isn't appropriate for it

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 not sure why something should be an IO type if it doesn't have read and write.

@tkelman tkelman added needs tests Unit tests are required for this change and removed needs tests Unit tests are required for this change labels Jan 14, 2016
@@ -87,8 +87,13 @@ end
nb_available(s::LibuvStream) = nb_available(s.buffer)

function eof(s::LibuvStream)
if isopen(s) # fast path
nb_available(s) > 0 && return true
Copy link
Member

Choose a reason for hiding this comment

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

Should this return false instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes

Copy link
Contributor

Choose a reason for hiding this comment

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

do add a test when you fix this

Copy link
Member Author

Choose a reason for hiding this comment

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

done in a0b5414

@ViralBShah
Copy link
Member

👍

@amitmurthy
Copy link
Contributor

@vtjnash what is a "fast path optimization" ?

@vtjnash
Copy link
Member Author

vtjnash commented Jan 15, 2016

in this case, copying the cheap epilogue of the function into the prologue, to detect when we don't need to call the expensive code in the middle

@@ -876,6 +894,14 @@ function stop_reading(stream::LibuvStream)
end
end

function readbytes!(s::LibuvStream, b::AbstractArray{UInt8}, nb=length(b))
wait_readnb(s, nb)
Copy link
Contributor

Choose a reason for hiding this comment

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

This line breaks MbedTLS and everything that depends on it. I think wait_readnb should probably have a wider signature, Integer instead of Int?

function wait_readnb(x::LibuvStream, nb::Int)

(also in need of tests)

function readbytes!(s::LibuvStream, b::AbstractArray{UInt8}, nb=length(b))
wait_readnb(s, nb)
nr = nb_available(s)
resize!(b, nr) # shrink to just contain input data if was resized
Copy link
Contributor

Choose a reason for hiding this comment

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

And this line won't work if you try to give it an array that shares data, cannot resize array with shared data - MbedTLS.jl does this via pointer_to_array with an array that is managed by the C library.

tkelman pushed a commit that referenced this pull request Mar 7, 2016
fixes #14467 performance regression (and some)

(cherry picked from commit 9dbc3ab)
ref #14667
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Must go faster
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Major socket io performance regression in 0.4 and 0.5-dev
7 participants