Last active
December 11, 2015 15:39
-
-
Save dragos/4622507 to your computer and use it in GitHub Desktop.
AttachmentsLeakTest
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Test that default arguments don't leak | |
*/ | |
class Foo( | |
x: Int = 100, | |
y: Int = 101, | |
z: Int = 102 | |
str1: String = "str1", | |
str2: String = "str1", | |
str3: String = "str1", | |
str4: String = "str1", | |
str5: String = "str1", | |
str6: String = "str1", | |
str7: String = "str1", | |
str8: String = "str1", | |
str9: String = "str1", | |
str10: String = "str1", | |
str11: String = "str1", | |
str12: String = "str1", | |
str13: String = "str1", | |
str14: String = "str1", | |
str15: String = "str1", | |
str16: String = "str1") | |
class Bar( | |
x: Int = 100, | |
y: Int = 101, | |
z: Int = 102 | |
str1: String = "str1", | |
str2: String = "str1", | |
str3: String = "str1", | |
str4: String = "str1", | |
str5: String = "str1", | |
str6: String = "str1", | |
str7: String = "str1", | |
str8: String = "str1", | |
str9: String = "str1", | |
str10: String = "str1", | |
str11: String = "str1", | |
str12: String = "str1", | |
str13: String = "str1", | |
str14: String = "str1", | |
str15: String = "str1", | |
str16: String = "str1") | |
class Baz( | |
x: Int = 100, | |
y: Int = 101, | |
z: Int = 102 | |
str1: String = "str1", | |
str2: String = "str1", | |
str3: String = "str1", | |
str4: String = "str1", | |
str5: String = "str1", | |
str6: String = "str1", | |
str7: String = "str1", | |
str8: String = "str1", | |
str9: String = "str1", | |
str10: String = "str1", | |
str11: String = "str1", | |
str12: String = "str1", | |
str13: String = "str1", | |
str14: String = "str1", | |
str15: String = "str1", | |
str16: String = "str1") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.PrintWriter | |
import java.io.FileOutputStream | |
import java.util.Calendar | |
import scala.tools.nsc.interactive.tests._ | |
import scala.tools.nsc.util._ | |
import scala.tools.nsc.io._ | |
import scala.tools.nsc.doc | |
/** memory leak test | |
*/ | |
object Test extends InteractiveTest { | |
final val mega = 1024 * 1024 | |
// override val settings: doc.Settings = docSettings | |
override def main(args: Array[String]): Unit = memoryConsumptionTest() | |
def batchSource(name: String) = | |
new BatchSourceFile(AbstractFile.getFile(name)) | |
def memoryConsumptionTest() { | |
val N = 50 | |
val filename = "usedmem-%tF.txt".format(Calendar.getInstance.getTime) | |
loadSources() | |
val usedMem = for (i <- 1 to N) yield { | |
val usedMem = withGC { | |
typeCheck() | |
} | |
usedMem / mega // report size in MB | |
} | |
dumpDataToFile(filename, usedMem) | |
println("Beginning at \t%d MB".format(usedMem.head)) | |
println("Ending at \t%d MB".format(usedMem.last)) | |
// drop the first two measurements, since the compiler needs some memory when initializing | |
val (a, b) = linearModel((3L to N).toSeq, usedMem.drop(2)) | |
println("LinearModel: constant: %.4f\tslope:%.4f".format(a, b)) | |
println(compiler.getClass.getDeclaredField("scala$tools$nsc$interactive$Global$$currentTopLevelSyms")) | |
val topLevelSymsField = compiler.getClass.getDeclaredField("scala$tools$nsc$interactive$Global$$currentTopLevelSyms") | |
topLevelSymsField.setAccessible(true) | |
val topLevelSyms = topLevelSymsField.get(compiler).asInstanceOf[collection.mutable.LinkedHashSet[compiler.Symbol]] | |
for (sym <- topLevelSyms) { | |
import scala.reflect.macros.Attachments | |
var att: Attachments = sym.attachments | |
if (!att.isInstanceOf[Position]) { | |
println(att.getClass) | |
val attOuter = att.getClass.getDeclaredField("$outer") | |
attOuter.setAccessible(true) | |
var len = 0 | |
while (!att.isInstanceOf[Position]) { | |
len += 1 | |
att = attOuter.get(att).asInstanceOf[Attachments] | |
} | |
println("Sym: %s \tlen: %d".format(sym, len)) | |
} | |
} | |
if (b > 1.0) | |
println("Rate of memory consumption is alarming! %.4f MB/run".format(b)) | |
else | |
println("No leaks detected.") | |
} | |
private def typeCheck() = { | |
askReload(sourceFiles) | |
askLoadedTyped(sourceFiles.head).get // block until it's here | |
} | |
private def dumpDataToFile(filename: String, usedMem: Seq[Long]) { | |
val outputFile = new PrintWriter(new FileOutputStream(filename)) | |
outputFile.println("\tusedMem") | |
for ((dataPoint, i) <- usedMem.zipWithIndex) { | |
outputFile.println("%d\t%d".format(i, dataPoint)) | |
} | |
outputFile.close() | |
} | |
/** Return the linear model of these values, (a, b). First value is the constant factor, | |
* second value is the slope, i.e. `y = a + bx` | |
* | |
* The linear model of a set of points is a straight line that minimizes the square distance | |
* between the each point and the line. | |
* | |
* See: http://en.wikipedia.org/wiki/Simple_linear_regression | |
*/ | |
def linearModel(xs: Seq[Long], ys: Seq[Long]): (Double, Double) = { | |
require(xs.length == ys.length) | |
def mean(v: Seq[Long]): Double = v.sum.toDouble / v.length | |
val meanXs = mean(xs) | |
val meanYs = mean(ys) | |
val beta = (mean((xs, ys).zipped.map(_ * _)) - meanXs * meanYs) / (mean(xs.map(x => x * x)) - meanXs * meanXs) | |
val alfa = meanYs - beta * meanXs | |
(alfa, beta) | |
} | |
/** Run the given closure and return the amount of used memory at the end of its execution. | |
* | |
* Runs the GC before and after the execution of `f'. | |
*/ | |
def withGC(f: => Unit): Long = { | |
val r = Runtime.getRuntime | |
System.gc() | |
f; | |
System.gc() | |
r.totalMemory() - r.freeMemory() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Beginning at 22 MB | |
Ending at 23 MB | |
LinearModel: constant: 21.6618 slope:0.0206 | |
private final scala.collection.mutable.LinkedHashSet scala.tools.nsc.interactive.Global.scala$tools$nsc$interactive$Global$$currentTopLevelSyms | |
class scala.reflect.macros.Attachments$NonemptyAttachments | |
Sym: object Foo len: 101 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment