cygrunsrv + sshd + rsync = 20 times too slow -- throttled?

Ken Brown kbrown@cornell.edu
Thu Sep 2 20:19:04 GMT 2021


On 9/2/2021 3:35 PM, Corinna Vinschen wrote:
> On Sep  2 21:00, Corinna Vinschen wrote:
>> On Sep  2 09:01, Ken Brown wrote:
>>> On 9/2/2021 4:17 AM, Corinna Vinschen wrote:
>>>> What if the readers never request more than, say, 50 or even 25% of the
>>>> available buffer space?  Our buffer is 64K and there's no guarantee that
>>>> any read > PIPE_BUF (== 4K) is atomic anyway.  This can work without
>>>> having to check the other side of the pipe.  Something like this,
>>>> ignoring border cases:
>>>>
>>>> pipe::create()
>>>> {
>>>>      [...]
>>>>      mutex = CreateMutex();
>>>> }
>>>>
>>>> pipe::raw_read(char *buf, size_t num_requested)
>>>> {
>>>>     if (blocking)
>>>>       {
>>>>         WFSO(mutex);
>>>>         NtQueryInformationFile(FilePipeLocalInformation);
>>>>         if (!fpli.ReadDataAvailable
>>>> 	  && num_requested > fpli.InboundQuota / 4)
>>>> 	num_requested = fpli.InboundQuota / 4;
>>>>         NtReadFile(pipe, buf, num_requested);
>>>>         ReleaseMutex(mutex);
>>>>       }
>>>> }
>>>>
>>>> It's not entirely foolproof, but it should fix 99% of the cases.
>>>
>>> I like it!
>>>
>>> Do you think there's anything we can or should do to avoid a deadlock in the
>>> rare cases where this fails?  The only thing I can think of immediately is
>>> to always impose a timeout if select is called with infinite timeout on the
>>> write side of a pipe, after which we report that the pipe is write ready.
>>> After all, we've lived since 2008 with a bug that caused select to *always*
>>> report write ready.
>>
>> Indeed.  Hmm.  What timeout are you thinking of?  Seconds?  Minutes?
>>
>>> Alternatively, we could just wait and see if there's an actual use case in
>>> which someone encounters a deadlock.
>>
>> Or that.  Fixing up select isn't too hard in that case, I guess.
> 
> It's getting too late again.  I drop off for tonight, but I attached
> my POC code I have so far.  It also adds the snippets from my previous
> patch which fixes stuff Takashi found during testing.  It also fixes
> something which looks like a bug in raw_write:
> 
> -	  ptr = ((char *) ptr) + chunk;
> +	  ptr = ((char *) ptr) + nbytes_now;
> 
> Incrementing ptr by chunk bytes while only nbytes_now have been written
> looks incorrect.

Yes.  I actually copied that bug from fhandler_base_overlapped::raw_write.  It's 
amazing that no one has no one has bumped into it up to now.
> As for the reader, it makes the # of bytes to read dependent on the
> number of reader handles.  I don't know if that's such a bright idea,
> but this can be changed easily.
> 
> Anyway, this runs all my testcases successfully but they are anything
> but thorough.
> 
> Patch relativ to topic/pipe attached.  Would you both mind to take a
> scrutinizing look?

Will do.

Ken


More information about the Cygwin-developers mailing list