Towards a more responsive Eclipse UI

Last modified: June 4, 2003

Eclipse is well known as a powerful integrated development environment, but it is perceived by users as sometimes being unwieldy or unresponsive to work with. The goal of this work is to uncover the underlying causes of the unresponsiveness and provide Eclipse developers with the tools they need to focus on making their code responsive.

To begin with, it is important to note that, responsiveness is not the same as performance, and to some extent they are contradictory:

The performance of an application is a measure of how much work it can do in a given length of time. For example, the Eclipse Platform can operate on thousands of files per minute on a typical desktop system. One way to achieve high performance is to ensure that all available resources are dedicated to each task until it is complete. Since most modern window systems require applications to regularly call system code to keep their user interfaces active, dedicating all processing resources to a non-user-interface task will cause the user interface to become unresponsive.

The responsiveness of an application is a measure of how often its user interface is in a state where the user can interact with it, how often those interactions can trigger new tasks being initiated, and how often the information the user interface is displaying accurately reflects the state of the system it is modeling. Implementing a responsive system will require the system resources to be split across multiple concurrent tasks, so although the user will typically be more productive, the time it takes the system to complete a particular task will be longer (i.e. Its performance on that task will be lower).

In order to increase the responsiveness of the Eclipse Platform we will be looking at the following two areas:

  1. all of the user interface "features" of the Eclipse Platform will be investigated to remove any inherent limitations which prevent them from being used in a responsive fashion. We have not begun work on this aspect of the problem, so it is difficult to provide any definitive examples. However, some likely candidates for investigation, at least, would be:

  1. certain operations like builds and searches which currently run synchronously and block the user (at the UI) from doing other work until they are completed will be modified to run asynchronously in the background. Implementing this requires an improved concurrency architecture. The remainder of this document describes the work which has been done so far in that area.

Overview of current problems

Proposed solutions

Job scheduling mechanism

Platform core (runtime plugin) will introduce a new job manager API for background work. This API will allow clients to:

This scheduling mechanism will replace most (if not all) existing background thread mechanisms in the SDK. This includes: editor reconcilers, UI decoration, search and Java indexing, workspace snapshot, and various threads used in the launch/debug framework: JDI thread for communicating with the VM, threads for monitoring input and output streams, debug view update thread, and the thread waiting for VM termination.

Also, the scheduling facility will make it easier for more components to off-load work into background threads, in order to free up the UI thread for responding to the user. This includes all jobs that currently run in the context of a modal progress indicator, but also other processing work that currently executes in the UI. Examples of activity that can be offloaded into jobs: decorating editors (marker ruler, overview ruler), type hierarchy computation, structure compare in compare editors, auto-refresh with file system, etc.

Scalability of the job manager mechanism will be a concern for some applications that are processing large numbers of very small work items, such as the decoration thread and the indexer thread. Creating a separate job for each work item would severely degrade the scheduler, and could result in an unwanted level of concurrency. For example, if several indexing jobs happen concurrently, then they may complete in the wrong order and corrupt the index files.

This can be solved by creating a single master job that maintains its own queue of smaller work items. The master job would run as long as work items remained in its private queue. If work items are added when the master job is not running, it can be scheduled lazily. If these systems still have to maintain their own queue, then why bother use the job manager at all? There are still some benefits:

New UI look and feel for long running activity

Long running operations will generally be run without a modal progress indicator by scheduling them with the core job manager API. Most jobs currently using a modal progress dialog will switch to this new non-modal way of running. The platform UI will provide a view from which users can see the list of waiting and running background jobs, along with their current progress. This is a view rather than a dialog so the user can continue to manipulate the UI while background jobs are running. This view will likely take the form of a tree so that expanding a job will give more detailed progress information. The UI will also provide some ubiquitous feedback device (much like the page loading indicator in popular web browsers or the Macintosh user interface), that will indicate when background activity is happening.

Users will be able to cancel any background activity from the progress view. Users will also be able to pause, resume, or fast forward (increase priority of) any waiting job. Since we can never know which of several background jobs the user is most anxious to complete, this puts some power in the user's hands to influence the order of execution of waiting background jobs.

The platform UI will introduce a special job called a UI job, which is simply a job that needs to be run in the UI Thread. We define this type of job as a convenience for those who do not want to keep looking for a Display to asyncExec in. Casting UI work as jobs will allow the framework to control scheduling based on priority and user defined scheduling rules. Note that although UI jobs should generally be brief in duration, they may require locks and thus the framework must have a strategy for avoiding deadlock when the UI thread is waiting for a lock.

Minimize use of long term workspace locks

We will actively discourage clients from acquiring the workspace lock for indefinite periods of time. IWorkspaceRunnable is the current mechanism that allows clients to lock the workspace for the duration of a runnable. This API will be deprecated. Clients that require exclusive access to portions of the workspace should schedule background jobs with appropriate scheduling rules. Scheduling rules can specify smaller portions of the workspace, allowing clients to "lock" only the resources they need. Longer running workspace API methods will be broken up as much as possible to avoid locking the workspace for extended periods. Clients that do not run as jobs, or that run as jobs without the appropriate scheduling rules, will have to be tolerant of concurrent modifications to the workspace.

New resource change notification and autobuild strategy

The current mechanism for batching resource changes and auto-building is based on the IWorkspaceRunnable API. This approach has two problems:

  1. Clients sometimes forget to use it, which results in severe performance problems because notifications and auto-builds happen more often than necessary.
  2. This can become too coarse-grained for long running operations. If the user begins an operation that will take several minutes, it would be nice to perform some incremental updates (notifications) while the operation is still running.

The resources plugin will adopt new heuristics for when builds and notifications should happen. These heuristics will likely require some fine-tuning and may need to be customizable, but generally:

Unless explicitly requested, builds and resource change listeners will always be run asynchronously in a different thread from the one that initiated the change. This will improve the responsiveness of workspace changing operations that are initiated from the UI thread.

Centralized locking mechanism

Platform core (runtime plugin) will introduce a smart locking facility. Clients that require exclusive access to a code region should use these locks as a replacement for Java object monitors in code that may interact with other locks. This will allow the platform to detect and break potential deadlocks. Note that these locks are orthogonal to the job scheduling rules described earlier. Job scheduling rules typically ensure that only non conflicting jobs are running, but cannot guarantee protection from malicious or incorrect code.

These locks will have the following features:

Milestone targets

This schedule is aggressive but the intent is to wrap up platform work by end of M3. This allows plenty of time to shake out threading bugs and allow other components to stabilize by M4.

Go back to concurrency home.

(Plan item bug reference: 36957)