| <!DOCTYPE html> |
| |
| <!-- |
| Google HTML5 slide template |
| |
| Authors: Luke Mahé (code) |
| Marcin Wichary (code and design) |
| |
| Dominic Mazzoni (browser compatibility) |
| Charles Chen (ChromeVox support) |
| John Arthorne (Eclipse template) |
| |
| URL: http://code.google.com/p/html5slides/ |
| --> |
| |
| <html> |
| <head> |
| <title>Eclipse SDK's Greatest Hits: The First Ten Years</title> |
| |
| <meta charset='utf-8'> |
| <script src='http://eclipse.org/eclipse/presentation/html/slides.js'></script> |
| <style> |
| /* Your individual styles here, or just use inline styles if that's |
| what you want. */ |
| |
| |
| </style> |
| </head> |
| |
| |
| <body style='display: none;'> |
| |
| <section class='slides layout-regular template-eclipse'> |
| |
| <!-- Your slides (<article>s) go here. Delete or comment out the |
| slides below. --> |
| |
| |
| <article id='splash' class='biglogo'> |
| </article> |
| |
| <article id='title'> |
| <h1> |
| Eclipse SDK's Greatest Hits: |
| <br> |
| The First Ten Years |
| </h1> |
| <p> |
| John Arthorne |
| <br> |
| March, 2012 |
| </p> |
| </article> |
| |
| <article id="disclaimer"> |
| <h3> |
| Disclaimer |
| </h3> |
| <ul> |
| <li> |
| This is a semi-random, subjective list |
| </li> |
| <li> |
| Just some deep Eclipse implementation details that I think are cool, from my perspective |
| </li> |
| <li> |
| This presentation contains code |
| </li> |
| </ul> |
| <p> |
| <img style='height: 300px;' src='images/warning.png'> |
| </p> |
| <div class='source'> |
| Source: http://www.flickr.com/photos/cara_vsangel/ |
| </div> |
| </article> |
| |
| <article id="overview"> |
| <h3> |
| What we're going to look at |
| </h3> |
| <ul> |
| <li> |
| Workspace tree representation |
| </li> |
| <li> |
| Incremental Java build |
| </li> |
| <li> |
| RCP refactoring |
| </li> |
| <li> |
| Command framework |
| </li> |
| <li> |
| p2 resolver |
| </li> |
| </ul> |
| </article> |
| |
| <!-- ************************************************************************ --> |
| |
| <article id="tree-intro"> |
| <h3> |
| Workspace tree representation |
| </h3> |
| <q> |
| It's ElementTree my dear Watson, ElementTree |
| </q> |
| <div class='author'> |
| ElementTree.java, line 75 |
| </div> |
| </article> |
| |
| <article id="tree-motivation"> |
| <h3> |
| ElementTree motivation |
| </h3> |
| <ul> |
| <li> |
| Typical edit/compile/deploy cycle for a developer focuses on a small segment of a potentially very large code base |
| </li> |
| <li> |
| Want to aggressively optimize for this common cycle: make performance cost proportional to the change, rather than to the size of the workspace |
| </li> |
| <li> |
| Create and manipulate "units of change" that are passed around to interested parties |
| </li> |
| </ul> |
| </article> |
| |
| <article id="tree-diag1"> |
| <h3> |
| Data flow |
| </h3> |
| <p> |
| <img style='height: 520px;' src='images/tree.png'> |
| </p> |
| </article> |
| |
| <article id="tree-observations"> |
| <h3> |
| Additional observations |
| </h3> |
| <ul> |
| <li>Clients want a delta of the workspace state between two moments in time</li> |
| <li>Different clients may want deltas with different start and/or end points</li> |
| <li>May need to keep track of hundreds of tree states at once</li> |
| <li>How to efficiently represent all these different deltas in memory?</li> |
| <li>How to compute these deltas without traversing entire workspaces?</li> |
| </ul> |
| </article> |
| |
| <article id="tree-diag2"> |
| <h3> |
| Representing two tree states |
| </h3> |
| <p> |
| <img style='height: 520px;' src='images/tree2.png'> |
| </p> |
| </article> |
| |
| <article id="tree-diag3"> |
| <h3> |
| Representing tree states as deltas |
| </h3> |
| <p> |
| <img style='height: 520px;' src='images/tree3.png'> |
| </p> |
| </article> |
| |
| <article id="tree-details"> |
| <h3> |
| More details |
| </h3> |
| <ul> |
| <li>Have only one complete tree, and represent all others as deltas</li> |
| <li>Only one delta is mutable - representing current operation</li> |
| <li>Immutability allows trees to share common parent and nodes to share children</li> |
| <li>Each tree seems complete when traversing using API, but internal structure quite different</li> |
| <li>Computing deltas is nearly free for most common operations</li> |
| </ul> |
| </article> |
| <article> |
| <h3> |
| Lessons learned |
| </h3> |
| <ul> |
| <li>Not all optimization is a speed-space tradeoff. Here we greatly reduced space required to represent states, and made delta calculation very fast</li> |
| <li>Textbook data structures work very well in most programming situations, but sometimes |
| a very specialized structure is called for</li> |
| <li>Internal representation of a data structure can be radically different from external appearance</li> |
| </ul> |
| </article> |
| |
| <!-- ************************************************************************ --> |
| |
| <article id="builder-intro" class='smaller'> |
| <h3> |
| Incremental Java build |
| </h3> |
| <q> |
| Conducts a trial on a single compilation unit. Returns true if the unit |
| is guilty. The sentence is compilation without possibility of parole. |
| </q> |
| <div class='author'> |
| IncrementalImageBuilder.java v_146, line 1570 |
| </div> |
| </article> |
| |
| <article id="builder-assumptions"> |
| <h3> |
| Starting assumptions |
| </h3> |
| <ul> |
| <li>Compilation is expensive</li> |
| <li>Compiling a single file can create a ripple effect where many more files need compiling</li> |
| </ul> |
| <p> |
| <img class='centered' style='height: 350px;' src='images/ripple.jpg'> |
| </p> |
| <div class='source'> |
| Source: Bill Gracey |
| </div> |
| </article> |
| |
| <article id="builder-1-0"> |
| <h3> |
| Eclipse 1.0 Java builder |
| </h3> |
| <ul> |
| <li>Used a trial metaphor</li> |
| <li>When a file was compiled it produced evidence (e.g., class B is a subclass of A)</li> |
| <li>When A is changed, all files that refer to it are put on trial (e.g., method foo() removed from A)</li> |
| <li>All the corner cases are considered: does B refer to foo(), does it also declare foo() and invoke super?</li> |
| <li>Compile guilty files; repeat</li> |
| </ul> |
| </article> |
| |
| <article id="builder-revisit"> |
| <h3> |
| Revisiting assumptions |
| </h3> |
| <ul> |
| <li>Meanwhile JDT compiler was rewritten to be blazingly fast</li> |
| <li>You only need to recompile dependents when there are structural changes</li> |
| <li>Structural changes have little or no ripple effect</li> |
| <li>Keeping all the evidence around is expensive and slows down compilation </li> |
| </ul> |
| </article> |
| |
| <article id="builder-2-0"> |
| <h3> |
| Builder 2.0 |
| </h3> |
| <ul> |
| <li>When a file is compiled, check for structural changes by comparing signatures with previous .class file</li> |
| <li>If no structural changes, we are done</li> |
| <li>If there are structural changes, recompile all dependents</li> |
| <li>Faster on average and vastly more memory efficient than Eclipse 1.0 builder</li> |
| </ul> |
| </article> |
| |
| <article id="builder-lessons"> |
| <h3> |
| Lessons learned |
| </h3> |
| <ul> |
| <li>Sometimes you need to revisit your starting assumptions</li> |
| <li>Sometimes the optimal solution is not the best!</li> |
| <li>A simpler solution is often easier to maintain (unnecessary compilation no longer a bug)</li> |
| </ul> |
| </article> |
| |
| <!-- ************************************************************************ --> |
| |
| <article id="rcp-intro"> |
| <h3> |
| RCP refactoring |
| </h3> |
| <q> |
| Performs arbitrary actions when the event loop crashes. |
| </q> |
| <div class='author'> |
| WorkbenchAdvisor.java, line 297 |
| </div> |
| </article> |
| |
| <article id="rcp-background"> |
| <h3> |
| RCP history |
| </h3> |
| <ul> |
| <li>As an <b>integration</b> platform, Eclipse focus was on seamless integration</li> |
| <li>Plugins by design had little or no control over general appearance</li> |
| <li>Plugins could only add; not remove</li> |
| <li>But some people wanted to be able to build applications that looked very different</li> |
| <li>Wanted to remove some of the built in functionality</li> |
| </ul> |
| </article> |
| |
| <article id="rcp-refactoring"> |
| <h3> |
| RCP refactoring |
| </h3> |
| <ul> |
| <li>Mechanical part was scrubbing "tool" artifacts from API</li> |
| <li>Harder part: decoupling workbench from the application so other applications could use it</li> |
| <li>Required inversion of control - separating policy from mechanism</li> |
| <li>IDE-specific behavior and functionality separated from the workbench</li> |
| <li>Can't just create preferences - must be under application control</li> |
| </ul> |
| </article> |
| |
| <article id="rcp-advisor"> |
| <h3>Policy vs mechanism</h3> |
| <table> |
| <tr> |
| <th> |
| Mechanism |
| </th> |
| <th> |
| Policy |
| </th> |
| </tr> |
| <tr> |
| <td> |
| Error handling |
| </td> |
| <td> |
| Show error dialog, log, exit |
| </td> |
| </tr> |
| <tr> |
| <td> |
| Menus |
| </td> |
| <td> |
| What menus appear, what do they contain |
| </td> |
| </tr> |
| <tr> |
| <td> |
| Toolbars |
| </td> |
| <td> |
| Decide what commands appear in toolbar |
| </td> |
| </tr> |
| <tr> |
| <td> |
| Default perspective |
| </td> |
| <td> |
| Select default perspective |
| </td> |
| </tr> |
| <tr> |
| <td> |
| Startup |
| </td> |
| <td> |
| Restore settings, welcome screen, login |
| </td> |
| </tr> |
| <tr> |
| <td> |
| Window trim |
| </td> |
| <td> |
| Progress, status line, title |
| </td> |
| </tr> |
| </table> |
| </article> |
| |
| <article id="rcp-solution"> |
| <h3>Workbench advisor</h3> |
| <ul> |
| <li>Application in charge of creating a workbench if desired: <code>PlatformUI.createAndRunWorkbench(Display, WorkbenchAdvisor)</code></li> |
| <li><code>WorkbenchAdvisor</code> is consulted on aspects of window appearance, and has |
| "hooks" that are run on startup, window open, shutdown, etc.</li> |
| <li>Advisor has complete control over default set of commands in menu and toolbars</li> |
| <li>Plugins can still contribute their own extra commands if the menu/toolbar exists</li> |
| </ul> |
| </article> |
| |
| <article id="rcp-extensibility"> |
| <h3>Many ways to add policy</h3> |
| <table> |
| <tr> |
| <th> |
| Mechanism |
| </th> |
| <th> |
| Arity |
| </th> |
| <th> |
| User Control |
| </th> |
| <th> |
| App Control |
| </th> |
| <th> |
| Plugin Control |
| </th> |
| </tr> |
| <tr> |
| <td> |
| Extension points |
| </td> |
| <td> |
| Many |
| </td> |
| <td> |
| No |
| </td> |
| <td> |
| Transforms |
| </td> |
| <td> |
| Yes |
| </td> |
| </tr> |
| <tr> |
| <td> |
| Services |
| </td> |
| <td> |
| Many |
| </td> |
| <td> |
| No |
| </td> |
| <td> |
| No |
| </td> |
| <td> |
| Yes |
| </td> |
| </tr> |
| <tr> |
| <td> |
| Preferences |
| </td> |
| <td> |
| Many |
| </td> |
| <td> |
| Maybe |
| </td> |
| <td> |
| Yes |
| </td> |
| <td> |
| Yes |
| </td> |
| </tr> |
| <tr> |
| <td> |
| System prop |
| </td> |
| <td> |
| One |
| </td> |
| <td> |
| Yes |
| </td> |
| <td> |
| Yes |
| </td> |
| <td> |
| Yes |
| </td> |
| </tr> |
| <tr> |
| <td> |
| Advisor |
| </td> |
| <td> |
| One |
| </td> |
| <td> |
| No |
| </td> |
| <td> |
| Yes |
| </td> |
| <td> |
| No |
| </td> |
| </tr> |
| </table> |
| |
| </article> |
| |
| <article id="rcp-lessons"> |
| <h3>Lessons learned</h3> |
| <ul> |
| <li>The "policy" vs "mechanism" distinction burned into committer minds</li> |
| <li>When designing functionality, always have to ask if another app might want to do it differently</li> |
| <li>Is it something any plugin should be able to control? Or only application? Only user? |
| <li>There are many ways to offer extensibility with various tradeoffs</li> |
| </ul> |
| </article> |
| |
| <!-- ************************************************************************ --> |
| |
| <article id="command-intro"> |
| <h3> |
| Command framework |
| </h3> |
| <q> |
| Okay. Have a seat. Relax a while. This is going to be a bumpy ride. |
| </q> |
| <div class='author'> |
| WidgetMethodHandler.java, line 81 |
| </div> |
| </article> |
| |
| <article id="commands-history"> |
| <h3> |
| Key bindings history |
| </h3> |
| <ul> |
| <li>Eclipse 1.0: hard-coded, unmodifiable</li> |
| <li>Eclipse 2.0: plugins can contribute bindings, only editor bindings can be customized</li> |
| <li>Eclipse 2.1: user contributed key bindings, concept of scopes but limited (global vs editor)</li> |
| <li>Eclipse 3.0: key bindings in dialogs, expanded concept of scopes</li> |
| <li>Eclipse 3.1: Introduced command framework.. views can override global commands</li> |
| </ul> |
| </article> |
| |
| <article id="commands-challenges"> |
| <h3> |
| Challenges |
| </h3> |
| <ul> |
| <li>Decisions on every key stroke</li> |
| <li>Bindings change with active part/shell</li> |
| <li>Ctrl+B could be Build or Bold</li> |
| <li>F2 in Package Explorer could be refactor or file rename</li> |
| <li>Incrementally bolting on functionality to original design starting to become untenable</li> |
| <li>Committers leaving to open breweries, become apple farmers, or to live in an Ashram</li> |
| </ul> |
| </article> |
| |
| <article id="commands-framework"> |
| <h3> |
| Command framework |
| </h3> |
| <ul> |
| <li>Introduced separation between command and handler</li> |
| <li>Key bindings are mapped to commands, command get bound to handlers</li> |
| <li>Mapping from binding to command is stable -> Cache!</li> |
| <li>Relationship between command and handler still needs updating on each part activation</li> |
| <li>Only need to process commands that have a handler specific to that part</li> |
| </ul> |
| </article> |
| |
| <article id="commands-lessons"> |
| <h3> |
| Lessons learned |
| </h3> |
| <ul> |
| <li>Incrementally adding functionality over time can reach a breaking point where |
| you need a fundamental rethink</li> |
| <li>Creating a pure "model" layer between user inputs and resulting behaviour was very powerful</li> |
| <li>Different parts of the problem could be isolated and optimized</li> |
| </ul> |
| </article> |
| |
| <!-- ************************************************************************ --> |
| |
| <article id="p2-intro"> |
| <h3>p2 resolver</h3> |
| <q> |
| The fix is to avoid the workaround. |
| </q> |
| <div class='author'> |
| Control.java (Motif), 4076 |
| </div> |
| </article> |
| |
| <article id="p2-background"> |
| <h3>p2 Background</h3> |
| <ul> |
| <li>Update manager only resolved feature dependencies</li> |
| <li>Features: once installed, always installed</li> |
| <li>A feature you don't really care about can block install of something you really want</li> |
| <li>Resolving dependencies could sometimes be slow but was generally usable</li> |
| <li>Redundant expression of dependencies at feature and plugin level was a source of bugs</li> |
| </ul> |
| </article> |
| |
| <article id="p2-observations"> |
| <h3>Observations</h3> |
| <ul> |
| <li>Some installed things are "roots" that the user chose to install, |
| other things are installed only to satisfy dependencies </li> |
| <li>In p2 we wanted to ensure all dependencies were satisfied - feature, bundle, and package level</li> |
| <li>This is an NP hard constraint satisfaction problem, and our hand-crafted resolver wasn't good enough</li> |
| </ul> |
| </article> |
| |
| <article> |
| <h3>Boolean satisfaction problem</h3> |
| <ul> |
| <li>A series of boolean expressions (AND, OR, and NOT)</li> |
| <li>Is there a set of variable assignments that will satisfy all expressions</li> |
| <li>Or, what set of values satisfies the most expressions (MAX-SAT)</li> |
| </ul> |
| <pre> |
| 1: x & !y |
| 2: x | y |
| |
| Solution: x=true, y=false |
| </pre> |
| </article> |
| |
| <article> |
| <h3>Mapping install to SAT (Projector)</h3> |
| <pre> |
| a := Plugin A 1.0 - requires B [1.0,2.0) |
| b := Plugin B 1.0 |
| c := Plugin B 1.1 |
| |
| 1: (a & b) | (a & c) |
| 2: (b & !c) | (!b & c) |
| |
| Solution: a=true, b=false, c=true |
| </pre> |
| <ul> |
| <li>Also assign weights to expressions to cause higher plugin version to be favoured</li> |
| <li>Throw the problem at a SAT solver</li> |
| </ul> |
| </article> |
| |
| <article id="p2-lessons-learned"> |
| <h3>Lessons learned</h3> |
| <ul> |
| <li>Need to recognize when you have an NP hard problem</li> |
| <li>There are probably others who have solved this problem more efficiently</li> |
| <li>Those things you learned in school about algorithm complexity and isomorphism sometimes come in handy!</li> |
| </ul> |
| </article> |
| |
| <article id="the-end" class='nobackground'> |
| <h3> |
| Thank you |
| </h3> |
| <iframe src='http://www.eclipsecon.org/2012/program/session-schedule'></iframe> |
| </article> |
| |
| </section> |
| |
| </body> |
| </html> |