You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by "Martin Grigorov (JIRA)" <ji...@apache.org> on 2014/03/05 09:50:44 UTC

[jira] [Resolved] (WICKET-5243) JS: High stack size in Function Executor causes "too much recursion"

     [ https://issues.apache.org/jira/browse/WICKET-5243?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Martin Grigorov resolved WICKET-5243.
-------------------------------------

       Resolution: Fixed
    Fix Version/s: 6.15.0
                   7.0.0
         Assignee: Martin Grigorov

The suggested patch has been applied to wicket-6.x and master branches.
>From now on recursion will not be used when there is no need to wait for notify() calls.
notify() is needed only for JS/CSS resources' download and JS execution with manual control.

This reduces a lot the need of allocating stack frames (i.e. using recursion) but still doesn't remove this completely.

> JS: High stack size in Function Executor causes "too much recursion"
> --------------------------------------------------------------------
>
>                 Key: WICKET-5243
>                 URL: https://issues.apache.org/jira/browse/WICKET-5243
>             Project: Wicket
>          Issue Type: Bug
>          Components: wicket
>    Affects Versions: 6.8.0
>         Environment: Tested on Firefox
>            Reporter: Tobias Haupt
>            Assignee: Martin Grigorov
>              Labels: javascript, perfomance
>             Fix For: 7.0.0, 6.15.0
>
>         Attachments: WICKET-5243-avoid-recursion.patch, WICKET-5243-notify-only-when-async.patch, response.xml, wicket-ajax-jquery.js
>
>
> The Function Executor in wicket-ajax-jquery.js uses recursion and deferred calls to the notify() function to ensure synchronous execution of all tasks contained in an AjaxResponse.
> Each task calls notif() when it is finished. This causes a recursive call to processNext() thus raising the stack for each execution. If there are a lot of task to handle, the stack size will increase beyond the possible stack size in the client causing a "too much recursion" exception and increasingly low performance.
> The deferred execution of notify is only necessary if the task executor has to wait for long running tasks to finish at some uncertain point in the future. Examples: downloading of external resources (js, css, images). These task can call back the executor as soon as they are really finished (e.g. load event triggerd).
> The problem is that the majority of tasks don't need to wait but return instantly instead. Examples: exchanging components, executing custom javascripts that do not use the "|-syntax" to include the notify callback.
> Current fix: The depth of the stack is counted and if a depth of >= 1000 is reached, a timeout will interrupt the synchronous task queue execution. A new executor will continue with an empty stack.
> Problems with that approach: 
> - why 1000?
> - several ajax requests might interrupt each other because the synchronous execution is broken.
> - if an executed custom javascript creates a big stack itself (e.g. by using jquery a lot) the stack will add to the stack used by the Function Executor so that it may still be too big.
> Proposal to fix this: see also the attached patch.
> Another callback notifyContinue() is supported that can be called whenever the task will return instantly. This callback avoids the recursive call to processNext and continues in a simple loop over all the tasks.



--
This message was sent by Atlassian JIRA
(v6.2#6252)