diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineIterator.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..961a59a4ceb4ad36ab677d014044624b4d2c4461
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineIterator.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.packages.analyzer;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.NoSuchElementException;
+import java.util.logging.Logger;
+
+public class FileLineIterator extends LineIterator {
+
+    private static final Logger LOGGER = Logger.getLogger(FileLineIterator.class.getName());
+
+    public static final int MAX_FILE_SIZE = 200 * 1024 * 1024;
+
+    private BufferedReader reader;
+    private String lookahead = null;
+
+    public FileLineIterator(Path p) {
+        try {
+            long size = Files.size(p);
+            if (size < MAX_FILE_SIZE) {
+                this.reader = Files.newBufferedReader(p);
+                nextLine();
+            } else {
+                this.reader = new BufferedReader(new InputStreamReader(new LimitSizeInputStreamReader(Files.newInputStream(p), MAX_FILE_SIZE)));
+                LOGGER.fine(String.format("Will read at most %d bytes from file %s.", MAX_FILE_SIZE, p));
+                this.reader = null;
+            }
+        } catch (IOException e) {
+            LOGGER.severe(String.format("I/O error occurred when reading %s: %s", p, e.getMessage()));
+        }
+    }
+
+    @Override
+    public void close() throws IOException {
+        if (reader != null) {
+            reader.close();
+        }
+    }
+
+    private String nextLine() {
+
+        String line = lookahead;
+        try {
+            lookahead = reader.readLine();
+        } catch (OutOfMemoryError e) {
+            // If a single line is just too large, abort.
+            lookahead = null;
+        } catch (IOException e) {
+            lookahead = null;
+        }
+        return line;
+    }
+
+    @Override
+    public boolean hasNext() {
+        return lookahead != null;
+    }
+
+    @Override
+    public String next() {
+        if (hasNext()) {
+            return nextLine();
+        }
+        throw new NoSuchElementException();
+    }
+
+    private static class LimitSizeInputStreamReader extends InputStream {
+
+        private final long limit;
+        private final InputStream source;
+        private long consumed;
+
+        protected LimitSizeInputStreamReader(InputStream source, long limit) {
+            this.source = source;
+            this.limit = limit;
+        }
+
+        @Override
+        public int read() throws IOException {
+            if (consumed < limit) {
+                consumed++;
+                return source.read();
+            }
+            return -1;
+        }
+
+        @Override
+        public int read(byte[] b) throws IOException {
+            return read(b, 0, b.length);
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            int read = super.read(b, off, (int) Math.min(limit - consumed, len));
+            consumed += read;
+            return read;
+        }
+
+        @Override
+        public int available() throws IOException {
+            return Math.min((int) (limit - consumed), super.available());
+        }
+
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineListReader.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineListReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..1dfe699153fcb01cebda5888f8355966a9adc860
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineListReader.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.packages.analyzer;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+public class FileLineListReader extends FileLineReader {
+
+    private final List<String> l;
+
+    public FileLineListReader(List<String> lines) {
+        this.l = lines;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return l.isEmpty();
+    }
+
+    @Override
+    public LineIterator iterator() {
+        return new LineIterator() {
+
+            private final Iterator<String> it = l.iterator();
+
+            @Override
+            public void close() throws IOException {
+                // nothing to do
+            }
+
+            @Override
+            public String next() {
+                return it.next();
+            }
+
+            @Override
+            public boolean hasNext() {
+                return it.hasNext();
+            }
+        };
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineReader.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8200cbcad560e6541b9d2cc91b49754605c5331
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineReader.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.packages.analyzer;
+
+public abstract class FileLineReader implements Iterable<String> {
+
+    public abstract boolean isEmpty();
+
+    @Override
+    public abstract LineIterator iterator();
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineStreamReader.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineStreamReader.java
new file mode 100644
index 0000000000000000000000000000000000000000..bdb7d03bd63f060e83598983353d37f6636a9dbb
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileLineStreamReader.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.packages.analyzer;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public class FileLineStreamReader extends FileLineReader {
+
+    private final Path p;
+
+    public FileLineStreamReader(Path p) {
+        this.p = p;
+
+    }
+
+    @Override
+    public boolean isEmpty() {
+        try {
+            return Files.size(p) == 0;
+        } catch (IOException e) {
+        }
+        return true;
+    }
+
+    @Override
+    public LineIterator iterator() {
+        return new FileLineIterator(p);
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileTreeWalker.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileTreeWalker.java
index 572124fc5f8eda8ae451c0a6127b145e1f4fef8e..a0626404dd0b8acf05080890de8b731d2f8d3338 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileTreeWalker.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileTreeWalker.java
@@ -157,10 +157,13 @@ public class FileTreeWalker {
         lfParser.addDetector(ConfigureErrorDetector.INSTANCE);
         lfParser.addTestResultDetector(DiffDetector.INSTANCE);
 
+        long startTime = System.currentTimeMillis();
         LogFile parseLogFile = lfParser.parseLogFile();
         Collection<Problem> problems = parseLogFile.collectProblems();
         pkgTestRun.setSuccess(parseLogFile.isSuccess());
         pkgTestRun.setLogFile(parseLogFile.getPath());
+        long endTime = System.currentTimeMillis();
+        LOGGER.info(String.format("Finished in %d seconds", (endTime - startTime) / 1000L));
 
         // log problems
         LOGGER.fine("Overall test result: " + (pkgTestRun.isSuccess() ? "OK" : "FAILED"));
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/LineIterator.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/LineIterator.java
new file mode 100644
index 0000000000000000000000000000000000000000..c84f3f133dd3acd000597d104fbcf2cf34087c1d
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/LineIterator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.packages.analyzer;
+
+import java.io.Closeable;
+import java.util.Iterator;
+
+public abstract class LineIterator implements Iterator<String>, Closeable {
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/PTAMain.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/PTAMain.java
index f60d22af3eff08353b486d7392c4732ffd09b77a..bb5f388c3c907951d757ec5839dc756606ddd349 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/PTAMain.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/PTAMain.java
@@ -204,6 +204,7 @@ public class PTAMain {
         sb.append("    --glob GLOB\t\tGlob-style directory filter for packages to consider (default: \"*\").").append(LF);
         sb.append("    --outDir PATH\tPath to directory for HTML output (default: \"html\").").append(LF);
         sb.append("    --console\t\tPrint output to console (by default, only errors are printed).").append(LF);
+        sb.append("    --verbose\t\tUse highest verbosity level.").append(LF);
         System.out.println(sb.toString());
         System.exit(1);
     }
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/ConfigureErrorDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/ConfigureErrorDetector.java
index 008b48d83c91a50d2d99207db82de7a64e9bf304..2b7621d8b7439bb80a36b7f59eec1a853a94f524 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/ConfigureErrorDetector.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/ConfigureErrorDetector.java
@@ -22,10 +22,12 @@
  */
 package com.oracle.truffle.r.test.packages.analyzer.detectors;
 
+import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
-import java.util.List;
 
+import com.oracle.truffle.r.test.packages.analyzer.LineIterator;
+import com.oracle.truffle.r.test.packages.analyzer.FileLineReader;
 import com.oracle.truffle.r.test.packages.analyzer.Location;
 import com.oracle.truffle.r.test.packages.analyzer.Problem;
 import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
@@ -45,17 +47,22 @@ public class ConfigureErrorDetector extends LineDetector {
     }
 
     @Override
-    public Collection<Problem> detect(RPackageTestRun pkgTestRun, Location startLocation, List<String> body) {
+    public Collection<Problem> detect(RPackageTestRun pkgTestRun, Location startLocation, FileLineReader body) {
         Collection<Problem> problems = new LinkedList<>();
         assert body.isEmpty() || startLocation != null;
         int lineNr = startLocation != null ? startLocation.lineNr : 0;
-        for (String line : body) {
-            if (line.startsWith(PREFIX)) {
-                String message = line.substring(PREFIX.length());
-                problems.add(new ConfigureErrorProblem(pkgTestRun, this, new Location(startLocation.file, lineNr), message));
-
+        try (LineIterator it = body.iterator()) {
+            while (it.hasNext()) {
+                String line = it.next();
+                if (line.startsWith(PREFIX)) {
+                    String message = line.substring(PREFIX.length());
+                    problems.add(new ConfigureErrorProblem(pkgTestRun, this, new Location(startLocation.file, lineNr), message));
+
+                }
+                ++lineNr;
             }
-            ++lineNr;
+        } catch (IOException e) {
+            // ignore
         }
         return problems;
     }
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/Detector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/Detector.java
index b71512b5e51415511a5add23996e8ed1c71343a0..f1e22de6a12f4e0b06fa4dd04b0af61fa424561a 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/Detector.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/Detector.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.test.packages.analyzer.detectors;
 
+import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
 
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/InstallationProblemDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/InstallationProblemDetector.java
index b63d31b1d5a274a6fcc4bee78685afc50b058885..8e4cb00b9fa85a76ac71111f1ed670636628619e 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/InstallationProblemDetector.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/InstallationProblemDetector.java
@@ -22,12 +22,14 @@
  */
 package com.oracle.truffle.r.test.packages.analyzer.detectors;
 
+import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import com.oracle.truffle.r.test.packages.analyzer.LineIterator;
+import com.oracle.truffle.r.test.packages.analyzer.FileLineReader;
 import com.oracle.truffle.r.test.packages.analyzer.Location;
 import com.oracle.truffle.r.test.packages.analyzer.Problem;
 import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
@@ -47,14 +49,19 @@ public class InstallationProblemDetector extends LineDetector {
     }
 
     @Override
-    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, List<String> body) {
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, FileLineReader body) {
         int lineNr = startLocation.lineNr;
-        for (String line : body) {
-            Matcher matcher = pattern.matcher(line);
-            if (matcher.matches()) {
-                return Collections.singletonList(new PackageInstallationProblem(pkg, this, new Location(startLocation.file, lineNr), line));
+        try (LineIterator it = body.iterator()) {
+            while (it.hasNext()) {
+                String line = it.next();
+                Matcher matcher = pattern.matcher(line);
+                if (matcher.matches()) {
+                    return Collections.singletonList(new PackageInstallationProblem(pkg, this, new Location(startLocation.file, lineNr), line));
+                }
+                ++lineNr;
             }
-            ++lineNr;
+        } catch (IOException e) {
+            // ignore
         }
         return Collections.emptyList();
     }
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/LineDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/LineDetector.java
index a035f5eb1be6b1c0e38f41c051f60c5423894fc0..ac8f8610414280000a641b54672a0664d460312f 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/LineDetector.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/LineDetector.java
@@ -22,9 +22,9 @@
  */
 package com.oracle.truffle.r.test.packages.analyzer.detectors;
 
-import java.util.List;
+import com.oracle.truffle.r.test.packages.analyzer.FileLineReader;
 
-public abstract class LineDetector extends Detector<List<String>> {
+public abstract class LineDetector extends Detector<FileLineReader> {
 
     protected LineDetector() {
         super(null);
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RErrorDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RErrorDetector.java
index 6f304037442499e61d0c18c2ed1673139cc08996..59a4525d2c205b472a588d79ab3d888677462f45 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RErrorDetector.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RErrorDetector.java
@@ -22,13 +22,14 @@
  */
 package com.oracle.truffle.r.test.packages.analyzer.detectors;
 
+import java.io.IOException;
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import com.oracle.truffle.r.test.packages.analyzer.LineIterator;
+import com.oracle.truffle.r.test.packages.analyzer.FileLineReader;
 import com.oracle.truffle.r.test.packages.analyzer.Location;
 import com.oracle.truffle.r.test.packages.analyzer.Problem;
 import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
@@ -48,28 +49,31 @@ public class RErrorDetector extends LineDetector {
     }
 
     @Override
-    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, List<String> body) {
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, FileLineReader body) {
 
         Collection<Problem> problems = new LinkedList<>();
         assert body.isEmpty() || startLocation != null;
         int lineOffset = startLocation != null ? startLocation.lineNr : 0;
 
         int i = -1;
-        Iterator<String> it = body.iterator();
-        while (it.hasNext()) {
-            String line = it.next();
-            ++i;
-            Matcher matcher = PATTERN.matcher(line);
-            if (matcher.matches()) {
-                String callString = matcher.group("CALLSTR");
-                String message = matcher.group("MSG");
-                if (message.trim().isEmpty() && it.hasNext()) {
-                    // message could be in the next line
-                    message = it.next();
-                    ++i;
+        try (LineIterator it = body.iterator()) {
+            while (it.hasNext()) {
+                String line = it.next();
+                ++i;
+                Matcher matcher = PATTERN.matcher(line);
+                if (matcher.matches()) {
+                    String callString = matcher.group("CALLSTR");
+                    String message = matcher.group("MSG");
+                    if (message.trim().isEmpty() && it.hasNext()) {
+                        // message could be in the next line
+                        message = it.next();
+                        ++i;
+                    }
+                    problems.add(new RErrorProblem(pkg, this, new Location(startLocation.file, i + lineOffset), callString, message));
                 }
-                problems.add(new RErrorProblem(pkg, this, new Location(startLocation.file, i + lineOffset), callString, message));
             }
+        } catch (IOException e) {
+            // ignore
         }
 
         return problems;
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RInternalErrorDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RInternalErrorDetector.java
index 56b5e78cedd8a748cc08ebf527e7f1632dedea1d..5f570e0344f312c95a30cd9031d2006e0b4cb5be 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RInternalErrorDetector.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RInternalErrorDetector.java
@@ -22,10 +22,12 @@
  */
 package com.oracle.truffle.r.test.packages.analyzer.detectors;
 
+import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
-import java.util.List;
 
+import com.oracle.truffle.r.test.packages.analyzer.LineIterator;
+import com.oracle.truffle.r.test.packages.analyzer.FileLineReader;
 import com.oracle.truffle.r.test.packages.analyzer.Location;
 import com.oracle.truffle.r.test.packages.analyzer.Problem;
 import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
@@ -41,22 +43,25 @@ public class RInternalErrorDetector extends LineDetector {
 
     @Override
     public String getName() {
-        // TODO Auto-generated method stub
         return null;
     }
 
     @Override
-    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, List<String> body) {
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, FileLineReader body) {
         Collection<Problem> problems = new LinkedList<>();
-        assert body.isEmpty() || startLocation != null;
         int lineNr = startLocation != null ? startLocation.lineNr : 0;
-        for (String line : body) {
-            int indexOf = line.indexOf(P);
-            if (indexOf != -1) {
-                String message = line.substring(indexOf + P.length());
-                problems.add(new RInternalErrorProblem(pkg, this, new Location(startLocation.file, lineNr), message));
+        try (LineIterator it = body.iterator()) {
+            while (it.hasNext()) {
+                String line = it.next();
+                int indexOf = line.indexOf(P);
+                if (indexOf != -1) {
+                    String message = line.substring(indexOf + P.length());
+                    problems.add(new RInternalErrorProblem(pkg, this, new Location(startLocation.file, lineNr), message));
+                }
+                ++lineNr;
             }
-            ++lineNr;
+        } catch (IOException e) {
+            // ignore
         }
         return problems;
     }
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SegfaultDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SegfaultDetector.java
index f23d7933a922ec8d504301440eaf8c36fcc8a9d7..be6844240ffdaf2adbdc26444659bab33bb73b5c 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SegfaultDetector.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SegfaultDetector.java
@@ -22,10 +22,12 @@
  */
 package com.oracle.truffle.r.test.packages.analyzer.detectors;
 
+import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.List;
 
+import com.oracle.truffle.r.test.packages.analyzer.LineIterator;
+import com.oracle.truffle.r.test.packages.analyzer.FileLineReader;
 import com.oracle.truffle.r.test.packages.analyzer.Location;
 import com.oracle.truffle.r.test.packages.analyzer.Problem;
 import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
@@ -44,28 +46,33 @@ public class SegfaultDetector extends LineDetector {
     }
 
     @Override
-    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, List<String> body) {
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, FileLineReader body) {
         StringBuilder segfaultMessage = new StringBuilder();
         boolean collect = false;
         assert body.isEmpty() || startLocation != null;
         int lineNr = startLocation != null ? startLocation.lineNr : 0;
         boolean takeNextLine = false;
-        for (String line : body) {
-            if (line.contains(SIGSEGV_START)) {
-                collect = true;
-            }
-            if (collect) {
-                if (takeNextLine) {
-                    segfaultMessage.append(line);
-                    takeNextLine = false;
+        try (LineIterator it = body.iterator()) {
+            while (it.hasNext()) {
+                String line = it.next();
+                if (line.contains(SIGSEGV_START)) {
+                    collect = true;
                 }
-                if (line.contains("Problematic frame")) {
-                    takeNextLine = true;
-                } else if (!line.contains("#")) {
-                    break;
+                if (collect) {
+                    if (takeNextLine) {
+                        segfaultMessage.append(line);
+                        takeNextLine = false;
+                    }
+                    if (line.contains("Problematic frame")) {
+                        takeNextLine = true;
+                    } else if (!line.contains("#")) {
+                        break;
+                    }
                 }
+                ++lineNr;
             }
-            ++lineNr;
+        } catch (IOException e) {
+            // ignore
         }
         if (collect) {
             return Collections.singleton(new SegfaultProblem(pkg, this, new Location(startLocation.file, lineNr), segfaultMessage.toString()));
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SymbolLookupErrorDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SymbolLookupErrorDetector.java
index bd218894e024d78ada9a40a34694e06cf24f472c..d69f84bd3b0ee83b91d3bb7cff7e18b4e6955888 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SymbolLookupErrorDetector.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SymbolLookupErrorDetector.java
@@ -22,12 +22,14 @@
  */
 package com.oracle.truffle.r.test.packages.analyzer.detectors;
 
+import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
-import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import com.oracle.truffle.r.test.packages.analyzer.LineIterator;
+import com.oracle.truffle.r.test.packages.analyzer.FileLineReader;
 import com.oracle.truffle.r.test.packages.analyzer.Location;
 import com.oracle.truffle.r.test.packages.analyzer.Problem;
 import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
@@ -47,17 +49,22 @@ public final class SymbolLookupErrorDetector extends LineDetector {
     }
 
     @Override
-    public Collection<Problem> detect(RPackageTestRun pkgTestRun, Location startLocation, List<String> body) {
+    public Collection<Problem> detect(RPackageTestRun pkgTestRun, Location startLocation, FileLineReader body) {
         Collection<Problem> problems = new LinkedList<>();
         int lineNr = startLocation != null ? startLocation.lineNr : 0;
-        for (String line : body) {
-            Matcher matcher = PATTERN.matcher(line);
-            if (matcher.matches()) {
-                String message = matcher.group("MSG");
-                problems.add(new SymbolLookupErrorProblem(pkgTestRun, this, new Location(startLocation.file, lineNr), message));
-
+        try (LineIterator it = body.iterator()) {
+            while (it.hasNext()) {
+                String line = it.next();
+                Matcher matcher = PATTERN.matcher(line);
+                if (matcher.matches()) {
+                    String message = matcher.group("MSG");
+                    problems.add(new SymbolLookupErrorProblem(pkgTestRun, this, new Location(startLocation.file, lineNr), message));
+
+                }
+                ++lineNr;
             }
-            ++lineNr;
+        } catch (IOException e) {
+            // ignore
         }
         return problems;
     }
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/UnsupportedSpecializationDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/UnsupportedSpecializationDetector.java
index 99f270940e23845ce25a4c3b260b9f278ca748d4..d5a3ea7b2ee5be3048ab1b4f6a3bdd3dddb47575 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/UnsupportedSpecializationDetector.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/UnsupportedSpecializationDetector.java
@@ -22,12 +22,14 @@
  */
 package com.oracle.truffle.r.test.packages.analyzer.detectors;
 
+import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
-import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import com.oracle.truffle.r.test.packages.analyzer.LineIterator;
+import com.oracle.truffle.r.test.packages.analyzer.FileLineReader;
 import com.oracle.truffle.r.test.packages.analyzer.Location;
 import com.oracle.truffle.r.test.packages.analyzer.Problem;
 import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
@@ -49,20 +51,25 @@ public class UnsupportedSpecializationDetector extends LineDetector {
     }
 
     @Override
-    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, List<String> body) {
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, FileLineReader body) {
         Collection<Problem> problems = new LinkedList<>();
         String message = null;
         assert body.isEmpty() || startLocation != null;
         int lineNr = startLocation != null ? startLocation.lineNr : 0;
         int problemStartLine = lineNr;
-        for (String line : body) {
-            Matcher matcher = PATTERN.matcher(line);
-            if (matcher.find()) {
-                message = matcher.group("MSG");
-                problemStartLine = lineNr;
-                problems.add(new UnsupportedSpecializationProblem(pkg, this, new Location(startLocation.file, problemStartLine), message));
+        try (LineIterator it = body.iterator()) {
+            while (it.hasNext()) {
+                String line = it.next();
+                Matcher matcher = PATTERN.matcher(line);
+                if (matcher.find()) {
+                    message = matcher.group("MSG");
+                    problemStartLine = lineNr;
+                    problems.add(new UnsupportedSpecializationProblem(pkg, this, new Location(startLocation.file, problemStartLine), message));
+                }
+                ++lineNr;
             }
-            ++lineNr;
+        } catch (IOException e) {
+            // ignore
         }
         return problems;
     }
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/LogFileParser.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/LogFileParser.java
index 57ddf81a2a6854017b216ab563a46937a7fa2df2..e50d913587ac7212ab39ecae67a7d43fafb62b8b 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/LogFileParser.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/LogFileParser.java
@@ -27,7 +27,6 @@ import java.io.IOException;
 import java.nio.file.FileVisitResult;
 import java.nio.file.FileVisitor;
 import java.nio.file.Files;
-import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.attribute.BasicFileAttributes;
@@ -46,6 +45,9 @@ import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import com.oracle.truffle.r.test.packages.analyzer.FileLineListReader;
+import com.oracle.truffle.r.test.packages.analyzer.FileLineReader;
+import com.oracle.truffle.r.test.packages.analyzer.FileLineStreamReader;
 import com.oracle.truffle.r.test.packages.analyzer.Location;
 import com.oracle.truffle.r.test.packages.analyzer.Problem;
 import com.oracle.truffle.r.test.packages.analyzer.detectors.Detector;
@@ -58,6 +60,8 @@ public class LogFileParser {
 
     private static final Logger LOGGER = Logger.getLogger(LogFileParser.class.getName());
 
+    private static final long MAX_FILE_SIZE = 200 * 1024 * 1024;
+
     private RPackageTestRun pkg;
     private BufferedReader reader;
     private Line curLine;
@@ -93,28 +97,33 @@ public class LogFileParser {
     }
 
     public LogFile parseLogFile() throws IOException {
-        try (BufferedReader r = Files.newBufferedReader(logFile.path)) {
-            this.reader = r;
-            consumeLine();
+        long size = Files.size(logFile.path);
+        if (size <= MAX_FILE_SIZE) {
+            try (BufferedReader r = Files.newBufferedReader(logFile.path)) {
+                this.reader = r;
+                consumeLine();
 
-            Section installTest0 = parseInstallTest();
-            logFile.addSection(installTest0);
-            if (!installTest0.isSuccess()) {
-                return logFile;
-            }
-            Section installTest1 = parseInstallTest();
-            logFile.addSection(installTest1);
-            if (installTest1.isSuccess()) {
-                logFile.addSection(parseCheckResults());
+                Section installTest0 = parseInstallTest();
+                logFile.addSection(installTest0);
+                if (!installTest0.isSuccess()) {
+                    return logFile;
+                }
+                Section installTest1 = parseInstallTest();
+                logFile.addSection(installTest1);
+                if (installTest1.isSuccess()) {
+                    logFile.addSection(parseCheckResults());
+                }
+                TestResult overallResult = parseOverallStatus();
+                logFile.setSuccess(overallResult.toBoolean());
+
+                // In the end, a recursive diff is executed which might produce error messages.
+                collectBody();
+                expectEOF();
+            } finally {
+                this.reader = null;
             }
-            TestResult overallResult = parseOverallStatus();
-            logFile.setSuccess(overallResult.toBoolean());
-
-            // In the end, a recursive diff is executed which might produce error messages.
-            collectBody();
-            expectEOF();
-        } finally {
-            this.reader = null;
+        } else {
+            LOGGER.severe(String.format("Cannot analyze %s, file is too large (%d bytes, max=%d bytes)", logFile.path, size, MAX_FILE_SIZE));
         }
         return logFile;
     }
@@ -176,18 +185,15 @@ public class LogFileParser {
 
                 if (Files.isReadable(outputFile)) {
                     ignoreFiles.add(outputFile);
-                    checkResults.problems.addAll(applyDetectors(Token.OUTPUT_MISMATCH_FASTR, outputFile, 0, Files.readAllLines(outputFile)));
+                    checkResults.problems.addAll(applyDetectors(Token.OUTPUT_MISMATCH_FASTR, outputFile, 0, new FileLineStreamReader(outputFile)));
                 } else {
                     // try to find the file anywhere in the test run directory (there were some
                     // cases)
                     Optional<Path> findFirst = null;
-                    try {
-                        findFirst = Files.find(logFile.path.getParent(), 3, (path, attr) -> path.getFileName().equals(outputFile.getFileName())).findFirst();
-                        if (findFirst.isPresent()) {
-                            ignoreFiles.add(findFirst.get());
-                            checkResults.problems.addAll(applyDetectors(Token.OUTPUT_MISMATCH_FASTR, findFirst.get(), 0, Files.readAllLines(findFirst.get())));
-                        }
-                    } catch (NoSuchFileException e) {
+                    findFirst = Files.find(logFile.path.getParent(), 3, (path, attr) -> path.getFileName().equals(outputFile.getFileName())).findFirst();
+                    if (findFirst.isPresent()) {
+                        ignoreFiles.add(findFirst.get());
+                        checkResults.problems.addAll(applyDetectors(Token.OUTPUT_MISMATCH_FASTR, findFirst.get(), 0, new FileLineStreamReader(findFirst.get())));
                     }
                     if (findFirst == null || !findFirst.isPresent()) {
                         LOGGER.warning("Cannot read output file " + outputFile);
@@ -198,8 +204,10 @@ public class LogFileParser {
                 }
 
                 checkResults.setSuccess(false);
-            } else {
+            } else if (laMatches(Token.END_CHECKING)) {
                 break;
+            } else {
+                consumeLine();
             }
         }
 
@@ -305,10 +313,10 @@ public class LogFileParser {
                     testing.problems.addAll(applyTestResultDetectors(diffResult));
                     diffResult.stream().forEach(chunk -> {
                         if (!chunk.getLeft().isEmpty()) {
-                            testing.problems.addAll(applyDetectors(Token.RUNNING_SPECIFIC_TESTS, chunk.getLeftFile(), chunk.getLeftStartLine(), chunk.getLeft()));
+                            testing.problems.addAll(applyDetectors(Token.RUNNING_SPECIFIC_TESTS, chunk.getLeftFile(), chunk.getLeftStartLine(), new FileLineListReader(chunk.getLeft())));
                         }
                         if (!chunk.getRight().isEmpty()) {
-                            testing.problems.addAll(applyDetectors(Token.RUNNING_SPECIFIC_TESTS, chunk.getRightFile(), chunk.getRightStartLine(), chunk.getRight()));
+                            testing.problems.addAll(applyDetectors(Token.RUNNING_SPECIFIC_TESTS, chunk.getRightFile(), chunk.getRightStartLine(), new FileLineListReader(chunk.getRight())));
                         }
                     });
 
@@ -330,7 +338,6 @@ public class LogFileParser {
             if (laMatches("Running ")) {
                 consumeLine();
             }
-            // TODO anything more to parse ?
             testing.problems.addAll(applyDetectors(Token.RUNNING_VIGNETTES, logFile.path, collectBody(Token.END_TESTING)));
         }
 
@@ -423,7 +430,7 @@ public class LogFileParser {
             @Override
             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                 if (endsWith(file, ".Rout", ".fail") && includeCheck.test(file)) {
-                    outputCheck.problems.addAll(applyDetectors(Token.BEGIN_CHECKING, file, 0, Files.readAllLines(file)));
+                    outputCheck.problems.addAll(applyDetectors(Token.BEGIN_CHECKING, file, 0, new FileLineStreamReader(file)));
                 }
                 return FileVisitResult.CONTINUE;
             }
@@ -454,12 +461,12 @@ public class LogFileParser {
         if (!body.isEmpty()) {
             Line firstLine = body.get(0);
             List<String> strBody = body.stream().map(l -> l.text).collect(Collectors.toList());
-            return applyDetectors(start, file, firstLine.lineNr, strBody);
+            return applyDetectors(start, file, firstLine.lineNr, new FileLineListReader(strBody));
         }
         return new LinkedList<>();
     }
 
-    private Collection<Problem> applyDetectors(Token start, Path file, int startLineNr, List<String> body) {
+    private Collection<Problem> applyDetectors(Token start, Path file, int startLineNr, FileLineReader body) {
         assert Files.isRegularFile(file);
         Location startLocation = null;
         if (!body.isEmpty()) {
@@ -487,7 +494,9 @@ public class LogFileParser {
     }
 
     private Collection<Problem> applyTestResultDetectors(List<DiffChunk> diffChunk) {
-        return testResultDetectors.stream().map(detector -> detector.detect(pkg, null, diffChunk)).flatMap(l -> l.stream()).collect(Collectors.toList());
+        return testResultDetectors.stream().map(detector -> {
+            return detector.detect(pkg, null, diffChunk);
+        }).flatMap(l -> l.stream()).collect(Collectors.toList());
     }
 
     /**
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/test/RErrorDetectorTest.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/test/RErrorDetectorTest.java
index 9e295bb54b43f612cd0829ff2e1cc3c27be58587..e404e94230451d3c976ce9abb22751a0e0c3ae75 100644
--- a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/test/RErrorDetectorTest.java
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/test/RErrorDetectorTest.java
@@ -26,12 +26,12 @@ import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.List;
 import java.util.Optional;
 
 import org.junit.Assert;
 import org.junit.Test;
 
+import com.oracle.truffle.r.test.packages.analyzer.FileLineListReader;
 import com.oracle.truffle.r.test.packages.analyzer.Location;
 import com.oracle.truffle.r.test.packages.analyzer.Problem;
 import com.oracle.truffle.r.test.packages.analyzer.detectors.RErrorDetector;
@@ -51,8 +51,8 @@ public class RErrorDetectorTest {
 
     @Test
     public void testMultiLine() {
-        List<String> lines = Arrays.asList(new String[]{"Error in check(options) : ",
-                        "ERROR: installing Rd objects failed for package ‘RUnit’"});
+        FileLineListReader lines = new FileLineListReader(Arrays.asList(new String[]{"Error in check(options) : ",
+                        "ERROR: installing Rd objects failed for package ‘RUnit’"}));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(1, detect.size());
@@ -65,7 +65,7 @@ public class RErrorDetectorTest {
 
     @Test
     public void testSingleLine0() {
-        List<String> lines = Collections.singletonList("Error in check(options) : invalid value for 'label' ");
+        FileLineListReader lines = new FileLineListReader(Collections.singletonList("Error in check(options) : invalid value for 'label' "));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(1, detect.size());
@@ -78,7 +78,7 @@ public class RErrorDetectorTest {
 
     @Test
     public void testSingleLine1() {
-        List<String> lines = Collections.singletonList("Error in check : invalid value for 'label' ");
+        FileLineListReader lines = new FileLineListReader(Collections.singletonList("Error in check : invalid value for 'label' "));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(1, detect.size());
@@ -91,7 +91,7 @@ public class RErrorDetectorTest {
 
     @Test
     public void testSingleLineMultipleColon() {
-        List<String> lines = Collections.singletonList("Error in check(options) : invalid value for 'label' : ");
+        FileLineListReader lines = new FileLineListReader(Collections.singletonList("Error in check(options) : invalid value for 'label' : "));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(1, detect.size());
@@ -104,7 +104,7 @@ public class RErrorDetectorTest {
 
     @Test
     public void testSingleLineWithoutCallstring0() {
-        List<String> lines = Collections.singletonList("Error: invalid value for 'label' ");
+        FileLineListReader lines = new FileLineListReader(Collections.singletonList("Error: invalid value for 'label' "));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(1, detect.size());
@@ -117,7 +117,7 @@ public class RErrorDetectorTest {
 
     @Test
     public void testSingleLineWithoutCallstring1() {
-        List<String> lines = Collections.singletonList("Error: invalid value for 'label' : ");
+        FileLineListReader lines = new FileLineListReader(Collections.singletonList("Error: invalid value for 'label' : "));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(1, detect.size());
@@ -129,7 +129,7 @@ public class RErrorDetectorTest {
 
     @Test
     public void testRInternalError0() {
-        List<String> lines = Collections.singletonList("RInternalError: invalid value for 'label'");
+        FileLineListReader lines = new FileLineListReader(Collections.singletonList("RInternalError: invalid value for 'label'"));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(0, detect.size());
@@ -137,7 +137,7 @@ public class RErrorDetectorTest {
 
     @Test
     public void testRInternalError1() {
-        List<String> lines = Collections.singletonList("> RInternalError: invalid value for 'label'");
+        FileLineListReader lines = new FileLineListReader(Collections.singletonList("> RInternalError: invalid value for 'label'"));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(0, detect.size());
@@ -145,7 +145,7 @@ public class RErrorDetectorTest {
 
     @Test
     public void testRInternalError2() {
-        List<String> lines = Collections.singletonList("  RInternalError: invalid value for 'label'");
+        FileLineListReader lines = new FileLineListReader(Collections.singletonList("  RInternalError: invalid value for 'label'"));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(0, detect.size());
@@ -153,7 +153,7 @@ public class RErrorDetectorTest {
 
     @Test
     public void testWithLinePrefix() {
-        List<String> lines = Collections.singletonList("> Error: invalid value for 'label'");
+        FileLineListReader lines = new FileLineListReader(Collections.singletonList("> Error: invalid value for 'label'"));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(1, detect.size());
@@ -165,8 +165,8 @@ public class RErrorDetectorTest {
 
     @Test
     public void testCallstringWithNamesAndValues0() {
-        List<String> lines = Arrays.asList(new String[]{"Error in grep(pattern, all.names, value = TRUE) : ",
-                        "  invalid regular expression '*': Dangling meta character '*' near index 0"});
+        FileLineListReader lines = new FileLineListReader(Arrays.asList(new String[]{"Error in grep(pattern, all.names, value = TRUE) : ",
+                        "  invalid regular expression '*': Dangling meta character '*' near index 0"}));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(1, detect.size());
@@ -178,8 +178,8 @@ public class RErrorDetectorTest {
 
     @Test
     public void testCallstringWithNamesAndValues1() {
-        List<String> lines = Arrays.asList(new String[]{"Error in grep(pattern, all.names, value = \":\") : ",
-                        "  invalid regular expression '*': Dangling meta character '*' near index 0"});
+        FileLineListReader lines = new FileLineListReader(Arrays.asList(new String[]{"Error in grep(pattern, all.names, value = \":\") : ",
+                        "  invalid regular expression '*': Dangling meta character '*' near index 0"}));
 
         Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
         Assert.assertEquals(1, detect.size());
diff --git a/com.oracle.truffle.r.test.packages/r/install.cache.R b/com.oracle.truffle.r.test.packages/r/install.cache.R
index 44acb6c78892cef96158f0699daf6323e3a9c19d..cab215a510a3ca5a05007bad5c47e5470d063ed4 100644
--- a/com.oracle.truffle.r.test.packages/r/install.cache.R
+++ b/com.oracle.truffle.r.test.packages/r/install.cache.R
@@ -88,7 +88,7 @@ pkg.cache.insert <- function(pkg.cache.env, pkgname, lib) {
         # to produce a TAR with relative paths, we need to change the working dir
         prev.wd <- getwd()
         setwd(lib)
-        if(zip(toPath, pkgname) != 0L) {
+        if(zip(toPath, pkgname, flags="-r9Xq") != 0L) {
             log.message("could not compress package dir ", fromPath , " and store it to ", toPath, level=1)
             return (FALSE)
         }
diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py
index abbe70e0d115b1104964fb4ac997ea5454967ceb..5baad996e5eea009e58eab2586eaf81a61b32957 100644
--- a/mx.fastr/mx_fastr_pkgs.py
+++ b/mx.fastr/mx_fastr_pkgs.py
@@ -495,6 +495,7 @@ def _set_test_status(fastr_test_info):
         with open(join(_pkg_testdir('fastr', pkg), 'testfile_status'), 'w') as f:
             f.write('# <file path> <tests passed> <tests skipped> <tests failed>\n')
             for fastr_relpath, fastr_testfile_status in fastr_outputs.iteritems():
+                print "generating testfile_status for {0}".format(fastr_relpath)
                 if fastr_testfile_status.status == "FAILED":
                     relpath = fastr_relpath + ".fail"
                 else:
@@ -504,6 +505,8 @@ def _set_test_status(fastr_test_info):
                 if os.path.exists(test_output_file):
                     ok, skipped, failed = fastr_testfile_status.report
                     f.write("{0} {1} {2} {3}\n".format(relpath, ok, skipped, failed))
+                else:
+                    print "File {0} does not exist".format(test_output_file)
 
         print 'END checking ' + pkg
 
@@ -604,7 +607,8 @@ def _replace_engine_references(output):
             # ignore differences which come from test directory paths
             output[idx] = val.replace('fastr', '<engine>').replace('gnur', '<engine>')
 
-def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename):
+
+def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename, verbose=False):
     '''
     Compares the test output of GnuR and FastR by ignoring implementation-specific differences like header, error,
     and warning messages.
@@ -636,14 +640,16 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename):
 
     gnur_cur_statement_start = -1
     fastr_cur_statement_start = -1
-    while gnur_i < gnur_end:
-        gnur_line = gnur_content[gnur_i]
-        if fastr_i >= fastr_len:
-            overall_result = 1
+    while True:
+        gnur_line, gnur_i = _get_next_line(gnur_prompt, gnur_content, gnur_end, gnur_i)
+        fastr_line, fastr_i = _get_next_line(fastr_prompt, fastr_content, fastr_len, fastr_i)
+
+        if gnur_line is None or fastr_line is None:
+            # fail if FastR's output is shorter than GnuR's
+            if gnur_line is not None and fastr_line is None:
+                overall_result = 1
             break
 
-        fastr_line = fastr_content[fastr_i]
-
         # check if the current line starts a statement
         if _is_statement_begin(gnur_prompt, gnur_line) and gnur_cur_statement_start != gnur_i:
             gnur_cur_statement_start = gnur_i
@@ -681,8 +687,6 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename):
                 to_match = 'Error' if 'Error' in gnur_line else 'Warning'
                 if to_match not in fastr_line:
                     result = 1
-                    # XXX do not break
-                    # break
                 else:
                     # accept differences in the error/warning messages but we need to synchronize
                     sync = True
@@ -691,8 +695,6 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename):
                 # genuine difference (modulo whitespace)
                 if not _ignore_whitespace(gnur_line, fastr_line):
                     result = 1
-                    # XXX do not break, but we might need to synchronize indices
-                    # break
 
 
         # report a mismatch or success
@@ -704,6 +706,13 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename):
             if fastr_cur_statement_start in statements_passed:
                 statements_passed.remove(fastr_cur_statement_start)
             statements_failed.add(fastr_cur_statement_start)
+
+            # for compatibility: print the first difference
+            if verbose:
+                print gnur_filename + ':%d' % (gnur_cur_statement_start+1) + ' vs. ' + fastr_filename + ':%d' % (fastr_cur_statement_start+1)
+                print gnur_line.strip()
+                print "vs."
+                print fastr_line.strip()
         else:
             assert result == 0
             if fastr_cur_statement_start not in statements_failed:
@@ -736,14 +745,19 @@ def _fuzzy_compare(gnur_content, fastr_content, gnur_filename, fastr_filename):
             gnur_i = gnur_i + 1
             fastr_i = fastr_i + 1
 
-    if overall_result == 1:
-        print gnur_filename + ':%d' % gnur_i + ' vs. ' + fastr_filename + ':%d' % fastr_i
-        print gnur_line.strip()
-        print "vs."
-        print fastr_line.strip()
     return overall_result, len(statements_passed), len(statements_failed)
 
 
+def _get_next_line(prompt, content, content_len, line_idx):
+    i = line_idx
+    while i < content_len:
+        line = content[i]
+        if line.replace(prompt, "", 1).strip() is not "":
+            return line, i
+        i = i + 1
+    return None, i
+
+
 def _ignore_whitespace(gnur_line, fastr_line):
     return gnur_line.translate(None, ' \t') == fastr_line.translate(None, ' \t')