Ubuntu上のAsyncで遅延 – BlackJumboDog CoreCLR

ずーっと気になっていたんですが、Ubuntu上でサーバーのTCPソケットをAcceptAsyncかけていたら、しばらくアクセスがない状態だと1秒程度の遅延が発生していました。そして、連続したアクセスだとこれは起きなかったんです。

元々のBjdではWhileとSleepによるポーリングを行っていたので、おそらくそんなことは起きなかっただろうと思っています。(そもそも、Begin/Endが動かなかったので、根拠はない!)

同じことが、ManualResetEventSlimeでも起きました。ある程度時間がたったときに、シグナルセット後のWait解放が1秒くらい。これ、Windowsでは起きなかったんですよね。

正直、そこまでプラットフォームに詳しい人間ではないので、なぜこうなるのか?は理解できませんでした。ただ、どうすれば?に関しては、「深い眠りにつかないようにする」っていう発想で回避しました。

https://github.com/darkcrash/bjd5/commit/a9049f8630d2e788dda19065026c415654efcd05#diff-c042d296432145429c9f5f4d27bfef99

     -            tTcp.Wait(this.Kernel.CancelToken);  
 94   +            while (true)  
 95   +            {  
 96   +                if (tTcp.Wait(2000, this.Kernel.CancelToken))  
 97   +                    break;  
 98   +                if (tTcp.Status == TaskStatus.Canceled)  
 99   +                    break;  
 100  +            }

Waitを2秒までとして、完了時はループを抜け、キャンセル時もループを抜けます。こうすることで2秒に一回このWaitが実行されます。そして、結果として遅延1秒はなくなりました。

SpinWaitの絡みとか、タイムスライスのルールとかありそうなんですが、ブラックボックスです。Darkが作るBlackなだけに・・・

これが、Kernelによるものなら、今後もこういう仕様ということになるでしょうし、.Net Coreのものであれば、改善されていくかもしれません。ので、現時点ではこのコードは、一つの回避策として整理してくださいませ!

それでは!