diff options
author | ulfjack <ulfjack@google.com> | 2018-06-11 09:46:50 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-06-11 09:48:24 -0700 |
commit | 15b8c259db111012b4642287172cb4d1d82151f3 (patch) | |
tree | 0d46f77b5b25bfd67440c102de54c7de5ff05add /src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java | |
parent | 6841a748109250f65448627bc5695d537990b686 (diff) |
Refactor profiler
- move the save method to an inner class
- don't use a timer, use a blocking queue instead
- add a format enum (in anticipation of adding a json output format)
- update the test to use an in memory buffer, and avoid FoundationTestCase
PiperOrigin-RevId: 200065404
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java | 141 |
1 files changed, 74 insertions, 67 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java b/src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java index ae1d572596..60a331c890 100644 --- a/src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java +++ b/src/test/java/com/google/devtools/build/lib/profiler/ProfilerTest.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.profiler; import static com.google.common.truth.Truth.assertThat; +import static com.google.devtools.build.lib.profiler.Profiler.Format.BINARY_BAZEL_FORMAT; import static java.nio.charset.StandardCharsets.ISO_8859_1; import com.google.common.collect.ImmutableList; @@ -23,14 +24,12 @@ import com.google.devtools.build.lib.clock.Clock; import com.google.devtools.build.lib.profiler.Profiler.ProfiledTaskKinds; import com.google.devtools.build.lib.profiler.Profiler.SlowTask; import com.google.devtools.build.lib.profiler.analysis.ProfileInfo; -import com.google.devtools.build.lib.testutil.FoundationTestCase; import com.google.devtools.build.lib.testutil.ManualClock; import com.google.devtools.build.lib.testutil.Suite; import com.google.devtools.build.lib.testutil.TestSpec; import com.google.devtools.build.lib.testutil.TestUtils; -import com.google.devtools.build.lib.vfs.FileSystemUtils; -import com.google.devtools.build.lib.vfs.Path; -import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; @@ -40,6 +39,7 @@ import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; +import junit.framework.TestCase; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,29 +50,28 @@ import org.junit.runners.JUnit4; */ @TestSpec(size = Suite.MEDIUM_TESTS) // testConcurrentProfiling takes ~700ms, testProfiler 100ms. @RunWith(JUnit4.class) -public class ProfilerTest extends FoundationTestCase { +public class ProfilerTest extends TestCase { - private Path cacheDir; private Profiler profiler = Profiler.instance(); private ManualClock clock; @Before - public final void createCacheDirectory() throws Exception { - cacheDir = scratch.dir("/tmp"); - } - - @Before public final void setManualClock() { clock = new ManualClock(); BlazeClock.setClock(clock); } + private ByteArrayOutputStream start(ProfiledTaskKinds kinds, Profiler.Format format) { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + profiler.start( + kinds, buffer, format, "test", false, BlazeClock.instance(), BlazeClock.nanoTime()); + return buffer; + } + @Test public void testProfilerActivation() throws Exception { - Path cacheFile = cacheDir.getRelative("profile1.dat"); assertThat(profiler.isActive()).isFalse(); - profiler.start(ProfiledTaskKinds.ALL, cacheFile.getOutputStream(), "basic test", false, - BlazeClock.instance(), BlazeClock.instance().nanoTime()); + start(ProfiledTaskKinds.ALL, BINARY_BAZEL_FORMAT); assertThat(profiler.isActive()).isTrue(); profiler.stop(); @@ -81,14 +80,12 @@ public class ProfilerTest extends FoundationTestCase { @Test public void testTaskDetails() throws Exception { - Path cacheFile = cacheDir.getRelative("profile1.dat"); - profiler.start(ProfiledTaskKinds.ALL, cacheFile.getOutputStream(), "basic test", false, - BlazeClock.instance(), BlazeClock.instance().nanoTime()); + ByteArrayOutputStream buffer = start(ProfiledTaskKinds.ALL, BINARY_BAZEL_FORMAT); try (SilentCloseable c = profiler.profile(ProfilerTask.ACTION, "action task")) { profiler.logEvent(ProfilerTask.INFO, "event"); } profiler.stop(); - ProfileInfo info = ProfileInfo.loadProfile(cacheFile); + ProfileInfo info = ProfileInfo.loadProfile(new ByteArrayInputStream(buffer.toByteArray())); info.calculateStats(); ProfileInfo.Task task = info.allTasksById.get(0); @@ -104,9 +101,7 @@ public class ProfilerTest extends FoundationTestCase { @Test public void testProfiler() throws Exception { - Path cacheFile = cacheDir.getRelative("profile1.dat"); - profiler.start(ProfiledTaskKinds.ALL, cacheFile.getOutputStream(), "basic test", false, - BlazeClock.instance(), BlazeClock.instance().nanoTime()); + ByteArrayOutputStream buffer = start(ProfiledTaskKinds.ALL, BINARY_BAZEL_FORMAT); profiler.logSimpleTask(BlazeClock.instance().nanoTime(), ProfilerTask.PHASE, "profiler start"); try (SilentCloseable c = profiler.profile(ProfilerTask.ACTION, "complex task")) { @@ -125,7 +120,7 @@ public class ProfilerTest extends FoundationTestCase { // all other calls to profiler should be ignored profiler.logEvent(ProfilerTask.PHASE, "should be ignored"); - ProfileInfo info = ProfileInfo.loadProfile(cacheFile); + ProfileInfo info = ProfileInfo.loadProfile(new ByteArrayInputStream(buffer.toByteArray())); info.calculateStats(); assertThat(info.allTasksById).hasSize(6); // only 5 tasks + finalization should be recorded @@ -160,16 +155,22 @@ public class ProfilerTest extends FoundationTestCase { @Test public void testProfilerRecordingAllEvents() throws Exception { - Path cacheFile = cacheDir.getRelative("profile1.dat"); - profiler.start(ProfiledTaskKinds.ALL, cacheFile.getOutputStream(), "basic test", true, - BlazeClock.instance(), BlazeClock.instance().nanoTime()); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + profiler.start( + ProfiledTaskKinds.ALL, + buffer, + BINARY_BAZEL_FORMAT, + "basic test", + true, + BlazeClock.instance(), + BlazeClock.instance().nanoTime()); try (SilentCloseable c = profiler.profile(ProfilerTask.ACTION, "action task")) { // Next task takes less than 10 ms but should be recorded anyway. clock.advanceMillis(1); profiler.logSimpleTask(BlazeClock.instance().nanoTime(), ProfilerTask.VFS_STAT, "stat1"); } profiler.stop(); - ProfileInfo info = ProfileInfo.loadProfile(cacheFile); + ProfileInfo info = ProfileInfo.loadProfile(new ByteArrayInputStream(buffer.toByteArray())); info.calculateStats(); assertThat(info.allTasksById).hasSize(3); // 2 tasks + finalization should be recorded @@ -182,10 +183,16 @@ public class ProfilerTest extends FoundationTestCase { @Test public void testProfilerRecordingOnlySlowestEvents() throws Exception { - Path profileData = cacheDir.getRelative("foo"); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - profiler.start(ProfiledTaskKinds.SLOWEST, profileData.getOutputStream(), "test", true, - BlazeClock.instance(), BlazeClock.instance().nanoTime()); + profiler.start( + ProfiledTaskKinds.SLOWEST, + buffer, + BINARY_BAZEL_FORMAT, + "test", + true, + BlazeClock.instance(), + BlazeClock.instance().nanoTime()); profiler.logSimpleTask(10000, 20000, ProfilerTask.VFS_STAT, "stat"); profiler.logSimpleTask(20000, 30000, ProfilerTask.REMOTE_EXECUTION, "remote execution"); @@ -194,7 +201,7 @@ public class ProfilerTest extends FoundationTestCase { profiler.stop(); - ProfileInfo info = ProfileInfo.loadProfile(profileData); + ProfileInfo info = ProfileInfo.loadProfile(new ByteArrayInputStream(buffer.toByteArray())); info.calculateStats(); assertThat(info.allTasksById).hasSize(1); // only VFS_STAT task should be recorded @@ -207,6 +214,7 @@ public class ProfilerTest extends FoundationTestCase { profiler.start( ProfiledTaskKinds.SLOWEST, ByteStreams.nullOutputStream(), + BINARY_BAZEL_FORMAT, "test", /*recordAllDurations=*/ true, BlazeClock.instance(), @@ -279,10 +287,15 @@ public class ProfilerTest extends FoundationTestCase { @Test public void testProfilerRecordsNothing() throws Exception { - Path profileData = cacheDir.getRelative("foo"); - - profiler.start(ProfiledTaskKinds.NONE, profileData.getOutputStream(), "test", true, - BlazeClock.instance(), BlazeClock.instance().nanoTime()); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + profiler.start( + ProfiledTaskKinds.NONE, + buffer, + BINARY_BAZEL_FORMAT, + "test", + true, + BlazeClock.instance(), + BlazeClock.instance().nanoTime()); profiler.logSimpleTask(10000, 20000, ProfilerTask.VFS_STAT, "stat"); assertThat(ProfilerTask.VFS_STAT.collectsSlowestInstances()).isTrue(); @@ -290,16 +303,14 @@ public class ProfilerTest extends FoundationTestCase { profiler.stop(); - ProfileInfo info = ProfileInfo.loadProfile(profileData); + ProfileInfo info = ProfileInfo.loadProfile(new ByteArrayInputStream(buffer.toByteArray())); info.calculateStats(); assertThat(info.allTasksById).isEmpty(); } @Test public void testConcurrentProfiling() throws Exception { - Path cacheFile = cacheDir.getRelative("profile3.dat"); - profiler.start(ProfiledTaskKinds.ALL, cacheFile.getOutputStream(), "concurrent test", false, - BlazeClock.instance(), BlazeClock.instance().nanoTime()); + ByteArrayOutputStream buffer = start(ProfiledTaskKinds.ALL, BINARY_BAZEL_FORMAT); long id = Thread.currentThread().getId(); Thread thread1 = new Thread() { @@ -329,7 +340,7 @@ public class ProfilerTest extends FoundationTestCase { } profiler.stop(); - ProfileInfo info = ProfileInfo.loadProfile(cacheFile); + ProfileInfo info = ProfileInfo.loadProfile(new ByteArrayInputStream(buffer.toByteArray())); info.calculateStats(); info.analyzeRelationships(); assertThat(info.allTasksById).hasSize(4 + 10000 + 10000); // total number of tasks @@ -353,9 +364,7 @@ public class ProfilerTest extends FoundationTestCase { @Test public void testPhaseTasks() throws Exception { - Path cacheFile = cacheDir.getRelative("profile4.dat"); - profiler.start(ProfiledTaskKinds.ALL, cacheFile.getOutputStream(), "phase test", false, - BlazeClock.instance(), BlazeClock.instance().nanoTime()); + ByteArrayOutputStream buffer = start(ProfiledTaskKinds.ALL, BINARY_BAZEL_FORMAT); Thread thread1 = new Thread() { @Override public void run() { for (int i = 0; i < 100; i++) { @@ -394,7 +403,7 @@ public class ProfilerTest extends FoundationTestCase { clock.advanceMillis(1); profiler.stop(); - ProfileInfo info = ProfileInfo.loadProfile(cacheFile); + ProfileInfo info = ProfileInfo.loadProfile(new ByteArrayInputStream(buffer.toByteArray())); info.calculateStats(); info.analyzeRelationships(); // number of tasks: INIT(1) + LOAD(1) + Thread1.TEST(100) + ANALYZE(1) @@ -417,9 +426,7 @@ public class ProfilerTest extends FoundationTestCase { @Test public void testCorruptedFile() throws Exception { - Path cacheFile = cacheDir.getRelative("profile5.dat"); - profiler.start(ProfiledTaskKinds.ALL, cacheFile.getOutputStream(), "phase test", false, - BlazeClock.instance(), BlazeClock.instance().nanoTime()); + ByteArrayOutputStream buffer = start(ProfiledTaskKinds.ALL, BINARY_BAZEL_FORMAT); for (int i = 0; i < 100; i++) { try (SilentCloseable c = profiler.profile(ProfilerTask.INFO, "outer task " + i)) { clock.advanceMillis(1); @@ -428,14 +435,12 @@ public class ProfilerTest extends FoundationTestCase { } profiler.stop(); - ProfileInfo info = ProfileInfo.loadProfile(cacheFile); + ProfileInfo info = ProfileInfo.loadProfile(new ByteArrayInputStream(buffer.toByteArray())); info.calculateStats(); assertThat(info.isCorruptedOrIncomplete()).isFalse(); - Path corruptedFile = cacheDir.getRelative("profile5bad.dat"); - FileSystemUtils.writeContent( - corruptedFile, Arrays.copyOf(FileSystemUtils.readContent(cacheFile), 2000)); - info = ProfileInfo.loadProfile(corruptedFile); + info = ProfileInfo.loadProfile( + new ByteArrayInputStream(Arrays.copyOf(buffer.toByteArray(), 2000))); info.calculateStats(); assertThat(info.isCorruptedOrIncomplete()).isTrue(); // Since root tasks will appear after nested tasks in the profile file and @@ -447,9 +452,7 @@ public class ProfilerTest extends FoundationTestCase { @Test public void testUnsupportedProfilerRecord() throws Exception { - Path dataFile = cacheDir.getRelative("profile5.dat"); - profiler.start(ProfiledTaskKinds.ALL, dataFile.getOutputStream(), "phase test", false, - BlazeClock.instance(), BlazeClock.instance().nanoTime()); + ByteArrayOutputStream buffer = start(ProfiledTaskKinds.ALL, BINARY_BAZEL_FORMAT); try (SilentCloseable c = profiler.profile(ProfilerTask.INFO, "outer task")) { profiler.logEvent(ProfilerTask.PHASE, "inner task"); } @@ -459,29 +462,28 @@ public class ProfilerTest extends FoundationTestCase { profiler.stop(); // Validate our test profile. - ProfileInfo info = ProfileInfo.loadProfile(dataFile); + ProfileInfo info = ProfileInfo.loadProfile(new ByteArrayInputStream(buffer.toByteArray())); info.calculateStats(); assertThat(info.isCorruptedOrIncomplete()).isFalse(); assertThat(info.getStatsForType(ProfilerTask.INFO, info.rootTasksById).count).isEqualTo(3); assertThat(info.getStatsForType(ProfilerTask.UNKNOWN, info.rootTasksById).count).isEqualTo(0); // Now replace "TEST" type with something unsupported - e.g. "XXXX". - InputStream in = new InflaterInputStream(dataFile.getInputStream(), new Inflater(false), 65536); - byte[] buffer = new byte[60000]; - int len = in.read(buffer); - in.close(); - assertThat(len).isLessThan(buffer.length); // Validate that file was completely decoded. - String content = new String(buffer, ISO_8859_1); + byte[] deflated = ByteStreams.toByteArray(new InflaterInputStream( + new ByteArrayInputStream(buffer.toByteArray()), new Inflater(false), 65536)); + String content = new String(deflated, ISO_8859_1); int infoIndex = content.indexOf("INFO"); assertThat(infoIndex).isGreaterThan(0); content = content.substring(0, infoIndex) + "XXXX" + content.substring(infoIndex + 4); - OutputStream out = new DeflaterOutputStream(dataFile.getOutputStream(), - new Deflater(Deflater.BEST_SPEED, false), 65536); + + buffer = new ByteArrayOutputStream(); + OutputStream out = + new DeflaterOutputStream(buffer, new Deflater(Deflater.BEST_SPEED, false), 65536); out.write(content.getBytes(ISO_8859_1)); out.close(); // Validate that XXXX records were classified as UNKNOWN. - info = ProfileInfo.loadProfile(dataFile); + info = ProfileInfo.loadProfile(new ByteArrayInputStream(buffer.toByteArray())); info.calculateStats(); assertThat(info.isCorruptedOrIncomplete()).isFalse(); assertThat(info.getStatsForType(ProfilerTask.INFO, info.rootTasksById).count).isEqualTo(0); @@ -505,9 +507,14 @@ public class ProfilerTest extends FoundationTestCase { return initialNanoTime - numNanoTimeCalls.addAndGet(1); } }; - Path cacheFile = cacheDir.getRelative("profile1.dat"); - profiler.start(ProfiledTaskKinds.ALL, cacheFile.getOutputStream(), - "testResilenceToNonDecreasingNanoTimes", false, badClock, initialNanoTime); + profiler.start( + ProfiledTaskKinds.ALL, + new ByteArrayOutputStream(), + BINARY_BAZEL_FORMAT, + "testResilenceToNonDecreasingNanoTimes", + false, + badClock, + initialNanoTime); profiler.logSimpleTask(badClock.nanoTime(), ProfilerTask.INFO, "some task"); profiler.stop(); } |