| ///******************************************************************************* |
| // * Copyright (c) 2000, 2006 IBM Corporation and others. |
| // * All rights reserved. This program and the accompanying materials |
| // * are made available under the terms of the Eclipse Public License v1.0 |
| // * which accompanies this distribution, and is available at |
| // * http://www.eclipse.org/legal/epl-v10.html |
| // * |
| // * Contributors: |
| // * IBM Corporation - initial API and implementation |
| // *******************************************************************************/ |
| //package org.eclipse.ui.tests.performance; |
| // |
| //import java.util.ArrayList; |
| //import java.util.HashSet; |
| //import java.util.List; |
| //import java.util.Locale; |
| //import java.util.Set; |
| // |
| //import org.eclipse.core.commands.Command; |
| //import org.eclipse.core.commands.CommandManager; |
| //import org.eclipse.core.commands.ParameterizedCommand; |
| //import org.eclipse.core.commands.common.NotDefinedException; |
| //import org.eclipse.core.commands.contexts.Context; |
| //import org.eclipse.core.commands.contexts.ContextManager; |
| //import org.eclipse.jface.bindings.Binding; |
| //import org.eclipse.jface.bindings.BindingManager; |
| //import org.eclipse.jface.bindings.Scheme; |
| //import org.eclipse.jface.bindings.keys.IKeyLookup; |
| //import org.eclipse.jface.bindings.keys.KeyBinding; |
| //import org.eclipse.jface.bindings.keys.KeyLookupFactory; |
| //import org.eclipse.jface.bindings.keys.KeySequence; |
| //import org.eclipse.jface.bindings.keys.KeyStroke; |
| //import org.eclipse.jface.bindings.keys.ParseException; |
| //import org.eclipse.swt.SWT; |
| // |
| ///** |
| // * <p> |
| // * Responsible for testing the commands, contexts and bindings architecture. |
| // * This test does not rely on the existence of the workbench; it operates purely |
| // * on JFace code and lower. See the method comments for descriptions of the |
| // * currently supported performance tests. |
| // * </p> |
| // * |
| // * @since 3.1 |
| // */ |
| //public final class CommandsPerformanceTest extends BasicPerformanceTest { |
| // |
| // /** |
| // * <p> |
| // * Constructs a branch of a context tree. This creates a branch of the given |
| // * depth -- remembering the identifiers along the way. This method operates |
| // * recursively. |
| // * </p> |
| // * <p> |
| // * TODO This should add a bit of breadth to the tree. |
| // * </p> |
| // * |
| // * @param contextManager |
| // * The context manager in which the contexts should be defined; |
| // * must not be <code>null</code>. |
| // * @param parent |
| // * The parent context identifier for the context to be created; |
| // * may be <code>null</code>. |
| // * @param successors |
| // * The number of successors to create. The depth of the branch to |
| // * be created. If this number is zero, then a context is created, |
| // * but no recursive call is made. |
| // * @param activeContextIds |
| // * The list of active context identifiers; must not be |
| // * <code>null</code>. |
| // */ |
| // private static final void createContext( |
| // final ContextManager contextManager, final String parent, |
| // final int successors, final List activeContextIds) { |
| // final int count = activeContextIds.size(); |
| // final String contextString = "context" + count; |
| // final Context context = contextManager.getContext(contextString); |
| // context.define(contextString, contextString, parent); |
| // activeContextIds.add(contextString); |
| // |
| // if (successors == 0) { |
| // return; |
| // } |
| // |
| // createContext(contextManager, contextString, successors - 1, |
| // activeContextIds); |
| // } |
| // |
| // /** |
| // * <p> |
| // * Constructs a branch of a scheme tree. This creates a branch of the given |
| // * depth -- remembering the schemes along the way. This method operates |
| // * recursively. |
| // * </p> |
| // * <p> |
| // * TODO This should add a bit of breadth to the tree. |
| // * </p> |
| // * |
| // * @param bindingManager |
| // * The binding manager in which the schemes should be defined; |
| // * must not be <code>null</code>. |
| // * @param parent |
| // * The parent scheme identifier for the scheme to be created; may |
| // * be <code>null</code>. |
| // * @param successors |
| // * The number of successors to create. The depth of the branch to |
| // * be created. If this number is zero, then a scheme is created, |
| // * but no recursive call is made. |
| // * @param schemes |
| // * The list of created schemes; must not be <code>null</code>. |
| // */ |
| // private static final void createScheme(final BindingManager bindingManager, |
| // final String parent, final int successors, final List schemes) { |
| // final int count = schemes.size(); |
| // final String schemeString = "scheme" + count; |
| // final Scheme scheme = bindingManager.getScheme(schemeString); |
| // scheme.define(schemeString, schemeString, parent); |
| // schemes.add(scheme); |
| // |
| // if (successors == 0) { |
| // return; |
| // } |
| // |
| // createScheme(bindingManager, schemeString, successors - 1, schemes); |
| // } |
| // |
| // /** |
| // * The binding manager for the currently running test. <code>null</code> |
| // * if no test is running. |
| // */ |
| // private BindingManager bindingManager = null; |
| // |
| // /** |
| // * The command manager for the currently running test. <code>null</code> |
| // * if no test is running. |
| // */ |
| // private CommandManager commandManager = null; |
| // |
| // /** |
| // * The context manager for the currently running test. <code>null</code> |
| // * if no test is running. |
| // */ |
| // private ContextManager contextManager = null; |
| // |
| // /** |
| // * Constructs an instance of <code>CommandsPerformanceTest</code>. |
| // * |
| // * @param testName |
| // * Test's name. |
| // */ |
| // public CommandsPerformanceTest(final String name) { |
| // super(name); |
| // } |
| // |
| // /** |
| // * <p> |
| // * Sets up a sufficiently complex set of bindings. |
| // * </p> |
| // * <p> |
| // * At the time of writing, Eclipse's key binding set contains about five |
| // * hundred bindings. Of these, 140 specify platform information, while only |
| // * 5 specify locale information. About 40 are deletion markers. The deepest |
| // * point in the context tree is four levels. There are two schemes. |
| // * </p> |
| // * <p> |
| // * The test binding set contains five thousand bindings. About 1400 specify |
| // * either locale or platform information. Five hundred are deletion markers. |
| // * The deepest point in the context tree is 40 levels. There are twenty |
| // * schemes. |
| // * </p> |
| // * <p> |
| // * The depth of the locale and platform tree is the same in both real life |
| // * and the test case. It is difficult to imagine why the locale list would |
| // * ever be anything but four elements, or why the platform list would ever |
| // * be anything but three elements. |
| // * </p> |
| // * |
| // * @throws NotDefinedException |
| // * If something went wrong initializing the active scheme. |
| // */ |
| // protected final void doSetUp() throws NotDefinedException, Exception { |
| // super.doSetUp(); |
| // |
| // /* |
| // * The constants to use in creating the various objects. The platform |
| // * locale count must be greater than or equal to the number of deletion |
| // * markers. Deletion markers are typically created based on the platform |
| // * or locale. |
| // */ |
| // final int contextTreeDepth = 40; |
| // final int schemeDepth = 20; |
| // final int bindingCount = 5000; |
| // final int platformLocaleCount = 1400; |
| // final int deletionMarkers = 500; |
| // final String currentLocale = Locale.getDefault().toString(); |
| // final String currentPlatform = SWT.getPlatform(); |
| // |
| // // Set-up a table of modifier keys. |
| // final IKeyLookup lookup = KeyLookupFactory.getDefault(); |
| // final int modifierKeys0 = 0; |
| // final int modifierKeys1 = lookup.getAlt(); |
| // final int modifierKeys2 = lookup.getCommand(); |
| // final int modifierKeys3 = lookup.getCtrl(); |
| // final int modifierKeys4 = lookup.getShift(); |
| // final int modifierKeys5 = lookup.getAlt() | lookup.getCommand(); |
| // final int modifierKeys6 = lookup.getAlt() | lookup.getCtrl(); |
| // final int modifierKeys7 = lookup.getAlt() | lookup.getShift(); |
| // final int modifierKeys8 = lookup.getCommand() | lookup.getCtrl(); |
| // final int modifierKeys9 = lookup.getCommand() | lookup.getShift(); |
| // final int modifierKeys10 = lookup.getCtrl() | lookup.getShift(); |
| // final int modifierKeys11 = lookup.getAlt() | lookup.getCommand() |
| // | lookup.getCtrl(); |
| // final int modifierKeys12 = lookup.getAlt() | lookup.getCommand() |
| // | lookup.getShift(); |
| // final int modifierKeys13 = lookup.getAlt() | lookup.getCtrl() |
| // | lookup.getShift(); |
| // final int modifierKeys14 = lookup.getCommand() | lookup.getCtrl() |
| // | lookup.getShift(); |
| // final int modifierKeys15 = lookup.getAlt() | lookup.getCommand() |
| // | lookup.getCtrl() | lookup.getShift(); |
| // final int[] modifierKeyTable = { modifierKeys0, modifierKeys1, |
| // modifierKeys2, modifierKeys3, modifierKeys4, modifierKeys5, |
| // modifierKeys6, modifierKeys7, modifierKeys8, modifierKeys9, |
| // modifierKeys10, modifierKeys11, modifierKeys12, modifierKeys13, |
| // modifierKeys14, modifierKeys15 }; |
| // |
| // // Initialize the command manager. |
| // commandManager = new CommandManager(); |
| // |
| // // Initialize the contexts. |
| // contextManager = new ContextManager(); |
| // final List activeContextIds = new ArrayList(); |
| // createContext(contextManager, null, contextTreeDepth, activeContextIds); |
| // contextManager.setActiveContextIds(new HashSet(activeContextIds)); |
| // |
| // // Initialize the schemes. |
| // bindingManager = new BindingManager(contextManager, commandManager); |
| // final List schemes = new ArrayList(); |
| // createScheme(bindingManager, null, schemeDepth, schemes); |
| // bindingManager |
| // .setActiveScheme((Scheme) schemes.get(schemes.size() - 1)); |
| // |
| // // Create the deletion markers. |
| // final Binding[] bindings = new Binding[bindingCount]; |
| // for (int i = 0; i < deletionMarkers; i++) { |
| // /* |
| // * Set-up the locale and platform. These are based on the numbers |
| // * given above. |
| // */ |
| // String locale = null; |
| // String platform = null; |
| // |
| // if (i < platformLocaleCount) { |
| // switch (i % 4) { |
| // case 0: |
| // locale = currentLocale; |
| // break; |
| // case 1: |
| // platform = currentPlatform; |
| // break; |
| // case 2: |
| // locale = "gibberish"; |
| // break; |
| // case 3: |
| // platform = "gibberish"; |
| // break; |
| // } |
| // } |
| // |
| // // Build a key sequence. |
| // final char character = (char) ('A' + (i % 26)); |
| // final int modifierKeys = modifierKeyTable[(i / 26) |
| // % modifierKeyTable.length]; |
| // final KeyStroke keyStroke = KeyStroke.getInstance(modifierKeys, |
| // character); |
| // final KeySequence keySequence = KeySequence.getInstance(keyStroke); |
| // |
| // // Build the other parameters. |
| // final String schemeId = ((Scheme) schemes.get(i % schemes.size())) |
| // .getId(); |
| // final String contextId = (String) activeContextIds.get(i |
| // % activeContextIds.size()); |
| // final int type = (i % 2); |
| // |
| // // Construct the binding. |
| // final Binding binding = new KeyBinding(keySequence, null, schemeId, |
| // contextId, locale, platform, null, type); |
| // bindings[i] = binding; |
| // } |
| // |
| // /* |
| // * Now create the regular bindings. By using the same loop structure and |
| // * resetting the index to zero, we ensure that the deletion markers will |
| // * actually delete something. |
| // */ |
| // for (int i = 0; i < bindingCount - deletionMarkers; i++) { |
| // /* |
| // * Set-up the locale and platform for those bindings that will not |
| // * be used to match the above deletion markers. These are based on |
| // * the numbers given above. |
| // */ |
| // String locale = null; |
| // String platform = null; |
| // |
| // if ((i > deletionMarkers) && (i < platformLocaleCount)) { |
| // switch (i % 4) { |
| // case 0: |
| // locale = currentLocale; |
| // break; |
| // case 1: |
| // platform = currentPlatform; |
| // break; |
| // case 2: |
| // locale = "gibberish"; |
| // break; |
| // case 3: |
| // platform = "gibberish"; |
| // break; |
| // } |
| // } |
| // |
| // // Build a key sequence. |
| // final char character = (char) ('A' + (i % 26)); |
| // final int modifierKeys = modifierKeyTable[(i / 26) |
| // % modifierKeyTable.length]; |
| // final KeyStroke keyStroke = KeyStroke.getInstance(modifierKeys, |
| // character); |
| // final KeySequence keySequence = KeySequence.getInstance(keyStroke); |
| // |
| // // Build the other parameters. |
| // final String commandId = "command" + i; |
| // final String schemeId = ((Scheme) schemes.get(i % schemes.size())) |
| // .getId(); |
| // final String contextId = (String) activeContextIds.get(i |
| // % activeContextIds.size()); |
| // final int type = (i % 2); |
| // |
| // // Construct the binding. |
| // final Command command = commandManager.getCommand(commandId); |
| // final ParameterizedCommand parameterizedCommand = new ParameterizedCommand( |
| // command, null); |
| // final Binding binding = new KeyBinding(keySequence, |
| // parameterizedCommand, schemeId, contextId, locale, |
| // platform, null, type); |
| // bindings[i + deletionMarkers] = binding; |
| // } |
| // bindingManager.setBindings(bindings); |
| // } |
| // |
| // protected final void doTearDown() throws Exception { |
| // bindingManager = null; |
| // commandManager = null; |
| // contextManager = null; |
| // super.doTearDown(); |
| // } |
| // |
| // /** |
| // * <p> |
| // * Tests how long it takes to access the cache if no conditions have |
| // * changed. It measures how long it takes to look up the computation from |
| // * the cache one million times. |
| // * </p> |
| // * |
| // * @throws ParseException |
| // * If "CTRL+F" can't be parsed for some strange reason. |
| // */ |
| // public final void testBindingCacheHitHard() throws ParseException { |
| // // Constants |
| // final int cacheHits = 1000000; |
| // final KeySequence keySequence = KeySequence.getInstance("CTRL+F"); |
| // |
| // // Compute once. |
| // bindingManager.getPartialMatches(keySequence); |
| // |
| // // Time how long it takes to access the cache; |
| // startMeasuring(); |
| // for (int i = 0; i < cacheHits; i++) { |
| // bindingManager.getPartialMatches(keySequence); |
| // } |
| // stopMeasuring(); |
| // commitMeasurements(); |
| // assertPerformance(); |
| // } |
| // |
| // /** |
| // * <p> |
| // * Tests how long it takes to access the cache if no conditions have |
| // * changed. It measures how long it takes to look up the computation from |
| // * the cache one million times. In this test, the look-up is done in reverse -- |
| // * from command identifier to trigger. |
| // * </p> |
| // * |
| // * @throws ParseException |
| // * If "CTRL+F" can't be parsed for some strange reason. |
| // */ |
| // public final void testBindingCacheHitHardReverse() throws ParseException { |
| // // Constants |
| // final int cacheHits = 1000000; |
| // final KeySequence keySequence = KeySequence.getInstance("CTRL+F"); |
| // |
| // // Compute once. |
| // bindingManager.getPartialMatches(keySequence); |
| // |
| // // Time how long it takes to access the cache; |
| // startMeasuring(); |
| // for (int i = 0; i < cacheHits; i++) { |
| // bindingManager.getActiveBindingsFor((ParameterizedCommand) null); |
| // } |
| // stopMeasuring(); |
| // commitMeasurements(); |
| // assertPerformance(); |
| // } |
| // |
| // /** |
| // * <p> |
| // * Tests how long it takes to access the cache if the conditions have |
| // * changed, but the cache contains a matching entry. It measures how long it |
| // * takes to look up the computation from the cache forty thousand times. |
| // * </p> |
| // * |
| // * @throws ParseException |
| // * If "CTRL+F" can't be parsed for some strange reason. |
| // */ |
| // public final void testBindingCacheHitSoft() throws ParseException { |
| // // Constants |
| // final int cacheHits = 10000; |
| // final KeySequence keySequence = KeySequence.getInstance("CTRL+F"); |
| // |
| // // Compute once for each context set. |
| // final Set contextSet1 = contextManager.getActiveContextIds(); |
| // bindingManager.getPartialMatches(keySequence); |
| // final List contextList = new ArrayList(contextSet1); |
| // contextList.remove(contextList.size() - 1); |
| // final Set contextSet2 = new HashSet(contextList); |
| // contextManager.setActiveContextIds(contextSet2); |
| // bindingManager.getPartialMatches(keySequence); |
| // |
| // // Time how long it takes to access the cache; |
| // startMeasuring(); |
| // for (int i = 0; i < cacheHits; i++) { |
| // if ((i % 2) == 0) { |
| // contextManager.setActiveContextIds(contextSet1); |
| // } else { |
| // contextManager.setActiveContextIds(contextSet2); |
| // } |
| // bindingManager.getPartialMatches(keySequence); |
| // } |
| // stopMeasuring(); |
| // commitMeasurements(); |
| // assertPerformance(); |
| // } |
| // |
| // /** |
| // * <p> |
| // * Tests how long it takes to do a full computation (i.e., a cache miss) on |
| // * an exceptionally large set of bindings. The binding set tries to mimick |
| // * some of the same properties of a "real" binding set. |
| // * </p> |
| // * |
| // * @throws ParseException |
| // * If "CTRL+F" can't be parsed for some strange reason. |
| // */ |
| // public final void testBindingCacheMissLarge() throws ParseException { |
| // // Constants |
| // final KeySequence keySequence = KeySequence.getInstance("CTRL+F"); |
| // |
| // // Time how long it takes to solve the binding set. |
| // startMeasuring(); |
| // bindingManager.getPartialMatches(keySequence); |
| // stopMeasuring(); |
| // commitMeasurements(); |
| // assertPerformance(); |
| // } |
| //} |