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
20a9f1d8
Unverified
Commit
20a9f1d8
authored
May 26, 2022
by
gaaclarke
Committed by
GitHub
May 26, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added option for Platform Channel statistics and Timeline events (#104531)
parent
5aca8bd1
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
148 additions
and
6 deletions
+148
-6
debug.dart
packages/flutter/lib/src/services/debug.dart
+15
-0
platform_channel.dart
packages/flutter/lib/src/services/platform_channel.dart
+133
-6
No files found.
packages/flutter/lib/src/services/debug.dart
View file @
20a9f1d8
...
...
@@ -13,6 +13,18 @@ import 'hardware_keyboard.dart';
/// of their extent of support for keyboard API.
KeyDataTransitMode
?
debugKeyEventSimulatorTransitModeOverride
;
/// Profile and print statistics on Platform Channel usage.
///
/// When this is is true statistics about the usage of Platform Channels will be
/// printed out periodically to the console and Timeline events will show the
/// time between sending and receiving a message (encoding and decoding time
/// excluded).
///
/// The statistics include the total bytes transmitted and the average number of
/// bytes per invocation in the last quantum. "Up" means in the direction of
/// Flutter to the host platform, "down" is the host platform to flutter.
bool
debugProfilePlatformChannels
=
false
;
/// Returns true if none of the widget library debug variables have been changed.
///
/// This function is used by the test framework to ensure that debug variables
...
...
@@ -24,6 +36,9 @@ bool debugAssertAllServicesVarsUnset(String reason) {
if
(
debugKeyEventSimulatorTransitModeOverride
!=
null
)
{
throw
FlutterError
(
reason
);
}
if
(
debugProfilePlatformChannels
)
{
throw
FlutterError
(
reason
);
}
return
true
;
}());
return
true
;
...
...
packages/flutter/lib/src/services/platform_channel.dart
View file @
20a9f1d8
...
...
@@ -3,14 +3,124 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:developer'
;
import
'dart:ui'
show
PlatformMessageResponseCallback
;
import
'package:flutter/foundation.dart'
;
import
'binary_messenger.dart'
;
import
'binding.dart'
;
import
'debug.dart'
show
debugProfilePlatformChannels
;
import
'message_codec.dart'
;
import
'message_codecs.dart'
;
bool
_debugProfilePlatformChannelsIsRunning
=
false
;
const
Duration
_debugProfilePlatformChannelsRate
=
Duration
(
seconds:
1
);
final
Expando
<
BinaryMessenger
>
_debugBinaryMessengers
=
Expando
<
BinaryMessenger
>();
class
_ProfiledBinaryMessenger
implements
BinaryMessenger
{
const
_ProfiledBinaryMessenger
(
this
.
proxy
,
this
.
channelTypeName
,
this
.
codecTypeName
);
final
BinaryMessenger
proxy
;
final
String
channelTypeName
;
final
String
codecTypeName
;
@override
Future
<
void
>
handlePlatformMessage
(
String
channel
,
ByteData
?
data
,
PlatformMessageResponseCallback
?
callback
)
{
return
proxy
.
handlePlatformMessage
(
channel
,
data
,
callback
);
}
Future
<
ByteData
?>?
sendWithPostfix
(
String
channel
,
String
postfix
,
ByteData
?
message
)
async
{
final
TimelineTask
task
=
TimelineTask
();
_debugRecordUpStream
(
channelTypeName
,
'
$channel$postfix
'
,
codecTypeName
,
message
);
task
.
start
(
'Platform Channel send
$channel$postfix
'
);
final
ByteData
?
result
;
try
{
result
=
await
proxy
.
send
(
channel
,
message
);
}
finally
{
task
.
finish
();
}
_debugRecordDownStream
(
channelTypeName
,
'
$channel$postfix
'
,
codecTypeName
,
result
);
return
result
;
}
@override
Future
<
ByteData
?>?
send
(
String
channel
,
ByteData
?
message
)
=>
sendWithPostfix
(
channel
,
''
,
message
);
@override
void
setMessageHandler
(
String
channel
,
MessageHandler
?
handler
)
{
proxy
.
setMessageHandler
(
channel
,
handler
);
}
}
class
_PlatformChannelStats
{
_PlatformChannelStats
(
this
.
channel
,
this
.
codec
,
this
.
type
);
final
String
channel
;
final
String
codec
;
final
String
type
;
int
_upCount
=
0
;
int
_upBytes
=
0
;
int
get
upBytes
=>
_upBytes
;
void
addUpStream
(
int
bytes
)
{
_upCount
+=
1
;
_upBytes
+=
bytes
;
}
int
_downCount
=
0
;
int
_downBytes
=
0
;
int
get
downBytes
=>
_downBytes
;
void
addDownStream
(
int
bytes
)
{
_downCount
+=
1
;
_downBytes
+=
bytes
;
}
double
get
averageUpPayload
=>
_upBytes
/
_upCount
;
double
get
averageDownPayload
=>
_downBytes
/
_downCount
;
}
final
Map
<
String
,
_PlatformChannelStats
>
_debugProfilePlatformChannelsStats
=
<
String
,
_PlatformChannelStats
>{};
Future
<
void
>
_debugLaunchProfilePlatformChannels
()
async
{
if
(!
_debugProfilePlatformChannelsIsRunning
)
{
_debugProfilePlatformChannelsIsRunning
=
true
;
await
Future
<
dynamic
>.
delayed
(
_debugProfilePlatformChannelsRate
);
_debugProfilePlatformChannelsIsRunning
=
false
;
final
StringBuffer
log
=
StringBuffer
();
log
.
writeln
(
'Platform Channel Stats:'
);
final
List
<
_PlatformChannelStats
>
allStats
=
_debugProfilePlatformChannelsStats
.
values
.
toList
();
// Sort highest combined bandwidth first.
allStats
.
sort
((
_PlatformChannelStats
x
,
_PlatformChannelStats
y
)
=>
(
y
.
upBytes
+
y
.
downBytes
)
-
(
x
.
upBytes
+
x
.
downBytes
));
for
(
final
_PlatformChannelStats
stats
in
allStats
)
{
log
.
writeln
(
' (name:"
${stats.channel}
" type:"
${stats.type}
" codec:"
${stats.codec}
" upBytes:
${stats.upBytes}
upBytes_avg:
${stats.averageUpPayload.toStringAsFixed(1)}
downBytes:
${stats.downBytes}
downBytes_avg:
${stats.averageDownPayload.toStringAsFixed(1)}
)'
);
}
debugPrint
(
log
.
toString
());
_debugProfilePlatformChannelsStats
.
clear
();
}
}
void
_debugRecordUpStream
(
String
channelTypeName
,
String
name
,
String
codecTypeName
,
ByteData
?
bytes
)
{
final
_PlatformChannelStats
stats
=
_debugProfilePlatformChannelsStats
[
name
]
??=
_PlatformChannelStats
(
name
,
codecTypeName
,
channelTypeName
);
stats
.
addUpStream
(
bytes
?.
lengthInBytes
??
0
);
_debugLaunchProfilePlatformChannels
();
}
void
_debugRecordDownStream
(
String
channelTypeName
,
String
name
,
String
codecTypeName
,
ByteData
?
bytes
)
{
final
_PlatformChannelStats
stats
=
_debugProfilePlatformChannelsStats
[
name
]
??=
_PlatformChannelStats
(
name
,
codecTypeName
,
channelTypeName
);
stats
.
addDownStream
(
bytes
?.
lengthInBytes
??
0
);
_debugLaunchProfilePlatformChannels
();
}
/// A named channel for communicating with platform plugins using asynchronous
/// message passing.
///
...
...
@@ -49,7 +159,15 @@ class BasicMessageChannel<T> {
final
MessageCodec
<
T
>
codec
;
/// The messenger which sends the bytes for this channel, not null.
BinaryMessenger
get
binaryMessenger
=>
_binaryMessenger
??
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
BinaryMessenger
get
binaryMessenger
{
final
BinaryMessenger
result
=
_binaryMessenger
??
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
return
!
kReleaseMode
&&
debugProfilePlatformChannels
?
_debugBinaryMessengers
[
this
]
??=
_ProfiledBinaryMessenger
(
// ignore: no_runtimetype_tostring
result
,
runtimeType
.
toString
(),
codec
.
runtimeType
.
toString
())
:
result
;
}
final
BinaryMessenger
?
_binaryMessenger
;
/// Sends the specified [message] to the platform plugins on this channel.
...
...
@@ -129,7 +247,15 @@ class MethodChannel {
/// The messenger used by this channel to send platform messages.
///
/// The messenger may not be null.
BinaryMessenger
get
binaryMessenger
=>
_binaryMessenger
??
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
BinaryMessenger
get
binaryMessenger
{
final
BinaryMessenger
result
=
_binaryMessenger
??
ServicesBinding
.
instance
.
defaultBinaryMessenger
;
return
!
kReleaseMode
&&
debugProfilePlatformChannels
?
_debugBinaryMessengers
[
this
]
??=
_ProfiledBinaryMessenger
(
// ignore: no_runtimetype_tostring
result
,
runtimeType
.
toString
(),
codec
.
runtimeType
.
toString
())
:
result
;
}
final
BinaryMessenger
?
_binaryMessenger
;
/// Backend implementation of [invokeMethod].
...
...
@@ -154,10 +280,11 @@ class MethodChannel {
@optionalTypeArgs
Future
<
T
?>
_invokeMethod
<
T
>(
String
method
,
{
required
bool
missingOk
,
dynamic
arguments
})
async
{
assert
(
method
!=
null
);
final
ByteData
?
result
=
await
binaryMessenger
.
send
(
name
,
codec
.
encodeMethodCall
(
MethodCall
(
method
,
arguments
)),
);
final
ByteData
input
=
codec
.
encodeMethodCall
(
MethodCall
(
method
,
arguments
));
final
ByteData
?
result
=
!
kReleaseMode
&&
debugProfilePlatformChannels
?
await
(
binaryMessenger
as
_ProfiledBinaryMessenger
).
sendWithPostfix
(
name
,
'#
$method
'
,
input
)
:
await
binaryMessenger
.
send
(
name
,
input
);
if
(
result
==
null
)
{
if
(
missingOk
)
{
return
null
;
...
...
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