Merge pull request #7714 from adpi2/2.x-fix-7711

[2.x] Reduce heap size after load
This commit is contained in:
adpi2 2024-10-02 17:12:49 +02:00 committed by GitHub
commit d4e2f91008
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 85 additions and 69 deletions

View File

@ -308,10 +308,11 @@ trait Cont:
tupleMapRepr.asType match
case '[tupleMap] =>
'{
given Applicative[F] = $applicativeExpr
import TupleMapExtension.*
${ br.tupleExpr.asInstanceOf[Expr[Tuple.Map[inputTypeTpe & Tuple, F]]] }
.mapN(${ lambda.asExprOf[inputTypeTpe & Tuple => A1] })
$applicativeExpr.mapN(
${ br.tupleExpr.asInstanceOf[Expr[Tuple.Map[inputTypeTpe & Tuple, F]]] }
)(
${ lambda.asExprOf[inputTypeTpe & Tuple => A1] }
)
}
eitherTree match
case Left(_) =>

View File

@ -242,7 +242,7 @@ object Def extends BuildSyntax with Init[Scope] with InitializeImplicits:
sbt.internal.util.complete.Parsers.spaceDelimited(argLabel)
/** Lifts the result of a setting initialization into a Task. */
def toITask[A1](i: Initialize[A1]): Initialize[Task[A1]] = map(i)(std.TaskExtra.inlineTask)
def toITask[A1](i: Initialize[A1]): Initialize[Task[A1]] = i(std.TaskExtra.inlineTask)
inline def toSParser[A1](p: Parser[A1]): State => Parser[A1] = const(p)
def toISParser[A1](p: Initialize[Parser[A1]]): Initialize[State => Parser[A1]] =

View File

@ -347,14 +347,10 @@ object Scoped:
protected def onTask[A2](f: Task[A1] => Task[A2]): Initialize[Task[A2]] =
init.apply(f)
def flatMapTaskValue[T](f: A1 => Task[T]): Initialize[Task[T]] =
onTask(_.result flatMap (f compose successM))
def map[A2](f: A1 => A2): Initialize[Task[A2]] =
onTask(_.result map (f compose successM))
def andFinally(fin: => Unit): Initialize[Task[A1]] =
onTask(_ andFinally fin)
def doFinally(t: Task[Unit]): Initialize[Task[A1]] =
onTask(_ doFinally t)
def flatMapTaskValue[T](f: A1 => Task[T]): Initialize[Task[T]] = onTask(_.flatMap(f))
def map[A2](f: A1 => A2): Initialize[Task[A2]] = onTask(_.map(f))
def andFinally(fin: => Unit): Initialize[Task[A1]] = onTask(_.andFinally(fin))
def doFinally(t: Task[Unit]): Initialize[Task[A1]] = onTask(_.doFinally(t))
def ||[T >: A1](alt: Task[T]): Initialize[Task[T]] = onTask(_ || alt)
def &&[T](alt: Task[T]): Initialize[Task[T]] = onTask(_ && alt)
def tag(tags: Tag*): Initialize[Task[A1]] = onTask(_.tag(tags: _*))
@ -842,4 +838,4 @@ class TupleWrap[Tup <: Tuple](value: Tuple.Map[Tup, Taskable]):
type InitTask[A2] = Initialize[Task[A2]]
lazy val initTasks = value.transform[InitTask]([a] => (t: Taskable[a]) => t.toTask)
def mapN[A1](f: Tup => A1): Def.Initialize[Task[A1]] =
initTasks.mapN[A1](f)(using std.FullInstance.initializeTaskMonad)
std.FullInstance.initializeTaskMonad.mapN(initTasks)(f)

View File

@ -18,7 +18,9 @@ object InitializeInstance:
type F[x] = Initialize[x]
override def pure[A1](a: () => A1): Initialize[A1] = Def.pure(a)
override def map[A1, A2](in: Initialize[A1])(f: A1 => A2): Initialize[A2] = Def.map(in)(f)
override def map[A1, A2](in: Initialize[A1])(f: A1 => A2): Initialize[A2] = in(f)
override def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, Initialize])(f: A1 => A2): Initialize[A2] =
Def.app(t)(f)
override def ap[A1, A2](ff: Initialize[A1 => A2])(fa: Initialize[A1]): Initialize[A2] =
Def.ap[A1, A2](ff)(fa)
override def flatMap[A1, A2](fa: Initialize[A1])(f: A1 => Initialize[A2]) =
@ -63,6 +65,10 @@ object FullInstance:
override def map[A1, A2](fa: Initialize[Task[A1]])(f: A1 => A2): Initialize[Task[A2]] =
F1F2.map(fa)(f)
override def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, [a] =>> Initialize[Task[a]]])(
f: A1 => A2
): Initialize[Task[A2]] = F1F2.mapN(t)(f)
override def ap[A1, A2](ff: Initialize[Task[A1 => A2]])(
fa: Initialize[Task[A1]]
): Initialize[Task[A2]] =

View File

@ -50,6 +50,7 @@ object Task:
}
override def map[A1, A2](in: Task[A1])(f: A1 => A2): Task[A2] = in.map(f)
override def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, Task])(f: A1 => A2): Task[A2] = t.mapN(f)
override def flatMap[A1, A2](in: F[A1])(f: A1 => F[A2]): F[A2] = in.flatMap(f)
override def flatten[A1](in: Task[Task[A1]]): Task[A1] = in.flatMap(identity)
end Task

View File

@ -313,8 +313,7 @@ object TaskExtra extends TaskExtra {
if incs.isEmpty then in.unmap(Result.tryValue)
else throw incompleteDeps(incs)
}
def failuresM[Tup <: Tuple]: Tuple.Map[Tup, Result] => Seq[Incomplete] = x =>
failures(x.iterator.toList)
def failuresM[Tup <: Tuple]: Tuple.Map[Tup, Result] => Seq[Incomplete] = x => failures(x.toList0)
def all[D](in: Seq[Result[D]]): Seq[D] = {
val incs = failures(in)

View File

@ -74,7 +74,7 @@ object Transform:
)(f: Tuple.Map[Tup, Result] => Either[Task[A1], A1]): Node[A1] =
new Node[A1]:
type Inputs = Tuple.Map[Tup, Result]
def dependencies: List[TaskId[?]] = deps.iterator.toList
def dependencies: List[TaskId[?]] = deps.toList0
def computeInputs(f: [a] => TaskId[a] => Result[a]) = deps.transform(f)
def work(inputs: Inputs) = f(inputs)

View File

@ -221,7 +221,7 @@ abstract class EvaluateSettings[ScopeType]:
private[this] final class MixedNode[Tup <: Tuple, A1](in: Tuple.Map[Tup, INode], f: Tup => A1)
extends INode[A1]:
import TupleMapExtension.*
protected override def dependsOn: Seq[INode[_]] = in.iterator.toList
protected override def dependsOn: Seq[INode[_]] = in.toList0
protected override def evaluate0(): Unit = setValue(f(in.unmap(getValue)))
private[this] final class UniformNode[A1, A2](in: List[INode[A1]], f: List[A1] => A2)

View File

@ -104,12 +104,12 @@ trait Init[ScopeType]:
Optional(Some(i), f)
def update[A1](key: ScopedKey[A1])(f: A1 => A1): Setting[A1] =
setting[A1](key, map(key)(f), NoPosition)
setting[A1](key, key(f), NoPosition)
def flatMap[A1, A2](in: Initialize[A1])(f: A1 => Initialize[A2]): Initialize[A2] = Bind(f, in)
def map[A1, A2](in: Initialize[A1])(f: A1 => A2): Initialize[A2] =
app[Tuple1[A1], A2](Tuple1(in)) { case Tuple1(x) => f(x) }
private[this] def map[A1, A2](in: Initialize[A1])(f: A1 => A2): Initialize[A2] =
Apply[Tuple1[A1], A2](x => f(x(0)), Tuple1(in))
def app[Tup <: Tuple, A2](inputs: Tuple.Map[Tup, Initialize])(f: Tup => A2): Initialize[A2] =
Apply[Tup, A2](f, inputs)
@ -801,7 +801,8 @@ trait Init[ScopeType]:
(fa: Initialize[A]) => (fa.mapConstant(g))
private[this] def evaluateK(g: Settings[ScopeType]): [A] => Initialize[A] => A = [A] =>
(fa: Initialize[A]) => (fa.evaluate(g))
private[this] def deps(ls: Seq[Initialize[_]]): Seq[ScopedKey[_]] = ls.flatMap(_.dependencies)
private[this] def deps(ls: List[Initialize[_]]): Seq[ScopedKey[_]] =
ls.flatMap(_.dependencies)
/**
* An `Initialize[T]` associated with a `ScopedKey[S]`.
@ -969,16 +970,7 @@ trait Init[ScopeType]:
private[sbt] override def processAttributes[A2](init: A2)(f: (A2, AttributeMap) => A2): A2 =
inputs.foldLeft(init)((v, i) => i.processAttributes(v)(f))
/* private[sbt] final class Mapped[A1, A2](f: A1 => A2, input: Initialize[A1]) extends Initialize[A1]:
override def dependencies: Seq[ScopedKey[_]] = deps(Seq(inputs))
override def mapReferenced(g: MapScoped): Initialize[A2] = Mapped(f, input.mapReferenced(g))
override def mapConstant(g: MapConstant): Initialize[A2] = Mapped(f, input.mapConstant(g))
override def apply[A3](g: A2 => A3): Initialize[A3] = Mapped(g.compose(f), input)
override def evaluate(ss: Settings[ScopeType]): A2 = f(input.evaluate(ss))
override def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A1] = input.validateKeyReferenced(g)
private[sbt] override def processAttributes[A2](init: A2)(f: (A2, AttributeMap) => A2): A2 =
input.processAttributes(init)(f) */
end Uniform
private[sbt] final class Apply[Tup <: Tuple, A1](
val f: Tup => A1,
@ -986,7 +978,7 @@ trait Init[ScopeType]:
) extends Initialize[A1]:
import sbt.internal.util.TupleMapExtension.*
override def dependencies: Seq[ScopedKey[_]] = deps(inputs.iterator.toList)
override def dependencies: Seq[ScopedKey[_]] = deps(inputs.toList0)
override def mapReferenced(g: MapScoped): Initialize[A1] =
Apply(f, inputs.transform(mapReferencedK(g)))
override def mapConstant(g: MapConstant): Initialize[A1] =
@ -998,13 +990,13 @@ trait Init[ScopeType]:
override def validateKeyReferenced(g: ValidateKeyRef): ValidatedInit[A1] =
val tx: Tuple.Map[Tup, ValidatedInit] = inputs.transform(validateKeyReferencedK(g))
val undefs = tx.iterator.flatMap(_.left.toSeq.flatten)
val undefs = tx.iterator.flatMap(_.left.getOrElse(Seq.empty))
val get = [A] => (fa: ValidatedInit[A]) => fa.toOption.get
if undefs.isEmpty then Right(Apply(f, tx.transform(get)))
else Left(undefs.toSeq)
private[sbt] override def processAttributes[A2](init: A2)(f: (A2, AttributeMap) => A2): A2 =
inputs.iterator.toList.foldLeft(init) { (v, i) => i.processAttributes(v)(f) }
inputs.toList0.foldLeft(init) { (v, i) => i.processAttributes(v)(f) }
end Apply
private def remove[A](s: Seq[A], v: A) = s.filterNot(_ == v)

View File

@ -5,28 +5,50 @@
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt.internal
package util
import sbt.util.Applicative
package sbt.internal.util
object TupleMapExtension:
extension [Tup <: Tuple, F1[_]](tuple: Tuple.Map[Tup, F1])
def iterator: Iterator[F1[Any]] = tuple.productIterator.asInstanceOf[Iterator[F1[Any]]]
def unmap(f: [a] => F1[a] => a): Tup =
Tuple.fromArray(tuple.iterator.map(f(_)).toArray).asInstanceOf[Tup]
// typed version of tuple.toList
def toList0: List[F1[Any]] =
tuple.iterator.toList.asInstanceOf[List[F1[Any]]]
def unmap(f: [a] => F1[a] => a): Tup = transform[[A] =>> A](f).asInstanceOf[Tup]
def transform[F2[_]](f: [a] => F1[a] => F2[a]): Tuple.Map[Tup, F2] =
Tuple.fromArray(tuple.iterator.map(f(_)).toArray).asInstanceOf[Tuple.Map[Tup, F2]]
def traverse[F2[_]](f: [a] => F1[a] => F2[a])(using app: Applicative[F2]): F2[Tup] =
val fxs: F2[List[Any]] = tuple.iterator
.foldRight[F2[List[Any]]](app.pure(() => Nil))((x, xs) =>
app.map(app.product(f(x), xs))((h, t) => h :: t)
)
app.map(fxs)(xs => Tuple.fromArray(xs.toArray).asInstanceOf[Tup])
def mapN[A1](f: Tup => A1)(using app: Applicative[F1]): F1[A1] =
app.map(tuple.traverse[F1]([a] => (f: F1[a]) => f))(f)
inline def f0(x: Any) = f(x.asInstanceOf[F1[Any]])
// We could use tuple.map from the scala3-library but it creates temporary arrays
// which has an impact on the performance.
// Instead, for small tuples, of size under 22, we map over each element manually.
// format: off
val res = (tuple: Tuple) match
case EmptyTuple => EmptyTuple
case t: NonEmptyTuple =>
t.size match
case 1 => Tuple1(f0(t(0)))
case 2 => (f0(t(0)), f0(t(1)))
case 3 => (f0(t(0)), f0(t(1)), f0(t(2)))
case 4 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)))
case 5 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)))
case 6 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)))
case 7 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)))
case 8 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)))
case 9 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)))
case 10 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)))
case 11 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)))
case 12 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)))
case 13 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)), f0(t(12)))
case 14 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)), f0(t(12)), f0(t(13)))
case 15 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)), f0(t(12)), f0(t(13)), f0(t(14)))
case 16 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)), f0(t(12)), f0(t(13)), f0(t(14)), f0(t(15)))
case 17 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)), f0(t(12)), f0(t(13)), f0(t(14)), f0(t(15)), f0(t(16)))
case 18 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)), f0(t(12)), f0(t(13)), f0(t(14)), f0(t(15)), f0(t(16)), f0(t(17)))
case 19 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)), f0(t(12)), f0(t(13)), f0(t(14)), f0(t(15)), f0(t(16)), f0(t(17)), f0(t(18)))
case 20 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)), f0(t(12)), f0(t(13)), f0(t(14)), f0(t(15)), f0(t(16)), f0(t(17)), f0(t(18)), f0(t(19)))
case 21 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)), f0(t(12)), f0(t(13)), f0(t(14)), f0(t(15)), f0(t(16)), f0(t(17)), f0(t(18)), f0(t(19)), f0(t(20)))
case 22 => (f0(t(0)), f0(t(1)), f0(t(2)), f0(t(3)), f0(t(4)), f0(t(5)), f0(t(6)), f0(t(7)), f0(t(8)), f0(t(9)), f0(t(10)), f0(t(11)), f0(t(12)), f0(t(13)), f0(t(14)), f0(t(15)), f0(t(16)), f0(t(17)), f0(t(18)), f0(t(19)), f0(t(20)), f0(t(21)))
case _ => scala.runtime.TupleXXL.fromIterator(tuple.iterator.map(f(_)))
// format: on
res.asInstanceOf[Tuple.Map[Tup, F2]]
end TupleMapExtension

View File

@ -10,6 +10,18 @@ package sbt.util
trait Applicative[F[_]] extends Apply[F]:
def pure[A1](x: () => A1): F[A1]
def mapN[A1 <: Tuple, A2](t: Tuple.Map[A1, F])(f: A1 => A2): F[A2] =
import sbt.internal.util.TupleMapExtension.*
val g = (l: List[Any]) => f(Tuple.fromArray(l.toArray).asInstanceOf[A1])
map(
t.iterator.foldLeft(pure(() => g))((g, head) =>
ap(map(head)(h => (f: List[Any] => A2) => (tail: List[Any]) => f(h :: tail)))(g)
)
)(_.apply(Nil))
def map2(t: (F[Int], F[String]))(f: (Int, String) => Boolean): F[Boolean] =
ap(ap(pure(() => f.curried))(t._1))(t._2)
override def map[A1, A2](fa: F[A1])(f: A1 => A2): F[A2] =
ap(pure(() => f))(fa)
end Applicative
@ -25,6 +37,8 @@ object Applicative:
override def pure[A1](x: () => A1): F1[F2[A1]] = F1.pure(() => F2.pure(x))
override def map[A1, A2](fa: F1[F2[A1]])(f: A1 => A2): F1[F2[A2]] =
F1.map(fa)(f2 => F2.map(f2)(f))
override def mapN[A1 <: Tuple, A2](t1: Tuple.Map[A1, F])(f: A1 => A2): F1[F2[A2]] =
F1.mapN(t1.asInstanceOf[Tuple.Map[Tuple.Map[A1, F2], F1]])(t2 => F2.mapN(t2)(f))
override def ap[A1, A2](f1f2f: F1[F2[A1 => A2]])(f1f2a: F1[F2[A1]]): F1[F2[A2]] =
F1.ap(F1.map(f1f2f) { (f2f: F2[A1 => A2]) => (f2a: F2[A1]) => F2.ap(f2f)(f2a) })(f1f2a)

View File

@ -9,9 +9,6 @@ package sbt.util
trait Apply[F[_]] extends Functor[F]:
def ap[A1, A2](ff: F[A1 => A2])(fa: F[A1]): F[A2]
def product[A1, A2](fa: F[A1], fb: F[A2]): F[(A1, A2)] =
ap(map(fa)(a => (b: A2) => (a, b)))(fb)
end Apply
object Apply:

View File

@ -57,7 +57,7 @@ case class SettingsUsage(val settingsExample: SettingsExample) {
// Define some settings
val mySettings: Seq[Setting[_]] = Seq(
setting(a3, value(3)),
setting(b4, map(a4)(_ * 3)),
setting(b4, a4(_ * 3)),
update(a5)(_ + 1)
)

View File

@ -1,12 +0,0 @@
package sbt.internal.util
import verify.BasicTestSuite
object TupleMapExtensionTest extends BasicTestSuite:
val tuple: Tuple.Map[(Int, String), Option] = ((Option(1), Option("foo")))
test("tuple.mapN") {
val f = (arg: (Int, String)) => arg._1.toString + "|" + arg._2
val actual = TupleMapExtension.mapN[(Int, String), Option](tuple)(f)
assert(actual == Option("1|foo"))
}