mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 20:11:19 +00:00
[io] Improve scheduling of IO worker threads
The allocation of the at most 32 IO worker threads to IO requests includes an inefficient check that a thread is free, when a request completes. A server application was taking 5% of its time running this check, which is a .contains call on HashMap.values. This CL replaces it with a use count on each IO thread, which is checked against 0. Bug: https://github.com/dart-lang/sdk/issues/50907 Change-Id: I6d13f9c62d36c34f165b2b4e32a48caeb6f9a77b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/278503 Reviewed-by: Zach Anderson <zra@google.com> Commit-Queue: William Hesse <whesse@google.com>
This commit is contained in:
parent
112e1213dc
commit
e8283b0839
|
@ -8,35 +8,34 @@ class _IOServicePorts {
|
|||
// We limit the number of IO Service ports per isolate so that we don't
|
||||
// spawn too many threads all at once, which can crash the VM on Windows.
|
||||
static const int maxPorts = 32;
|
||||
List<SendPort> _ports = <SendPort>[];
|
||||
List<SendPort> _freePorts = <SendPort>[];
|
||||
Map<int, SendPort> _usedPorts = new HashMap<int, SendPort>();
|
||||
final List<SendPort> _ports = [];
|
||||
final List<int> _useCounts = [];
|
||||
final List<int> _freePorts = [];
|
||||
final Map<int, int> _usedPorts = HashMap<int, int>();
|
||||
|
||||
_IOServicePorts();
|
||||
|
||||
SendPort _getPort(int forRequestId) {
|
||||
if (_freePorts.isEmpty && _usedPorts.length < maxPorts) {
|
||||
assert(!_usedPorts.containsKey(forRequestId));
|
||||
if (_freePorts.isEmpty && _ports.length < maxPorts) {
|
||||
final SendPort port = _newServicePort();
|
||||
_ports.add(port);
|
||||
_freePorts.add(port);
|
||||
_useCounts.add(0);
|
||||
_freePorts.add(_ports.length - 1);
|
||||
}
|
||||
if (!_freePorts.isEmpty) {
|
||||
final SendPort port = _freePorts.removeLast();
|
||||
assert(!_usedPorts.containsKey(forRequestId));
|
||||
_usedPorts[forRequestId] = port;
|
||||
return port;
|
||||
}
|
||||
// We have already allocated the max number of ports. Re-use an
|
||||
// existing one.
|
||||
final SendPort port = _ports[forRequestId % maxPorts];
|
||||
_usedPorts[forRequestId] = port;
|
||||
return port;
|
||||
// Use a free port if one exists.
|
||||
final index = _freePorts.isNotEmpty
|
||||
? _freePorts.removeLast()
|
||||
: forRequestId % maxPorts;
|
||||
_usedPorts[forRequestId] = index;
|
||||
_useCounts[index]++;
|
||||
return _ports[index];
|
||||
}
|
||||
|
||||
void _returnPort(int forRequestId) {
|
||||
final SendPort port = _usedPorts.remove(forRequestId)!;
|
||||
if (!_usedPorts.values.contains(port)) {
|
||||
_freePorts.add(port);
|
||||
final index = _usedPorts.remove(forRequestId)!;
|
||||
if (--_useCounts[index] == 0) {
|
||||
_freePorts.add(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue