Skip to content

Commit

Permalink
Merge branch 'series/3.x' into chrome
Browse files Browse the repository at this point in the history
  • Loading branch information
armanbilge authored Jul 30, 2021
2 parents e55220d + c6b120f commit cdf004a
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright 2020-2021 Typelevel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cats.effect.benchmarks

import cats.effect.IO
import cats.effect.unsafe.implicits.global
import cats.implicits.{catsSyntaxParallelTraverse1, toTraverseOps}

import org.openjdk.jmh.annotations._
import org.openjdk.jmh.infra.Blackhole

import java.util.concurrent.TimeUnit

/**
* To do comparative benchmarks between versions:
*
* benchmarks/run-benchmark ParallelBenchmark
*
* This will generate results in `benchmarks/results`.
*
* Or to run the benchmark from within sbt:
*
* jmh:run -i 10 -wi 10 -f 2 -t 4 cats.effect.benchmarks.ParallelBenchmark
*
* Which means "10 iterations", "10 warm-up iterations", "2 forks", "4 thread".
* Please note that benchmarks should be usually executed at least in
* 10 iterations (as a rule of thumb), but more is better.
*/
@State(Scope.Thread)
@BenchmarkMode(Array(Mode.Throughput))
@OutputTimeUnit(TimeUnit.SECONDS)
class ParallelBenchmark {

@Param(Array("100", "1000", "10000"))
var size: Int = _

@Param(Array("100", "1000", "10000", "100000", "1000000"))
var cpuTokens: Long = _

@Benchmark
def parTraverse(): Unit =
1.to(size).toList.parTraverse(_ => IO(Blackhole.consumeCPU(cpuTokens))).void.unsafeRunSync()

@Benchmark
def traverse(): Unit =
1.to(size).toList.traverse(_ => IO(Blackhole.consumeCPU(cpuTokens))).void.unsafeRunSync()
}
35 changes: 31 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ import org.openqa.selenium.remote.server.DriverProvider
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.firefox.FirefoxOptions
import org.openqa.selenium.firefox.FirefoxProfile
import org.scalajs.jsenv.selenium.SeleniumJSEnv

import JSEnv._

ThisBuild / baseVersion := "3.1"
ThisBuild / baseVersion := "3.2"

ThisBuild / organization := "org.typelevel"
ThisBuild / organizationName := "Typelevel"
Expand Down Expand Up @@ -140,8 +141,11 @@ ThisBuild / Test / jsEnv := {
useJSEnv.value match {
case NodeJS => old
case Firefox =>
val profile = new FirefoxProfile()
profile.setPreference("privacy.file_unique_origin", false)
val options = new FirefoxOptions()
options.setHeadless(true)
options.setProfile(profile)
options.addArguments("-headless")
new SeleniumJSEnv(options)
case Chrome =>
val options = new ChromeOptions()
Expand Down Expand Up @@ -190,14 +194,23 @@ addCommandAlias("ciJS", "; project rootJS; headerCheck; scalafmtCheck; clean; te

// we do the browser ci *only* on core because we're only really interested in IO here
def browserCiCommand(browser: JSEnv) =
s"; set Global / useJSEnv := JSEnv.$browser; project rootJS; headerCheck; scalafmtCheck; clean; testsJS/test; set Global / useJSEnv := JSEnv.NodeJS"
s"; set Global / useJSEnv := JSEnv.$browser; project rootJS; headerCheck; scalafmtCheck; clean; testsJS/test; webWorkerTests/test; set Global / useJSEnv := JSEnv.NodeJS"
addCommandAlias("ciFirefox", browserCiCommand(Firefox))
addCommandAlias("ciChrome", browserCiCommand(Chrome))

addCommandAlias("prePR", "; root/clean; scalafmtSbt; +root/scalafmtAll; +root/headerCreate")

val jsProjects: Seq[ProjectReference] =
Seq(kernel.js, kernelTestkit.js, laws.js, core.js, testkit.js, tests.js, std.js, example.js)
Seq(
kernel.js,
kernelTestkit.js,
laws.js,
core.js,
testkit.js,
tests.js,
webWorkerTests,
std.js,
example.js)

val undocumentedRefs =
jsProjects ++ Seq[ProjectReference](benchmarks, example.jvm)
Expand Down Expand Up @@ -378,6 +391,20 @@ lazy val tests = crossProject(JSPlatform, JVMPlatform)
Test / fork := true,
Test / javaOptions += s"-Dsbt.classpath=${(Test / fullClasspath).value.map(_.data.getAbsolutePath).mkString(File.pathSeparator)}")

lazy val webWorkerTests = project
.in(file("webworker-tests"))
.dependsOn(tests.js % "compile->test")
.enablePlugins(ScalaJSPlugin, BuildInfoPlugin, NoPublishPlugin)
.settings(
name := "cats-effect-webworker-tests",
scalaJSUseMainModuleInitializer := true,
libraryDependencies += ("org.scala-js" %%% "scalajs-dom" % "1.1.0")
.cross(CrossVersion.for3Use2_13),
(Test / test) := (Test / test).dependsOn(Compile / fastOptJS).value,
buildInfoKeys := Seq[BuildInfoKey](scalaVersion, baseDirectory),
buildInfoPackage := "cats.effect"
)

/**
* Implementations lof standard functionality (e.g. Semaphore, Console, Queue)
* purely in terms of the typeclasses, with no dependency on IO. In most cases,
Expand Down
1 change: 1 addition & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.4.3")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.3")
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.2.22")
addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.4.3")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0")
53 changes: 53 additions & 0 deletions webworker-tests/src/main/scala/cats/effect/IOSpecRunner.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2020-2021 Typelevel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cats.effect

import org.scalajs.dom.webworkers.DedicatedWorkerGlobalScope
import org.specs2.control.ExecuteActions
import org.specs2.reporter.BufferedLineLogger
import org.specs2.runner.ClassRunner
import org.specs2.runner.Runner
import org.specs2.specification.core.Env

import scala.scalajs.js

object IOSpecRunner extends IOApp.Simple with ClassRunner {

def postMessage(msg: js.Any): Unit = DedicatedWorkerGlobalScope.self.postMessage(msg)

override def run: IO[Unit] = IO.fromFuture {
IO {
val spec = new IOSpec
val env = Env(lineLogger = new BufferedLineLogger {
override def infoLine(msg: String): Unit = postMessage(s"[info] $msg")
override def failureLine(msg: String): Unit = postMessage(s"[error] $msg")
override def errorLine(msg: String): Unit = postMessage(s"[error] $msg")
override def warnLine(msg: String): Unit = postMessage(s"[warn] $msg")
})
val loader = new ClassLoader() {}
val action = for {
printers <- createPrinters(env.arguments, loader).toAction
stats <- Runner.runSpecStructure(spec.structure(env), env, loader, printers)
// TODO I have no idea how to suspend effects in this
_ = postMessage(stats.toString)
_ = postMessage(stats.isSuccess)
} yield ()
ExecuteActions.runActionFuture(action)(env.executionEnv)
}
}

}
56 changes: 56 additions & 0 deletions webworker-tests/src/test/scala/cats/effect/WebWorkerIOSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2020-2021 Typelevel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package cats.effect

import org.scalajs.dom.webworkers.Worker
import org.scalajs.dom.window

import scala.concurrent.duration._
import scala.util.Try

class WebWorkerIOSpec extends BaseSpec {

override def executionTimeout = 5.minutes // This is to run the _entire_ IOSpec

def scalaVersion = if (BuildInfo.scalaVersion.startsWith("2"))
BuildInfo.scalaVersion.split("\\.").init.mkString(".")
else
BuildInfo.scalaVersion

def targetDir = s"${BuildInfo.baseDirectory}/target/scala-${scalaVersion}"

Try(window).toOption.foreach { _ =>
"io on webworker" should {
"pass the spec" in real {
for {
worker <- IO(
new Worker(s"file://${targetDir}/cats-effect-webworker-tests-fastopt/main.js"))
success <- IO.async_[Boolean] { cb =>
worker.onmessage = { event =>
event.data match {
case log: String => println(log)
case success: Boolean => cb(Right(success))
case _ => ()
}
}
}
} yield success mustEqual true
}
}
}

}
22 changes: 22 additions & 0 deletions webworker-tests/src/test/scala/java/io/File.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2020-2021 Typelevel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package java.io

// hack hack buildinfo hack
class File(path: String) {
override def toString() = path
}

0 comments on commit cdf004a

Please sign in to comment.