Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
831ee22b
Unverified
Commit
831ee22b
authored
Jan 20, 2021
by
Romain Rastel
Committed by
GitHub
Jan 20, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add removeListenerWhileNotifying benchmark for ChangeNotifier (#71986)
parent
dcc4fdd5
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
157 additions
and
88 deletions
+157
-88
change_notifier_bench.dart
...microbenchmarks/lib/foundation/change_notifier_bench.dart
+157
-88
No files found.
dev/benchmarks/microbenchmarks/lib/foundation/change_notifier_bench.dart
View file @
831ee22b
...
...
@@ -6,108 +6,177 @@ import 'package:flutter/foundation.dart';
import
'../common.dart'
;
const
int
_kNumIterations
=
1000
;
const
double
_scale
=
1000.0
/
_kNumIterations
;
const
int
_kNumIterations
=
65536
;
const
int
_kNumWarmUp
=
100
;
const
int
_kScale
=
1000
;
void
main
(
)
{
assert
(
false
,
"Don't run benchmarks in checked mode! Use 'flutter run --release'."
);
void
listener
()
{}
void
listener2
()
{}
void
listener3
()
{}
void
listener4
()
{}
void
listener5
()
{}
// Warm up lap
for
(
int
i
=
0
;
i
<
_kNumWarmUp
;
i
+=
1
)
{
_Notifier
()
..
addListener
(
listener
)
..
addListener
(
listener2
)
..
addListener
(
listener3
)
..
addListener
(
listener4
)
..
addListener
(
listener5
)
..
notify
()
..
removeListener
(
listener
)
..
removeListener
(
listener2
)
..
removeListener
(
listener3
)
..
removeListener
(
listener4
)
..
removeListener
(
listener5
);
}
// In the following benchmarks, we won't remove the listeners when we don't
// want to measure removeListener because we know that everything will be
// GC'ed in the end.
// Not removing listeners would cause memory leaks in a real application.
final
Stopwatch
addListenerWatch
=
Stopwatch
();
final
Stopwatch
removeListenerWatch
=
Stopwatch
();
final
Stopwatch
notifyListenersWatch
=
Stopwatch
();
final
BenchmarkResultPrinter
printer
=
BenchmarkResultPrinter
();
for
(
int
listenersCount
=
0
;
listenersCount
<=
5
;
listenersCount
++)
{
void
runAddListenerBenchmark
(
int
iteration
,
{
bool
addResult
=
true
})
{
const
String
name
=
'addListener'
;
for
(
int
listenerCount
=
1
;
listenerCount
<=
5
;
listenerCount
+=
1
)
{
final
List
<
_Notifier
>
notifiers
=
List
<
_Notifier
>.
generate
(
iteration
,
(
_
)
=>
_Notifier
(),
growable:
false
,
);
final
Stopwatch
watch
=
Stopwatch
();
watch
.
start
();
for
(
int
i
=
0
;
i
<
iteration
;
i
+=
1
)
{
for
(
int
l
=
0
;
l
<
listenerCount
;
l
+=
1
)
{
notifiers
[
i
].
addListener
(()
{});
}
}
watch
.
stop
();
final
int
elapsed
=
watch
.
elapsedMicroseconds
;
final
double
averagePerIteration
=
elapsed
/
iteration
;
if
(
addResult
)
printer
.
addResult
(
description:
'
$name
(
$listenerCount
listeners)'
,
value:
averagePerIteration
*
_kScale
,
unit:
'ns per iteration'
,
name:
'
$name${listenerCount}
_iteration'
,
);
}
}
void
runNotifyListenerBenchmark
(
int
iteration
,
{
bool
addResult
=
true
})
{
const
String
name
=
'notifyListener'
;
for
(
int
j
=
0
;
j
<
_kNumIterations
;
j
+=
1
)
{
for
(
int
listenerCount
=
0
;
listenerCount
<=
5
;
listenerCount
+=
1
)
{
final
_Notifier
notifier
=
_Notifier
();
addListenerWatch
.
start
();
notifier
.
addListener
(
listener
);
if
(
listenersCount
>
1
)
notifier
.
addListener
(
listener2
);
if
(
listenersCount
>
2
)
notifier
.
addListener
(
listener3
);
if
(
listenersCount
>
3
)
notifier
.
addListener
(
listener4
);
if
(
listenersCount
>
4
)
notifier
.
addListener
(
listener5
);
addListenerWatch
.
stop
();
notifyListenersWatch
.
start
();
notifier
.
notify
();
notifyListenersWatch
.
stop
();
removeListenerWatch
.
start
();
// Remove listeners in reverse order to evaluate the worse-case scenario:
// the listener removed is the last listener
if
(
listenersCount
>
4
)
notifier
.
removeListener
(
listener5
);
if
(
listenersCount
>
3
)
notifier
.
removeListener
(
listener4
);
if
(
listenersCount
>
2
)
notifier
.
removeListener
(
listener3
);
if
(
listenersCount
>
1
)
notifier
.
removeListener
(
listener2
);
notifier
.
removeListener
(
listener
);
removeListenerWatch
.
stop
();
for
(
int
i
=
1
;
i
<=
listenerCount
;
i
+=
1
)
{
notifier
.
addListener
(()
{});
}
final
Stopwatch
watch
=
Stopwatch
();
watch
.
start
();
for
(
int
i
=
0
;
i
<
iteration
;
i
+=
1
)
{
notifier
.
notify
();
}
watch
.
stop
();
final
int
elapsed
=
watch
.
elapsedMicroseconds
;
final
double
averagePerIteration
=
elapsed
/
iteration
;
if
(
addResult
)
printer
.
addResult
(
description:
'
$name
(
$listenerCount
listeners)'
,
value:
averagePerIteration
*
_kScale
,
unit:
'ns per iteration'
,
name:
'
$name${listenerCount}
_iteration'
,
);
}
}
final
int
notifyListener
=
notifyListenersWatch
.
elapsedMicroseconds
;
notifyListenersWatch
.
reset
();
final
int
addListenerElapsed
=
addListenerWatch
.
elapsedMicroseconds
;
addListenerWatch
.
reset
();
final
int
removeListenerElapsed
=
removeListenerWatch
.
elapsedMicroseconds
;
removeListenerWatch
.
reset
();
printer
.
addResult
(
description:
'addListener (
$listenersCount
listeners)'
,
value:
addListenerElapsed
*
_scale
,
unit:
'ns per iteration'
,
name:
'addListener
${listenersCount}
_iteration'
,
);
printer
.
addResult
(
description:
'removeListener (
$listenersCount
listeners)'
,
value:
removeListenerElapsed
*
_scale
,
unit:
'ns per iteration'
,
name:
'removeListener
${listenersCount}
_iteration'
,
);
printer
.
addResult
(
description:
'notifyListener (
$listenersCount
listeners)'
,
value:
notifyListener
*
_scale
,
unit:
'ns per iteration'
,
name:
'notifyListener
${listenersCount}
_iteration'
,
);
void
runRemoveListenerBenchmark
(
int
iteration
,
{
bool
addResult
=
true
})
{
const
String
name
=
'removeListener'
;
final
List
<
VoidCallback
>
listeners
=
<
VoidCallback
>[
()
{},
()
{},
()
{},
()
{},
()
{},
];
for
(
int
listenerCount
=
1
;
listenerCount
<=
5
;
listenerCount
+=
1
)
{
final
List
<
_Notifier
>
notifiers
=
List
<
_Notifier
>.
generate
(
iteration
,
(
_
)
{
final
_Notifier
notifier
=
_Notifier
();
for
(
int
l
=
0
;
l
<
listenerCount
;
l
+=
1
)
{
notifier
.
addListener
(
listeners
[
l
]);
}
return
notifier
;
},
growable:
false
,
);
final
Stopwatch
watch
=
Stopwatch
();
watch
.
start
();
for
(
int
i
=
0
;
i
<
iteration
;
i
+=
1
)
{
for
(
int
l
=
0
;
l
<
listenerCount
;
l
+=
1
)
{
notifiers
[
i
].
removeListener
(
listeners
[
l
]);
}
}
watch
.
stop
();
final
int
elapsed
=
watch
.
elapsedMicroseconds
;
final
double
averagePerIteration
=
elapsed
/
iteration
;
if
(
addResult
)
printer
.
addResult
(
description:
'
$name
(
$listenerCount
listeners)'
,
value:
averagePerIteration
*
_kScale
,
unit:
'ns per iteration'
,
name:
'
$name${listenerCount}
_iteration'
,
);
}
}
void
runRemoveListenerWhileNotifyingBenchmark
(
int
iteration
,
{
bool
addResult
=
true
})
{
const
String
name
=
'removeListenerWhileNotifying'
;
final
List
<
VoidCallback
>
listeners
=
<
VoidCallback
>[
()
{},
()
{},
()
{},
()
{},
()
{},
];
for
(
int
listenerCount
=
1
;
listenerCount
<=
5
;
listenerCount
+=
1
)
{
final
List
<
_Notifier
>
notifiers
=
List
<
_Notifier
>.
generate
(
iteration
,
(
_
)
{
final
_Notifier
notifier
=
_Notifier
();
notifier
.
addListener
(()
{
// This listener will remove all other listeners. So that only this
// one is called and measured.
for
(
int
l
=
0
;
l
<
listenerCount
;
l
+=
1
)
{
notifier
.
removeListener
(
listeners
[
l
]);
}
});
for
(
int
l
=
0
;
l
<
listenerCount
;
l
+=
1
)
{
notifier
.
addListener
(
listeners
[
l
]);
}
return
notifier
;
},
growable:
false
,
);
final
Stopwatch
watch
=
Stopwatch
();
watch
.
start
();
for
(
int
i
=
0
;
i
<
iteration
;
i
+=
1
)
{
notifiers
[
i
].
notify
();
}
watch
.
stop
();
final
int
elapsed
=
watch
.
elapsedMicroseconds
;
final
double
averagePerIteration
=
elapsed
/
iteration
;
if
(
addResult
)
printer
.
addResult
(
description:
'
$name
(
$listenerCount
listeners)'
,
value:
averagePerIteration
*
_kScale
,
unit:
'ns per iteration'
,
name:
'
$name${listenerCount}
_iteration'
,
);
}
}
runAddListenerBenchmark
(
_kNumWarmUp
,
addResult:
false
);
runAddListenerBenchmark
(
_kNumIterations
,
addResult:
true
);
runNotifyListenerBenchmark
(
_kNumWarmUp
,
addResult:
false
);
runNotifyListenerBenchmark
(
_kNumIterations
,
addResult:
true
);
runRemoveListenerBenchmark
(
_kNumWarmUp
,
addResult:
false
);
runRemoveListenerBenchmark
(
_kNumIterations
,
addResult:
true
);
runRemoveListenerWhileNotifyingBenchmark
(
_kNumWarmUp
,
addResult:
false
);
runRemoveListenerWhileNotifyingBenchmark
(
_kNumIterations
,
addResult:
true
);
printer
.
printToStdout
();
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment