Add warning for slow hostname lookups on OS X

I spent a lot of time debugging why it took 5 seconds to run tests each
time. It turns out that if the hostname is not set explicitly on os x,
then getaddrinfo takes 5 seconds to try (and fail) to resolve the dns
entry for the localhostname. This is easily fixed by setting the
hostname, but it is not at all easy to figure out that a slow hostname
lookup is the reason why tests are slow to start.

I don't know if this is a common issue on other platforms, so only issue
the warning on OS X.
This commit is contained in:
Ethan Atkins 2017-11-24 12:43:50 -08:00
parent 2848770f85
commit 27e93601b5
3 changed files with 23 additions and 5 deletions

View File

@ -1039,7 +1039,9 @@ private[sbt] object Load {
// Grab all the settings we already loaded from sbt files // Grab all the settings we already loaded from sbt files
def settings(files: Seq[File]): Seq[Setting[_]] = { def settings(files: Seq[File]): Seq[Setting[_]] = {
if (files.nonEmpty) if (files.nonEmpty)
log.info(s"${files.map(_.getName).mkString(s"Loading settings for project ${p.id} from ", ",", " ...")}") log.info(
s"${files.map(_.getName).mkString(s"Loading settings for project ${p.id} from ", ",", " ...")}"
)
for { for {
file <- files file <- files
config <- (memoSettings get file).toSeq config <- (memoSettings get file).toSeq

View File

@ -30,6 +30,6 @@ object JUnitXmlReportPlugin extends AutoPlugin {
// It might be a good idea to derive this setting into specific test scopes. // It might be a good idea to derive this setting into specific test scopes.
override lazy val projectSettings: Seq[Setting[_]] = override lazy val projectSettings: Seq[Setting[_]] =
Seq( Seq(
testListeners += new JUnitXmlTestsListener(target.value.getAbsolutePath) testListeners += new JUnitXmlTestsListener(target.value.getAbsolutePath, streams.value.log)
) )
} }

View File

@ -13,8 +13,10 @@ import java.time.LocalDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
import java.util.Hashtable import java.util.Hashtable
import java.util.concurrent.TimeUnit.NANOSECONDS
import scala.collection.mutable.ListBuffer import scala.collection.mutable.ListBuffer
import scala.util.Properties
import scala.xml.{ Elem, Node => XNode, XML } import scala.xml.{ Elem, Node => XNode, XML }
import testing.{ import testing.{
Event => TEvent, Event => TEvent,
@ -23,6 +25,7 @@ import testing.{
OptionalThrowable, OptionalThrowable,
TestSelector TestSelector
} }
import util.Logger
import sbt.protocol.testing.TestResult import sbt.protocol.testing.TestResult
/** /**
@ -30,14 +33,27 @@ import sbt.protocol.testing.TestResult
* report format. * report format.
* @param outputDir path to the dir in which a folder with results is generated * @param outputDir path to the dir in which a folder with results is generated
*/ */
class JUnitXmlTestsListener(val outputDir: String) extends TestsListener { class JUnitXmlTestsListener(val outputDir: String, logger: Logger) extends TestsListener {
// This constructor is for binary compatibility with older versions of sbt.
def this(outputDir: String) = this(outputDir, null)
/**Current hostname so we know which machine executed the tests*/ /**Current hostname so we know which machine executed the tests*/
val hostname = val hostname = {
try InetAddress.getLocalHost.getHostName val start = System.nanoTime
val name = try InetAddress.getLocalHost.getHostName
catch { catch {
case _: IOException => "localhost" case _: IOException => "localhost"
} }
val elapsed = System.nanoTime - start
if ((NANOSECONDS.toSeconds(elapsed) >= 4) && Properties.isMac && logger != null) {
logger.warn(
s"Getting the hostname $name was slow (${elapsed / 1.0e6} ms). " +
"This is likely because the computer's hostname is not set. You can set the " +
"hostname with the command: scutil --set HostName $(scutil --get LocalHostName)."
)
}
name
}
/**The dir in which we put all result files. Is equal to the given dir + "/test-reports"*/ /**The dir in which we put all result files. Is equal to the given dir + "/test-reports"*/
val targetDir = new File(outputDir + "/test-reports/") val targetDir = new File(outputDir + "/test-reports/")