I see! So if that's the case, is there a real benefit from IO controller thread? What would stop you replacing it with some other construct that feeds into the queues directly?
On 23 June 2012 22:34, Jerome Louvel <[email protected]> wrote: > That’s the way it already works indeed! There is just one IO controller > thread that communicates with a pool of worker threads via a set of message > queues, managed at the connector helper level. The wakeup issue here is > only relevant for the IO controller thread to prevent it from spinning over > and over.**** > > ** ** > > Best regards,**** > > Jerome**** > > --**** > > http://www.restlet.com**** > > http://twitter.com/#!/jlouvel**** > > ** ** > > ** ** > > *De :* Ioannis Mavroukakis [mailto:[email protected]] > *Envoyé :* samedi 23 juin 2012 13:47 > > *À :* [email protected] > *Objet :* Re: Idling app has ~2MB of garbage collected every 30 seconds*** > * > > ** ** > > Cool, so in essence you wouldn't need to rely on interrupts to serve an > incoming request, is that correct?**** > > On 23 June 2012 21:41, Jerome Louvel <[email protected]> wrote:*** > * > > Hi Ioannis,**** > > **** > > Actually, we use several queues down the road to process the messages > (requests and responses), so it already almost works like you expect. See > diagrams here:**** > > http://wiki.restlet.org/developers/172-restlet/g1/354-restlet.html**** > > **** > > Best regards,**** > > Jerome**** > > --**** > > http://www.restlet.com**** > > http://twitter.com/#!/jlouvel**** > > **** > > **** > > **** > > **** > > *De :* Ioannis Mavroukakis [mailto:[email protected]] > *Envoyé :* samedi 23 juin 2012 13:11**** > > > *À :* [email protected] > *Objet :* Re: Idling app has ~2MB of garbage collected every 30 seconds*** > * > > **** > > Well I'm speculating here as I haven't seen the code, but it *sounds like* > a classic producer/consumer scenario, which might be best served with a > blocking queue. So at one end you'd have your NIO selector or whatever > else feeding the queue, and at the other end, a consumer picking up jobs > via either take() or poll() (which blocks if there's no element to be > taken).The cool thing about this, is that it promotes work stealing, so you > could have multiple queues and consumers, which can steal work from other > queues when idle.**** > > As I forewarned, I haven't delved deep into the code, so I may be talking > out of my ass :)**** > > **** > > Cheers,**** > > Ioannis**** > > On 22 June 2012 17:41, Jerome Louvel <[email protected]> wrote:*** > * > > Hi Ioannis, > > Regarding the GC of iterators, I've fixed the one under our control in RF > 2.1 and 2.2/master branches yesterday. The second one is inside the NIO > selector code so we can't remove it, which leads to the second solution > anyway. I've also started to implement the notification/wakeup logic but > haven't got it done yet. > > This takes us back to you remark. The NIO Selector#select method is here > to allow a single thread to handle thousands of concurrent connections in a > scalable manner. You register for IO interest for specific > channels/connections and wait for it to return and tell you the selected > one that are ready for processing. > > Could you explain a bit more about a blocking queue could help us solve > this issue?**** > > > Best regards, > Jerome > -- > http://www.restlet.com > http://twitter.com/#!/jlouvel > > > > -----Message d'origine----- > De : Ioannis Mavroukakis [mailto:[email protected]]**** > > Envoyé : vendredi 22 juin 2012 01:17**** > > À : [email protected] > Objet : Re: Idling app has ~2MB of garbage collected every 30 seconds > > Hi Jerome , > > You're welcome, it's an interesting discussion. Is interrupting the > cleanest way of doing this ? Wouldn't a blocking queue serve better in the > context of a producer/consumer scenario? > > On 22 Jun 2012, at 00:31, Jerome Louvel <[email protected]> wrote: > > > Hi Yan, Ioannis, > > > > Thanks for pointing your finger on this hot spot! The GC overhead is > > clearly an issue that needs to be fixed and definitely worth a ticket in > GitHub. > > > > A first and easy solution is to replace those two iterator objects > > with regular loops to prevent unnecessary garbage collection. > > > > The second and harder solution will require to have the controller > > thread sleep by default (as long as possible to prevent unnecessary > > CPU cycles) and indeed interrupt it when an event occurs: > > 1) NIO event detected > > 2) Connection event detected (new connection/message/entity chunk to > > process) > > > > See this wiki pages to details on this connector and the pending tasks: > > http://wiki.restlet.org/developers/172-restlet/g3/354-restlet.html > > > > Best regards, > > Jerome > > -- > > http://www.restlet.com > > http://twitter.com/#!/jlouvel > > > > > > -----Message d'origine----- > > De : Ioannis Mavroukakis [mailto:[email protected]] Envoyé : > > jeudi 21 juin 2012 01:05 À : [email protected] Objet : Re: > > Idling app has ~2MB of garbage collected every 30 seconds > > > > Yes it could but you would you not end up having the overhead of > > context switching from the thrown thread interrupts? On a low resource > > device this can't be the best of situations I imagine. > > > > On 21 Jun 2012, at 00:16, Yan Zhou <[email protected]> wrote: > > > >> Any objections if the following is added as a new issue in the issue > > tracker? > >> > >> I am thinking that the selectKeys(sleepTime) call below really should > >> be > > able to return immediately (thread interrupted, for example) if there > > has been a connection state change that needs attention. The sleepTime > > will then have little effect on how soon or how often > controlConnections() is run. > >> > >> Thanks, > >> Yan Zhou > >> > >>> Hi, > >>> > >>> We are noticing that an idling Restlet server has about 2MB of > >>> garbage > > collected in 30 seconds. > >>> > >>> I think I tracked it down to the loop in ConnectionController that > > invokes the method below: > >>> > >>> > >>> @Override > >>> protected void doRun(long sleepTime) throws IOException { > >>> super.doRun(sleepTime); > >>> registerKeys(); > >>> updateKeys(); > >>> selectKeys(sleepTime); > >>> controlConnections(); > >>> } > >>> > >>> The sleepTime comes from the controllerSleepTimeMs parameter, which > >>> is 1 > > by default. > >>> > >>> So if the loop generates 60 bytes of garbage (2 iterator objects), > >>> it'd > > lead to: 60 x 1000 x 30 = 1,800,000 bytes or 1.8MB every 30 seconds. > >>> > >>> Can I ask if this is a known issue? And if there are workarounds? > >>> > >>> I have already tried tweaking the controllerSleepTimeMs and changing > >>> it > > to something like 30000 (30 seconds). Every connection then takes up > > to 30 seconds to close - probably not acceptable as a solution. > >>> > >>> Additional info: Restlet 2.1 rc4 Android edition. > >>> > >>> Thanks, > >>> Yan Zhou > >> > >> ------------------------------------------------------ > >> > > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId > > =29722 > > 83 > > > > ------------------------------------------------------ > > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId > > =29723 > > 87 > > > > ------------------------------------------------------ > > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId > > =2972533**** > > ------------------------------------------------------ > > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2972585 > > ------------------------------------------------------ > > http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2972655 > **** > > **** > > ** ** > ------------------------------------------------------ http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2972815

