dart-lang / sdk

The Dart SDK, including the VM, dart2js, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
9.94k stars 1.53k forks source link

Memory leak in Process.run and Process.start #50689

Open au-top opened 1 year ago

au-top commented 1 year ago

Windows Platform

run code

import 'dart:io';

void main() async {
  for (var var_name = 0; var_name < 999999; var_name) {
    await Process.run("dir", []);
  }
}

I found that the memory was not properly released

And the same problem occurred when I used Process.start

Memory will increase rapidly in the former case

In the latter case, it will increase slowly

void main() async {
  for (var var_name = 0; var_name < 999999; var_name) {
    final p = await Process.start("dir", []);
    await p.stdout.toList();
    await p.stderr.toList();
    p.kill();
  }
}

I don't think this is the case that GC is not called immediately, because I observed the same situation in another dart program used for long-term running. The memory continues to increase from 8M=>100M within an hour

I observed the DART development tool and found that the RSS memory on the chart continued to increase

dart verson

Dart SDK version: 2.17.5 (stable) (Tue Jun 21 11:05:10 2022 +0200) on "windows_x64"
au-top commented 1 year ago

it will increase slowly

void main(List<String> args) {
  // serviceMain("");
  Timer.periodic(Duration(seconds: 1), (timer) async {
    print("-");
    final p = Process.runSync("dir", []);
    print("+");
  });
}
brianquinlan commented 1 year ago

The rapid case is actually covered in the documentation:

Users must read all data coming on the stdout and stderr streams of processes started with Process.start. If the user does not read all data on the streams the underlying system resources will not be released since there is still pending data.

Is the memory increase that you observed (i.e. 8M => 100M in one hour) for the fast or the slow case?

au-top commented 1 year ago

The rapid case is actually covered in the documentation:

Users must read all data coming on the stdout and stderr streams of processes started with Process.start. If the user does not read all data on the streams the underlying system resources will not be released since there is still pending data.

Is the memory increase that you observed (i.e. 8M => 100M in one hour) for the fast or the slow case?

Its memory will increase slowly in a few hours from 8m=>100m

I use the following code

void main() async {
  for (var var_name = 0; var_name < 999999; var_name) {
  final p = await Process.start("typeperf",
        ["\\Processor Information(_Total)\\% Processor Utility", "-sc", "1"]);
    await p.stdout.toList();
    await p.stderr.toList();
    p.kill();
  }
}
au-top commented 1 year ago

The rapid case is actually covered in the documentation:

Users must read all data coming on the stdout and stderr streams of processes started with Process.start. If the user does not read all data on the streams the underlying system resources will not be released since there is still pending data.

Is the memory increase that you observed (i.e. 8M => 100M in one hour) for the fast or the slow case?

Its memory will increase slowly in a few hours from 8m=>100m

I use the following code

void main() async {
  for (var var_name = 0; var_name < 999999; var_name) {
  final p = await Process.start("typeperf",
        ["\\Processor Information(_Total)\\% Processor Utility", "-sc", "1"]);
    await p.stdout.toList();
    await p.stderr.toList();
    p.kill();
  }
}

I'm not sure whether this is related to the command, but when I execute await Process.start("typeperf", ["\\Processor Information(_Total)\\% Processor Utility", "-sc", "1"]); When the memory increases more obviously, it will increase by about 0.1m within 10 seconds