Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@
import static org.eclipse.ui.tests.harness.util.UITestUtil.openTestWindow;
import static org.eclipse.ui.tests.harness.util.UITestUtil.processEvents;
import static org.eclipse.ui.tests.performance.UIPerformanceTestRule.getTestProject;
import static org.eclipse.ui.tests.performance.UIPerformanceTestUtil.reportTimings;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.test.performance.PerformanceTestCaseJunit4;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
Expand All @@ -36,10 +41,30 @@
import org.junit.runners.Parameterized.Parameters;

/**
* Measures opening many editors and closing them again. Reports the cost of the
* first and the last editors separately, so that a cost that grows with the
* number of open editors is visible.
*
* @since 3.1
*/
@RunWith(Parameterized.class)
public class OpenMultipleEditorTest extends PerformanceTestCaseJunit4 {
public class OpenMultipleEditorTest {

/**
* Stays below the REUSE_EDITORS threshold, which defaults to 99. Above it the
* workbench recycles the oldest editor, so further opens would measure reuse
* rather than opening.
*/
private static final int EDITOR_COUNT = 90;

/**
* Enough editors to get the editor implementation loaded and compiled. Below
* roughly this many, the reported times are dominated by JIT warm-up.
*/
private static final int WARMUP_EDITORS = 20;

/** How many editors at each end of the run are reported on their own. */
private static final int SEGMENT = 10;

@ClassRule
public static final UIPerformanceTestRule uiPerformanceTestRule = new UIPerformanceTestRule();
Expand All @@ -50,7 +75,7 @@ public class OpenMultipleEditorTest extends PerformanceTestCaseJunit4 {
private final String extension;
private final boolean closeAll;

@Parameters(name = "{index}: closeAll: {0} - closeEach: {1}")
@Parameters(name = "{index}: {0} - closeAll: {1}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] { { "perf_basic", true }, { "perf_outline", true }, { "perf_text", true },
{ "perf_basic", false }, { "perf_outline", false }, { "perf_text", false } });
Expand All @@ -64,27 +89,71 @@ public OpenMultipleEditorTest(String extension, boolean closeAll) {
@Test
public void test() throws Throwable {
IWorkbenchWindow window = openTestWindow(UIPerformanceTestRule.PERSPECTIVE1);
IWorkbenchPage activePage = window.getActivePage();
IWorkbenchPage page = window.getActivePage();

startMeasuring();
// Class loading and JIT warm-up would otherwise end up in the reported times.
openEditors(page, WARMUP_EDITORS, null);
page.closeAllEditors(false);
processEvents();
EditorTestHelper.calmDown(500, 30000, 500);

List<Long> openTimes = new ArrayList<>();
openEditors(page, EDITOR_COUNT, openTimes);
assertEquals("Not all editors stayed open. The workbench recycles the oldest editor once REUSE_EDITORS"
+ " (default 99) are open, so EDITOR_COUNT has to stay below that threshold.", EDITOR_COUNT,
page.getEditorReferences().length);

String label = extension + (closeAll ? ", closeAll" : ", closeEach");
reportTimings("openMultiple[" + label + "] open", openTimes);
reportTimings("openMultiple[" + label + "] open, first " + SEGMENT, openTimes.subList(0, SEGMENT));
reportTimings("openMultiple[" + label + "] open, last " + SEGMENT,
openTimes.subList(EDITOR_COUNT - SEGMENT, EDITOR_COUNT));

for (int i = 0; i < 100; i++) {
IFile file = getTestProject().getFile(i + "." + extension);
IDE.openEditor(activePage, file, true);
processEvents();
}
if (closeAll) {
activePage.closeAllEditors(false);
long before = System.nanoTime();
page.closeAllEditors(false);
processEvents();
reportTimings("openMultiple[" + label + "] closeAllEditors", List.of(System.nanoTime() - before));
} else {
List<Long> closeTimes = closeEditorsIndividually(page);
reportTimings("openMultiple[" + label + "] close", closeTimes);
reportTimings("openMultiple[" + label + "] close, first " + SEGMENT, closeTimes.subList(0, SEGMENT));
reportTimings("openMultiple[" + label + "] close, last " + SEGMENT,
closeTimes.subList(EDITOR_COUNT - SEGMENT, EDITOR_COUNT));
}
else {
IEditorReference[] parts = activePage.getEditorReferences();
for (IEditorReference part : parts) {
activePage.closeEditor(part.getEditor(false), false);
assertEquals("Not all editors were closed", 0, page.getEditorReferences().length);
}

/**
* Opens {@code count} editors, recording each open when the given list is not
* {@code null}.
*/
private void openEditors(IWorkbenchPage page, int count, List<Long> openTimes) throws Exception {
for (int i = 0; i < count; i++) {
IFile file = getTestProject().getFile(i + "." + extension);
long before = System.nanoTime();
IEditorPart part = IDE.openEditor(page, file, true);
processEvents();
long after = System.nanoTime();
assertNotNull("No editor opened for " + file.getName(), part);

if (openTimes != null) {
openTimes.add(after - before);
}
}
stopMeasuring();
commitMeasurements();
assertPerformance();
}

private static List<Long> closeEditorsIndividually(IWorkbenchPage page) {
List<Long> closeTimes = new ArrayList<>();
for (IEditorReference reference : page.getEditorReferences()) {
IEditorPart part = reference.getEditor(false);
assertNotNull("Editor was never created: " + reference.getId(), part);

long before = System.nanoTime();
page.closeEditor(part, false);
processEvents();
closeTimes.add(System.nanoTime() - before);
}
return closeTimes;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@
import static org.eclipse.ui.tests.harness.util.UITestUtil.processEvents;
import static org.eclipse.ui.tests.performance.UIPerformanceTestRule.getTestProject;
import static org.eclipse.ui.tests.performance.UIPerformanceTestUtil.exercise;
import static org.eclipse.ui.tests.performance.UIPerformanceTestUtil.reportTimings;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.test.performance.PerformanceTestCaseJunit4;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveRegistry;
import org.eclipse.ui.IWorkbenchPage;
Expand All @@ -42,10 +46,23 @@
import org.junit.runners.Parameterized.Parameters;

/**
* Test perspective switching.
* Measures switching back and forth between two perspectives, and reports each
* switch direction separately.
*/
@RunWith(Parameterized.class)
public class PerspectiveSwitchTest extends PerformanceTestCaseJunit4 {
public class PerspectiveSwitchTest {

/**
* Enough switches to get the participating parts loaded and compiled. Below
* roughly this many, the reported times are dominated by JIT warm-up.
*/
private static final int WARMUP_PAIRS = 5;

private static final int MIN_PAIRS = 5;

private static final int MAX_PAIRS = 50;

private static final int MAX_MEASURE_TIME_MS = 12000;

@ClassRule
public static final UIPerformanceTestRule uiPerformanceTestRule = new UIPerformanceTestRule();
Expand Down Expand Up @@ -80,28 +97,18 @@ public PerspectiveSwitchTest(String id1, String id2, String activeEditor) {
this.activeEditor = activeEditor;
}

/**
* Test perspective switching performance.
*/
@Test
public void test() throws CoreException, WorkbenchException {
// Get the two perspectives to switch between.
final IPerspectiveRegistry registry = WorkbenchPlugin.getDefault().getPerspectiveRegistry();
final IPerspectiveDescriptor perspective1 = registry.findPerspectiveWithId(id1);
final IPerspectiveDescriptor perspective2 = registry.findPerspectiveWithId(id2);

// Don't fail if we reference an unknown perspective ID. This can be
// a normal occurrance since the test suites reference JDT perspectives, which
// might not exist. Just skip the test.
if (perspective1 == null) {
System.out.println("Unknown perspective ID: " + id1);
return;
}

if (perspective2 == null) {
System.out.println("Unknown perspective ID: " + id2);
return;
}
// The parameters reference JDT perspectives, which are not part of every target
// platform. Skip visibly rather than reporting a pass for something that was
// never measured.
assumeTrue("Perspective not available: " + id1, perspective1 != null);
assumeTrue("Perspective not available: " + id2, perspective2 != null);

// Open the two perspectives and the file, in a new window.
// Do this outside the loop so as not to include
Expand All @@ -111,25 +118,43 @@ public void test() throws CoreException, WorkbenchException {
assertNotNull(page);
page.setPerspective(perspective2);

// IFile aFile = getProject().getFile("1." +
// EditorPerformanceSuite.EDITOR_FILE_EXTENSIONS[0]);
IFile aFile = getTestProject().getFile(activeEditor);
assertTrue(aFile.exists());
assertTrue("Missing test file " + activeEditor + ", the fixture does not create it", aFile.exists());

IDE.openEditor(page, aFile, true);

// Class loading and JIT warm-up would otherwise end up in the reported times.
for (int i = 0; i < WARMUP_PAIRS; i++) {
switchTo(page, perspective1, null);
switchTo(page, perspective2, null);
}
EditorTestHelper.calmDown(500, 30000, 500);

List<Long> toFirst = new ArrayList<>();
List<Long> toSecond = new ArrayList<>();

exercise(() -> {
processEvents();

startMeasuring();
page.setPerspective(perspective1);
processEvents();
page.setPerspective(perspective2);
processEvents();
stopMeasuring();
});

commitMeasurements();
assertPerformance();
switchTo(page, perspective1, toFirst);
switchTo(page, perspective2, toSecond);
}, MIN_PAIRS, MAX_PAIRS, MAX_MEASURE_TIME_MS);

reportTimings("PerspectiveSwitch to [" + id1 + "]", toFirst);
reportTimings("PerspectiveSwitch to [" + id2 + "]", toSecond);
}

/**
* Switches to the given perspective, recording the time when the given list is
* not {@code null}.
*/
private static void switchTo(IWorkbenchPage page, IPerspectiveDescriptor perspective, List<Long> times) {
long before = System.nanoTime();
page.setPerspective(perspective);
processEvents();
long after = System.nanoTime();
assertEquals("Wrong perspective active", perspective, page.getPerspective());

if (times != null) {
times.add(after - before);
}
}
}
Loading