///******************************************************************************* // * 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(); // } //}