Repository: square/leakcanary
File: leakcanary-android-instrumentation/src/androidTest/java/leakcanary/Profiler.kt (Kotlin)

Code before:
   * the function execution.
   * First, it awaits for Profiler to be attached at start of sampling, then executes [block]
   * and finally waits for sampling to stop. See [waitForSamplingStart] and [waitForSamplingStop]
   * for more details.
   */
  fun <T> runWithProfilerSampling(block: () -> T): T {
    waitForSamplingStart()
    val result = block()
    waitForSamplingStop()
    return result
  }

  private const val TRACES_FOLDER = "/sdcard/traces/"
  private const val TRACE_NAME_PATTERN = "yyyy-MM-dd_HH-mm-ss_SSS'.trace'"
  private const val BUFFER_SIZE = 50 * 1024 * 1024
  private const val TRACE_INTERVAL_US = 1000

  /**
   * Executes the given function [block] with method tracing to SD card and returns the result of
   * the function execution.
   * Tracing is performed with [Debug.startMethodTracingSampling] which uses sampling with
   * [TRACE_INTERVAL_US] microseconds interval.
   * Trace file will be stored in [TRACES_FOLDER] and can be pulled via `adb pull` command.
   * See Logcat output for an exact command to retrieve trace file
   */
  fun <T> runWithMethodTracing(block: () -> T): T {
    java.io.File(TRACES_FOLDER).mkdirs()
    val fileName = SimpleDateFormat(TRACE_NAME_PATTERN, Locale.US).format(Date())
    Debug.startMethodTracingSampling(
        "$TRACES_FOLDER$fileName",
        BUFFER_SIZE,
        TRACE_INTERVAL_US
    )
    val result = block()
    Debug.stopMethodTracing()
    SharkLog.d { "Method tracing complete! Run following command to retrieve your trace:" }
    SharkLog.d { "adb pull $TRACES_FOLDER$fileName ~/Downloads/ " }
    return result
  }

  private inline fun sleepUntil(condition: () -> Boolean) {
    while (true) {
      if (condition()) return else Thread.sleep(SLEEP_TIME_MILLIS)
    }
  }

  private fun samplingThreadExists() = findThread(SAMPLING_THREAD_NAME) != null

  /**
   * Utility to get thread by its name; in case of multiple matches first one will be returned.
   */

Review comment (suggestion):
nit: wondering if folder, buffer size and interval should be params with default values. Not necessary though

Code after:
   * the function execution.
   * First, it awaits for Profiler to be attached at start of sampling, then executes [block]
   * and finally waits for sampling to stop. See [waitForSamplingStart] and [waitForSamplingStop]
   * for more details.
   */
  fun <T> runWithProfilerSampling(block: () -> T): T {
    waitForSamplingStart()
    val result = block()
    waitForSamplingStop()
    return result
  }

  private const val TRACES_FOLDER = "/sdcard/traces/"
  private const val TRACE_NAME_PATTERN = "yyyy-MM-dd_HH-mm-ss_SSS'.trace'"
  private const val BUFFER_SIZE = 50 * 1024 * 1024
  private const val TRACE_INTERVAL_US = 1000

  /**
   * Executes the given function [block] with method tracing to SD card and returns the result of
   * the function execution.
   * Tracing is performed with [Debug.startMethodTracingSampling] which uses sampling with
   * [TRACE_INTERVAL_US] microseconds interval.
   * Trace file will be stored in [TRACES_FOLDER] and can be pulled via `adb pull` command.
   * See Logcat output for an exact command to retrieve trace file
   */
  fun <T> runWithMethodTracing(block: () -> T): T {
    java.io.File(TRACES_FOLDER).mkdirs()
    val fileName = SimpleDateFormat(TRACE_NAME_PATTERN, Locale.US).format(Date())
    Debug.startMethodTracingSampling(
        "$TRACES_FOLDER$fileName",
        BUFFER_SIZE,
        TRACE_INTERVAL_US
    )
    val result = block()
    Debug.stopMethodTracing()
    SharkLog.d { "Method tracing complete! Run the following command to retrieve the trace:" }
    SharkLog.d { "adb pull $TRACES_FOLDER$fileName ~/Downloads/ " }
    return result
  }

  private inline fun sleepUntil(condition: () -> Boolean) {
    while (true) {
      if (condition()) return else Thread.sleep(SLEEP_TIME_MILLIS)
    }
  }

  private fun samplingThreadExists() = findThread(SAMPLING_THREAD_NAME) != null

  /**
   * Utility to get thread by its name; in case of multiple matches first one will be returned.
   */