Question

I am trapping into a memory leak. I wrote following sample, which increases memory usage continuously:

import 'dart:io';
import 'dart:async';
import 'dart:utf';

Future<Stream<List<int>>> readFile2Stream(String path){
  File f = new File(path);
  return f.exists().then((bool exists){
    if( !exists ){
      return new Stream<List<int>>.fromIterable([encodeUtf8("Could not find $path")]); 
    }else{
      return f.openRead();
    }
  });
}

void readFile(String path){
  readFile2Stream(path).then(
    (Stream<List<int>> data){
      data.listen((List<int> data){
        print(data);
      },
      onError: (dynamic error){
        print("Error: $error");
      },
      onDone: (){
        print("Done");
      });
    }
  );
}

void main() {
  Timer t = new Timer.periodic(new Duration(seconds:2),(Timer it){
    readFile("memleaktest.dart");
  });
}

May someone give me a hint for some reason? I don't have any clue :-(

Some minor additional question:

Is there a way to simplify this sample by getting rid of the Future encapsulation of the return types? I don't want to use File.existsSync(), instead I somekind want to prepend the Future handling to the Stream handling.

Was it helpful?

Solution

There is no memory leak. The garbage collector just doesn't run, which is a difference.

If you reduce your duration (e.g. 2 milliseconds), you'll see your memory usage rise until it reaches a certain point (500MB on my machine, but your mileage may vary). Apparently, at this point the garbage collector runs and frees the unused memory, reducing the memory usage to almost zero. Then it rises again etc. etc.

As for why the garbage collector doesn't run, I don't really know. There seems to be no specification or documentation how the GC works.

At least, your memory isn't lost and will be recycled, if needed. So - your code is fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top