Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DiDi
DoraemonKit
提交
148925c9
D
DoraemonKit
项目概览
DiDi
/
DoraemonKit
12 个月 前同步成功
通知
166
Star
19623
Fork
3062
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
DoraemonKit
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
148925c9
编写于
2月 24, 2021
作者:
[
[linjizong]
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
vmhelper重构;完善内存泄漏demo
上级
25967ead
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
448 addition
and
162 deletion
+448
-162
Flutter/example/ios/Podfile.lock
Flutter/example/ios/Podfile.lock
+0
-6
Flutter/example/lib/main.dart
Flutter/example/lib/main.dart
+66
-1
Flutter/example/pubspec.yaml
Flutter/example/pubspec.yaml
+1
-1
Flutter/lib/kit/apm/leak/leak_checker.dart
Flutter/lib/kit/apm/leak/leak_checker.dart
+81
-0
Flutter/lib/kit/apm/leak/leak_obj.dart
Flutter/lib/kit/apm/leak/leak_obj.dart
+4
-4
Flutter/lib/kit/apm/leak/leak_observer.dart
Flutter/lib/kit/apm/leak/leak_observer.dart
+31
-0
Flutter/lib/kit/apm/leak_kit.dart
Flutter/lib/kit/apm/leak_kit.dart
+9
-30
Flutter/lib/kit/apm/memory_kit.dart
Flutter/lib/kit/apm/memory_kit.dart
+10
-7
Flutter/lib/kit/apm/vm/iso_pool.dart
Flutter/lib/kit/apm/vm/iso_pool.dart
+37
-0
Flutter/lib/kit/apm/vm/version.dart
Flutter/lib/kit/apm/vm/version.dart
+0
-0
Flutter/lib/kit/apm/vm/vm_helper.dart
Flutter/lib/kit/apm/vm/vm_helper.dart
+97
-0
Flutter/lib/kit/apm/vm/vm_service_wrapper.dart
Flutter/lib/kit/apm/vm/vm_service_wrapper.dart
+61
-99
Flutter/lib/kit/common/basic_info.dart
Flutter/lib/kit/common/basic_info.dart
+43
-14
Flutter/pubspec.lock
Flutter/pubspec.lock
+7
-0
Flutter/pubspec.yaml
Flutter/pubspec.yaml
+1
-0
未找到文件。
Flutter/example/ios/Podfile.lock
浏览文件 @
148925c9
...
...
@@ -8,8 +8,6 @@ PODS:
- Flutter
- path_provider_windows (0.0.1):
- Flutter
- sensors (0.0.1):
- Flutter
- shared_preferences (0.0.1):
- Flutter
- shared_preferences_linux (0.0.1):
...
...
@@ -27,7 +25,6 @@ DEPENDENCIES:
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- path_provider_linux (from `.symlinks/plugins/path_provider_linux/ios`)
- path_provider_windows (from `.symlinks/plugins/path_provider_windows/ios`)
- sensors (from `.symlinks/plugins/sensors/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- shared_preferences_linux (from `.symlinks/plugins/shared_preferences_linux/ios`)
- shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`)
...
...
@@ -45,8 +42,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/path_provider_linux/ios"
path_provider_windows:
:path: ".symlinks/plugins/path_provider_windows/ios"
sensors:
:path: ".symlinks/plugins/sensors/ios"
shared_preferences:
:path: ".symlinks/plugins/shared_preferences/ios"
shared_preferences_linux:
...
...
@@ -64,7 +59,6 @@ SPEC CHECKSUMS:
path_provider: fb74bd0465e96b594bb3b5088ee4a4e7bb1f2a9d
path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4
path_provider_windows: a2b81600c677ac1959367280991971cb9a1edb3b
sensors: 84eb7a30e47a649e4172b71d6e81be614c280336
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
shared_preferences_linux: afefbfe8d921e207f01ede8b60373d9e3b566b78
shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087
...
...
Flutter/example/lib/main.dart
浏览文件 @
148925c9
...
...
@@ -8,13 +8,15 @@
import
'dart:async'
;
import
'dart:convert'
;
import
'dart:io'
;
import
'dart:typed_data'
;
import
'package:dio/dio.dart'
;
import
'package:dokit/kit/apm/leak/leak_observer.dart'
;
import
'package:flutter/material.dart'
;
import
'package:dokit/dokit.dart'
;
import
'package:flutter/services.dart'
;
import
'package:memory_checker/leak_observer.dart'
;
import
'package:path_provider/path_provider.dart'
;
import
'package:dokit/kit/apm/vm/vm_helper.dart'
;
void
main
(
)
{
List
<
String
>
blackList
=
[
...
...
@@ -58,6 +60,7 @@ class MyApp extends StatelessWidget {
// closer together (more dense) than on mobile platforms.
visualDensity:
VisualDensity
.
adaptivePlatformDensity
,
),
navigatorObservers:
[
LeakObserver
(),
DoKitLeakObserver
()],
home:
DoKitTestPage
(),
);
}
...
...
@@ -179,6 +182,22 @@ class _DoKitTestPageState extends State<DoKitTestPage> {
},
),
),
Container
(
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4
)),
color:
Color
(
0xffcccccc
)),
margin:
EdgeInsets
.
only
(
bottom:
30
),
child:
FlatButton
(
child:
Text
(
'Test Isolate'
,
style:
TextStyle
(
color:
Color
(
0xff000000
),
fontSize:
18
,
)),
onPressed:
()
{
VmHelper
.
instance
.
testIsolate
();
},
),
),
Container
(
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4
)),
...
...
@@ -347,7 +366,53 @@ class TestPageState extends State<TestPage> {
}
}
class
A
{
dynamic
a
;
A
(
this
.
a
);
aa
()
{}
}
class
B
{
dynamic
b
;
B
(
this
.
b
);
bb
()
{}
}
class
C
{
dynamic
c
;
C
(
this
.
c
);
cc
()
{}
}
class
D
{
dynamic
d
;
D
(
this
.
d
);
dd
()
{}
}
class
TestPage2
extends
StatefulWidget
{
@override
StatefulElement
createElement
()
{
// TODO: implement createElement
StatefulElement
element
=
super
.
createElement
();
// DoKitLeakObserver.element = element;
// DoKitLeakObserver.test = A(B(C(D(element))));
// Future.delayed(Duration(hours: 1), () {
// print(element);
// });
return
element
;
// return super.createElement();
}
@override
State
<
StatefulWidget
>
createState
()
{
return
TestPageState2
();
...
...
Flutter/example/pubspec.yaml
浏览文件 @
148925c9
...
...
@@ -13,7 +13,7 @@ dependencies:
path
:
..
dio
:
3.0.10
path_provider
:
1.6.0
memory_checker
:
^0.0.4
dev_dependencies
:
flutter_test
:
...
...
Flutter/lib/kit/apm/leak/leak_checker.dart
0 → 100644
浏览文件 @
148925c9
import
'package:dokit/kit/apm/leak/leak_obj.dart'
;
import
'package:dokit/kit/apm/vm/iso_pool.dart'
;
import
'package:dokit/kit/apm/vm/vm_helper.dart'
;
import
'package:dokit/kit/apm/vm/vm_service_wrapper.dart'
;
import
'package:vm_service/vm_service.dart'
;
import
'../leak_kit.dart'
;
Expando
<
LeakInfo
>
expando
;
Future
<
void
>
leakCheck
(
dynamic
obj
)
async
{
// print(obj);
if
(!
VMServiceWrapper
.
instance
.
connected
||
obj
==
null
)
{
return
;
}
expando
=
new
Expando
();
expando
[
obj
]
=
new
LeakInfo
();
VMServiceWrapper
.
instance
.
service
.
getAllocationProfile
(
VMServiceWrapper
.
instance
.
main
.
id
,
gc:
true
);
Future
.
delayed
(
Duration
(
seconds:
1
),
()
{
obj2Id
(
expando
).
then
((
id
)
=>
getRetainingPath
(
obj
,
id
));
});
}
void
getRetainingPath
(
dynamic
obj
,
String
expandoId
)
async
{
String
leakObjId
=
await
IsoPool
().
start
(
_leakCheck
,
expandoId
);
expando
[
obj
]
=
null
;
if
(
leakObjId
!=
null
)
{
// String RetainingPath = await IsoPool().start(_getRetainingPath, leakObjId);
_getRetainingPath
(
leakObjId
);
// print(RetainingPath);
}
else
{
print
(
'no leak:
$obj
'
);
}
}
Future
<
String
>
_getRetainingPath
(
String
leakObjId
)
async
{
if
(!
VMServiceWrapper
.
instance
.
connected
)
{
await
VMServiceWrapper
.
instance
.
connect
();
}
if
(
VMServiceWrapper
.
instance
.
connected
)
{
final
mainId
=
VMServiceWrapper
.
instance
.
main
.
id
;
final
service
=
VMServiceWrapper
.
instance
.
service
;
RetainingPath
path
=
await
service
.
getRetainingPath
(
mainId
,
leakObjId
,
10000
);
print
(
path
);
path
.
elements
.
forEach
((
element
)
{
if
(
element
.
value
.
type
==
'@Instance'
)
{
InstanceRef
ref
=
element
.
value
;
// 过滤隐藏类,一般是系统类
if
(
ref
.
classRef
!=
null
)
{
service
.
invoke
(
mainId
,
element
.
value
.
id
,
'toString'
,
[]).
then
(
(
value
)
=>
printElement
(
ref
.
classRef
.
name
,
value
as
InstanceRef
));
}
}
});
return
path
.
toString
();
}
}
printElement
(
String
className
,
InstanceRef
value
)
{
print
(
'className:
$className
detail:
${value.valueAsString}
'
);
}
Future
<
String
>
_leakCheck
(
String
objectId
)
async
{
if
(!
VMServiceWrapper
.
instance
.
connected
)
{
await
VMServiceWrapper
.
instance
.
connect
();
}
if
(
VMServiceWrapper
.
instance
.
connected
)
{
final
mainId
=
VMServiceWrapper
.
instance
.
main
.
id
;
final
service
=
VMServiceWrapper
.
instance
.
service
;
Instance
instance
=
await
service
.
getObject
(
mainId
,
objectId
);
BoundField
field
=
instance
.
fields
.
firstWhere
((
element
)
=>
element
.
decl
.
name
==
'_data'
);
instance
=
await
service
.
getObject
(
mainId
,
field
.
value
.
id
);
InstanceRef
ref
=
instance
.
elements
.
firstWhere
((
element
)
=>
element
!=
null
&&
(
element
as
InstanceRef
).
kind
==
'WeakProperty'
);
instance
=
await
service
.
getObject
(
mainId
,
ref
.
id
);
return
instance
.
propertyKey
.
id
;
}
}
Flutter/lib/
engine
/leak_obj.dart
→
Flutter/lib/
kit/apm/leak
/leak_obj.dart
浏览文件 @
148925c9
import
'package:dokit/kit/apm/vm
_hel
per.dart'
;
import
'package:dokit/kit/apm/vm
/vm_service_wrap
per.dart'
;
import
'package:vm_service/vm_service.dart'
;
int
_key
=
0
;
...
...
@@ -17,12 +17,12 @@ dynamic keyToObj(String key) {
/// 对象转 id
Future
<
String
>
obj2Id
(
dynamic
obj
)
async
{
VmService
service
=
V
mHelper
.
instance
.
serviceClient
;
String
isolateId
=
V
mHel
per
.
instance
.
main
.
id
;
VmService
service
=
V
MServiceWrapper
.
instance
.
service
;
String
isolateId
=
V
MServiceWrap
per
.
instance
.
main
.
id
;
Isolate
isolate
=
await
service
.
getIsolate
(
isolateId
);
String
libraryId
=
isolate
.
libraries
.
firstWhere
(
(
element
)
=>
element
.
uri
.
contains
(
'dokit/
engine
/leak_obj.dart'
))
(
element
)
=>
element
.
uri
.
contains
(
'dokit/
kit/apm/leak
/leak_obj.dart'
))
.
id
;
// 用 vm service 执行 generateNewKey 函数
...
...
Flutter/lib/kit/apm/leak/leak_observer.dart
0 → 100644
浏览文件 @
148925c9
import
'package:dokit/kit/apm/leak/leak_checker.dart'
;
import
'package:flutter/material.dart'
;
import
'../fps_kit.dart'
;
class
DoKitLeakObserver
extends
NavigatorObserver
{
static
dynamic
element
;
static
dynamic
test
;
@override
void
didPop
(
Route
<
dynamic
>
route
,
Route
<
dynamic
>
previousRoute
)
=>
_doCheck
(
route
,
previousRoute
);
@override
void
didReplace
({
Route
<
dynamic
>
newRoute
,
Route
<
dynamic
>
oldRoute
})
=>
_doCheck
(
newRoute
,
oldRoute
);
@override
void
didRemove
(
Route
<
dynamic
>
route
,
Route
<
dynamic
>
previousRoute
)
=>
_doCheck
(
route
,
previousRoute
);
Future
<
bool
>
get
enableCheck
=>
Future
.
value
(
true
);
void
_doCheck
(
Route
<
dynamic
>
route
,
Route
<
dynamic
>
previousRoute
)
async
{
final
enableCheck
=
await
this
.
enableCheck
;
if
(!
enableCheck
)
return
;
dynamic
obj
=
element
;
element
=
null
;
await
leakCheck
(
route
);
}
}
Flutter/lib/kit/apm/leak_kit.dart
浏览文件 @
148925c9
import
'package:dokit/dokit.dart'
;
import
'package:dokit/
engine
/leak_obj.dart'
;
import
'package:dokit/
kit/apm/leak
/leak_obj.dart'
;
import
'package:dokit/kit/apm/apm.dart'
;
import
'package:dokit/kit/apm/fps_kit.dart'
;
import
'package:dokit/kit/apm/vm_helper.dart'
;
import
'package:dokit/kit/apm/vm/vm_helper.dart'
;
import
'package:dokit/kit/apm/vm/vm_service_wrapper.dart'
;
import
'package:dokit/kit/kit.dart'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/src/widgets/framework.dart'
;
import
'package:vm_service/vm_service.dart'
;
import
"package:vm_service/vm_service.dart"
;
class
LeakKit
extends
ApmKit
{
Expando
<
LeakInfo
>
_expando
=
new
Expando
();
...
...
@@ -28,49 +29,27 @@ class LeakKit extends ApmKit {
@override
String
getIcon
()
{
Uri
uri
=
Uri
.
parse
(
'http://www.baidu.com'
);
Uri
uri
=
Uri
.
parse
(
'http://www.baidu.com'
);
return
'images/dk_log_info.png'
;
}
static
Element
e
;
static
FpsInfo
fpsInfo
=
new
FpsInfo
();
static
FpsInfo
fpsInfo
=
new
FpsInfo
();
@override
void
start
()
{
Future
.
delayed
(
Duration
(
seconds:
1
),
()
{
e
=
DoKitApp
.
rootKey
.
currentContext
;
_expando
[
e
]
=
new
LeakInfo
();
_expando
[
fpsInfo
]=
new
LeakInfo
();
VmHelper
.
instance
.
serviceClient
.
getAllocationProfile
(
VmHelper
.
instance
.
main
.
id
,
gc:
true
);
_expando
[
fpsInfo
]
=
new
LeakInfo
();
VMServiceWrapper
.
instance
.
gc
();
Future
.
delayed
(
Duration
(
seconds:
1
),
()
{
obj2Id
(
_expando
).
then
((
id
)
=>
printExpando
(
id
));
});
});
}
void
printExpando
(
String
objectId
)
{
VmHelper
.
instance
.
serviceClient
.
getObject
(
VmHelper
.
instance
.
main
.
id
,
objectId
)
.
then
((
value
)
=>
(
value
as
Instance
).
fields
.
forEach
((
element
)
{
if
(
element
.
decl
.
name
==
'_data'
)
{
VmHelper
.
instance
.
serviceClient
.
getObject
(
VmHelper
.
instance
.
main
.
id
,
element
.
value
.
id
)
.
then
((
value
)
=>
(
value
as
Instance
).
elements
.
forEach
((
element
)
{
if
(
element
!=
null
)
{
InstanceRef
ref
=
element
as
InstanceRef
;
if
(
ref
.
kind
==
'WeakProperty'
)
{
VmHelper
.
instance
.
serviceClient
.
getObject
(
VmHelper
.
instance
.
main
.
id
,
ref
.
id
)
.
then
((
value
)
=>
print
((
value
as
Instance
).
propertyKey
));
}
}
}));
}
}));
}
void
printExpando
(
String
objectId
)
{}
@override
void
stop
()
{}
...
...
Flutter/lib/kit/apm/memory_kit.dart
浏览文件 @
148925c9
import
'dart:ui'
;
import
'package:dokit/kit/apm/vm/vm_service_wrapper.dart'
;
import
'package:flutter/cupertino.dart'
;
import
'package:flutter/material.dart'
;
import
'package:dokit/util/util.dart'
;
...
...
@@ -9,7 +10,7 @@ import 'package:vm_service/vm_service.dart';
import
'../../dokit.dart'
;
import
'../kit.dart'
;
import
'apm.dart'
;
import
'vm_helper.dart'
;
import
'vm
/vm
_helper.dart'
;
class
MemoryInfo
implements
IInfo
{
int
fps
;
...
...
@@ -36,14 +37,16 @@ class MemoryKit extends ApmKit {
@override
void
start
()
async
{
VMServiceWrapper
.
instance
.
connect
();
VmHelper
vmHelper
=
VmHelper
.
instance
;
await
vmHelper
.
startConnect
();
vmHelper
.
updateMemoryUsage
();
VMServiceWrapper
.
instance
.
connect
()
.
then
((
value
)
=>
vmHelper
.
resolveVMInfo
());
}
void
update
()
{
VmHelper
.
instance
.
dump
AllocationProfile
();
VmHelper
.
instance
.
resolv
eFlutterVersion
();
VmHelper
.
instance
.
update
AllocationProfile
();
VmHelper
.
instance
.
updat
eFlutterVersion
();
VmHelper
.
instance
.
updateMemoryUsage
();
}
...
...
@@ -53,7 +56,7 @@ class MemoryKit extends ApmKit {
@override
void
stop
()
{
V
mHel
per
.
instance
.
disConnect
();
V
MServiceWrap
per
.
instance
.
disConnect
();
}
@override
...
...
@@ -118,7 +121,7 @@ class MemoryPageState extends State<MemoryPage> {
fontSize:
16
)),
StreamBuilder
(
stream:
Stream
.
periodic
(
Duration
(
seconds:
2
),
(
value
)
{
VmHelper
.
instance
.
dump
AllocationProfile
();
VmHelper
.
instance
.
update
AllocationProfile
();
VmHelper
.
instance
.
updateMemoryUsage
();
}),
builder:
(
context
,
snapshot
)
{
...
...
Flutter/lib/kit/apm/vm/iso_pool.dart
0 → 100644
浏览文件 @
148925c9
import
'dart:async'
;
import
'package:isolate/isolate.dart'
;
class
IsoPool
{
static
final
IsoPool
_instance
=
IsoPool
.
_internal
();
factory
IsoPool
()
{
return
_instance
;
}
IsoPool
.
_internal
();
LoadBalancer
_loadBalance
;
bool
_isBalanceRunning
=
false
;
Future
<
R
>
start
<
R
,
P
>(
FutureOr
<
R
>
Function
(
P
argument
)
function
,
argument
)
{
return
_isBalanceRunning
?
_calculateMore
(
function
,
argument
)
:
_startBalance
(
function
,
argument
);
}
Future
<
R
>
_startBalance
<
R
,
P
>(
FutureOr
<
R
>
Function
(
P
argument
)
function
,
argument
)
async
{
if
(
_isBalanceRunning
)
throw
Exception
(
'ISO pool is running, do not start again'
);
_loadBalance
=
await
LoadBalancer
.
create
(
1
,
IsolateRunner
.
spawn
);
final
res
=
await
_loadBalance
.
run
<
R
,
P
>(
function
,
argument
);
_isBalanceRunning
=
true
;
return
res
;
}
Future
<
R
>
_calculateMore
<
R
,
P
>(
FutureOr
<
R
>
Function
(
P
argument
)
function
,
argument
)
async
{
if
(!
_isBalanceRunning
)
throw
Exception
(
'ISO pool is not running'
);
return
await
_loadBalance
.
run
<
R
,
P
>(
function
,
argument
);
}
}
Flutter/lib/kit/apm/version.dart
→
Flutter/lib/kit/apm/v
m/v
ersion.dart
浏览文件 @
148925c9
文件已移动
Flutter/lib/kit/apm/vm/vm_helper.dart
0 → 100644
浏览文件 @
148925c9
import
'dart:async'
;
import
'package:dokit/kit/apm/vm/iso_pool.dart'
;
import
'package:dokit/kit/apm/vm/version.dart'
;
import
'package:dokit/kit/apm/vm/vm_service_wrapper.dart'
;
import
'package:package_info/package_info.dart'
;
import
'package:vm_service/vm_service.dart'
;
class
VmHelper
{
VmHelper
.
_privateConstructor
();
static
final
VmHelper
_instance
=
VmHelper
.
_privateConstructor
();
static
VmHelper
get
instance
=>
_instance
;
// 各Isolate内存使用情况
Map
<
IsolateRef
,
MemoryUsage
>
memoryInfo
=
new
Map
();
AllocationProfile
allocationProfile
;
PackageInfo
packageInfo
;
// flutter版本
String
_flutterVersion
=
''
;
VM
get
vm
=>
VMServiceWrapper
.
instance
.
vm
;
Future
<
void
>
resolveVMInfo
()
async
{
if
(!
VMServiceWrapper
.
instance
.
connected
)
{
return
;
}
PackageInfo
.
fromPlatform
().
then
((
value
)
=>
packageInfo
=
value
);
updateMemoryUsage
();
updateFlutterVersion
();
updateAllocationProfile
();
}
String
get
flutterVersion
{
if
(!
VMServiceWrapper
.
instance
.
connected
)
{
return
'Flutter Attach后可获取版本号'
;
}
if
(
_flutterVersion
!=
''
)
{
return
_flutterVersion
;
}
else
{
return
'Flutter Attach后可获取版本号'
;
}
}
updateMemoryUsage
()
{
if
(!
VMServiceWrapper
.
instance
.
connected
)
{
return
;
}
VMServiceWrapper
.
instance
.
service
.
getMemoryUsage
(
VMServiceWrapper
.
instance
.
main
.
id
)
.
then
((
value
)
=>
memoryInfo
[
VMServiceWrapper
.
instance
.
main
]
=
value
);
}
updateFlutterVersion
()
{
if
(!
VMServiceWrapper
.
instance
.
connected
)
{
return
;
}
VMServiceWrapper
.
instance
.
callExtensionService
(
'flutterVersion'
)?.
then
(
(
value
)
=>
_flutterVersion
=
FlutterVersion
.
parse
(
value
.
json
).
version
);
}
updateAllocationProfile
()
{
if
(!
VMServiceWrapper
.
instance
.
connected
)
{
return
;
}
VMServiceWrapper
.
instance
.
service
.
getAllocationProfile
(
VMServiceWrapper
.
instance
.
main
.
id
)
.
then
((
value
)
=>
allocationProfile
=
value
);
}
testIsolate
()
async
{
Script
script
=
await
IsoPool
().
start
(
getScriptList
,
'main.dart'
);
// Script script = await getScriptList('main.dart');
print
(
script
?.
source
);
}
}
Future
<
Script
>
getScriptList
(
String
fileName
)
async
{
print
(
'has connected:
${VMServiceWrapper.instance.connected}
'
);
if
(!
VMServiceWrapper
.
instance
.
connected
)
{
await
VMServiceWrapper
.
instance
.
connect
();
}
if
(
VMServiceWrapper
.
instance
.
service
!=
null
&&
VMServiceWrapper
.
instance
.
connected
)
{
ScriptList
scriptList
=
await
VMServiceWrapper
.
instance
.
service
.
getScripts
(
VMServiceWrapper
.
instance
.
main
.
id
);
ScriptRef
scriptRef
=
scriptList
?.
scripts
?.
firstWhere
((
element
)
=>
element
.
id
.
contains
(
fileName
));
if
(
scriptRef
!=
null
)
{
return
(
await
VMServiceWrapper
.
instance
.
service
.
getObject
(
VMServiceWrapper
.
instance
.
main
.
id
,
scriptRef
.
id
))
as
Script
;
}
}
return
null
;
}
Flutter/lib/kit/apm/vm
_hel
per.dart
→
Flutter/lib/kit/apm/vm
/vm_service_wrap
per.dart
浏览文件 @
148925c9
library
service_tester
;
import
'dart:async'
;
import
'dart:developer'
;
import
'package:dokit/kit/apm/version.dart'
;
import
'package:flutter/
material
.dart'
;
import
'package:
package_info/package_info
.dart'
;
import
'package:dokit/kit/apm/v
m/v
ersion.dart'
;
import
'package:flutter/
foundation
.dart'
;
import
'package:
vm_service/utils
.dart'
;
import
'package:vm_service/vm_service.dart'
;
import
'package:vm_service/vm_service_io.dart'
;
import
'package:vm_service/utils.dart'
;
class
V
mHel
per
{
V
mHelper
.
_privateConstructor
()
{}
class
V
MServiceWrap
per
{
V
MServiceWrapper
.
_privateConstructor
();
static
final
VmHelper
_instance
=
VmHelper
.
_privateConstructor
();
static
final
VMServiceWrapper
_instance
=
VMServiceWrapper
.
_privateConstructor
();
static
VmHelper
get
instance
=>
_instance
;
static
VMServiceWrapper
get
instance
=>
_instance
;
VmService
service
;
VmService
serviceClient
;
Version
_protocolVersion
;
Version
_dartIoVersion
;
IsolateRef
main
;
VM
vm
;
// flutter版本
String
_flutterVersion
=
''
;
VM
vm
;
// 各Isolate内存使用情况
Map
<
IsolateRef
,
MemoryUsage
>
memoryInfo
=
new
Map
();
bool
connected
;
AllocationProfile
allocationProfile
;
PackageInfo
packageInfo
;
ExtensionService
_extensionService
;
bool
connected
=
false
;
Map
<
String
,
List
<
String
>>
get
registeredMethodsForService
=>
_registeredMethodsForService
;
final
Map
<
String
,
List
<
String
>>
_registeredMethodsForService
=
{};
Future
<
VmService
>
getService
(
info
)
async
{
Uri
uri
=
convertToWebSocketUrl
(
serviceProtocolUrl:
info
.
serverUri
);
return
await
vmServiceConnectUri
(
uri
.
toString
(),
log:
StdoutLog
());
}
startC
onnect
()
async
{
Future
<
void
>
c
onnect
()
async
{
ServiceProtocolInfo
info
=
await
Service
.
getInfo
();
if
(
info
==
null
||
info
.
serverUri
==
null
)
{
print
(
"service protocol url is null,start vm service fail"
);
return
;
}
Uri
uri
=
convertToWebSocketUrl
(
serviceProtocolUrl:
info
.
serverUri
);
serviceClient
=
await
vmServiceConnectUri
(
uri
.
toString
(),
log:
StdoutLog
());
service
=
await
getService
(
info
);
print
(
'socket connected in service
$info
'
);
connected
=
true
;
vm
=
await
serviceClient
.
getVM
();
vm
=
await
service
.
getVM
();
List
<
IsolateRef
>
isolates
=
vm
.
isolates
;
main
=
isolates
.
firstWhere
((
ref
)
=>
ref
.
name
.
contains
(
'main'
));
main
??=
isolates
.
first
;
serviceClient
.
getMemoryUsage
(
main
.
id
)
.
then
((
value
)
=>
memoryInfo
[
main
]
=
value
);
loadExtensionService
();
PackageInfo
.
fromPlatform
().
then
((
value
)
=>
packageInfo
=
value
);
getScriptList
();
connected
=
true
;
}
Future
<
Response
>
callExtensionService
(
String
method
)
async
{
if
(
_extensionService
==
null
)
{
_extensionService
=
new
ExtensionService
(
service
,
main
);
await
_extensionService
.
loadExtensionService
();
}
return
_extensionService
.
callMethod
(
method
);
}
gc
()
{
if
(
connected
)
{
service
.
getAllocationProfile
(
main
.
id
,
gc:
true
);
}
}
disConnect
()
async
{
if
(
service
!=
null
)
{
print
(
'waiting for client to shut down...'
);
service
.
dispose
();
await
service
.
onDone
;
connected
=
false
;
service
=
null
;
print
(
'service client shut down'
);
}
}
}
class
ExtensionService
{
final
VmService
serviceClient
;
final
IsolateRef
main
;
Version
_protocolVersion
;
Version
_dartIoVersion
;
Map
<
String
,
List
<
String
>>
get
registeredMethodsForService
=>
_registeredMethodsForService
;
final
Map
<
String
,
List
<
String
>>
_registeredMethodsForService
=
{};
ExtensionService
(
this
.
serviceClient
,
this
.
main
);
// 获取flutter版本,目前比较鸡肋,需要借助devtools向vmservice注册的服务来获取,flutter 未 attach的情况下无法使用。
void
loadExtensionService
()
async
{
Future
<
void
>
loadExtensionService
()
async
{
final
serviceStreamName
=
await
this
.
serviceStreamName
;
serviceClient
.
onEvent
(
serviceStreamName
).
listen
(
handleServiceEvent
);
final
streamIds
=
[
...
...
@@ -83,15 +106,6 @@ class VmHelper {
print
(
e
);
}
}));
resolveFlutterVersion
();
}
String
get
flutterVersion
{
if
(
_flutterVersion
!=
''
)
{
return
_flutterVersion
;
}
else
{
return
'Flutter Attach后可获取版本号'
;
}
}
Future
<
String
>
get
serviceStreamName
async
=>
...
...
@@ -146,9 +160,6 @@ class VmHelper {
_registeredMethodsForService
.
putIfAbsent
(
serviceName
,
()
=>
[])
.
add
(
e
.
method
);
if
(
_flutterVersion
==
''
&&
serviceName
==
'flutterVersion'
)
{
resolveFlutterVersion
();
}
}
if
(
e
.
kind
==
EventKind
.
kServiceUnregistered
)
{
...
...
@@ -157,25 +168,6 @@ class VmHelper {
}
}
void
resolveFlutterVersion
()
{
callMethod
(
'flutterVersion'
)?.
then
(
(
value
)
=>
_flutterVersion
=
FlutterVersion
.
parse
(
value
.
json
).
version
);
}
void
getScriptList
()
{
if
(
serviceClient
!=
null
&&
connected
)
{
serviceClient
.
getScripts
(
main
.
id
)
.
then
((
value
)
=>
value
.
scripts
?.
forEach
((
value
)
{
if
(
value
.
id
.
contains
(
'main.dart'
))
{
serviceClient
.
getObject
(
main
.
id
,
value
.
id
)
.
then
((
obj
)
=>
{
print
((
obj
as
Script
).
source
)});
}
}));
}
}
Future
<
Response
>
callMethod
(
String
method
)
{
if
(
registeredMethodsForService
.
containsKey
(
method
))
{
return
(
serviceClient
.
callMethod
(
registeredMethodsForService
[
method
].
last
,
...
...
@@ -183,36 +175,6 @@ class VmHelper {
}
return
null
;
}
updateMemoryUsage
()
{
if
(
serviceClient
!=
null
&&
connected
)
{
serviceClient
.
getMemoryUsage
(
main
.
id
)
.
then
((
value
)
=>
memoryInfo
[
main
]
=
value
);
}
}
dumpAllocationProfile
()
async
{
if
(
serviceClient
!=
null
&&
connected
)
{
serviceClient
.
getAllocationProfile
(
main
.
id
)
.
then
((
value
)
=>
allocationProfile
=
value
);
}
}
disConnect
()
async
{
if
(
serviceClient
!=
null
)
{
print
(
'waiting for client to shut down...'
);
serviceClient
.
dispose
();
await
serviceClient
.
onDone
;
connected
=
false
;
serviceClient
=
null
;
print
(
'service client shut down'
);
}
}
}
class
StdoutLog
extends
Log
{
...
...
Flutter/lib/kit/common/basic_info.dart
浏览文件 @
148925c9
import
'package:dokit/kit/apm/vm_helper.dart'
;
import
'package:dokit/kit/apm/vm/vm_helper.dart'
;
import
'package:dokit/kit/apm/vm/vm_service_wrapper.dart'
;
import
'package:dokit/kit/common/common.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/src/widgets/framework.dart'
;
import
'package:vm_service/vm_service.dart'
;
class
BasicInfoKit
extends
CommonKit
{
@override
...
...
@@ -46,19 +48,7 @@ class BasicInfoPage extends StatelessWidget {
list
.
add
(
Divider
(
height:
0.5
,
color:
Color
(
0xffeeeeee
)));
list
.
add
(
InfoItem
(
'Flutter版本'
,
VmHelper
.
instance
.
flutterVersion
));
list
.
add
(
Divider
(
height:
0.5
,
color:
Color
(
0xffeeeeee
)));
String
isolate
;
int
index
=
1
;
VmHelper
.
instance
.
vm
?.
isolates
?.
forEach
((
element
)
{
if
(
isolate
==
null
)
{
isolate
=
'[isolate
$index
]:
${element.name}
${element.type}
\n
'
;
}
else
{
isolate
+=
'[isolate
$index
]:
${element.name}
${element.type}
\n
'
;
}
});
if
(
isolate
!=
null
&&
isolate
.
length
>
1
)
{
isolate
=
isolate
.
substring
(
0
,
isolate
.
length
-
1
);
}
list
.
add
(
InfoItem
(
'Isolates'
,
isolate
));
list
.
add
(
IsolateItem
());
list
.
add
(
Divider
(
height:
0.5
,
color:
Color
(
0xffeeeeee
)));
list
.
add
(
Container
(
...
...
@@ -78,6 +68,45 @@ class BasicInfoPage extends StatelessWidget {
}
}
class
IsolateItem
extends
StatefulWidget
{
@override
State
<
StatefulWidget
>
createState
()
{
return
_IsolateItemState
();
}
}
class
_IsolateItemState
extends
State
<
IsolateItem
>
{
VM
vm
;
@override
void
initState
()
{
super
.
initState
();
VMServiceWrapper
.
instance
.
service
.
getVM
().
then
((
value
)
=>
setState
(()
{
vm
=
value
;
}));
}
@override
Widget
build
(
BuildContext
context
)
{
String
isolate
;
int
index
=
1
;
vm
?.
isolates
?.
forEach
((
element
)
{
if
(
isolate
==
null
)
{
isolate
=
'[isolate
$index
]:
${element.name}
${element.type}
\n
'
;
}
else
{
isolate
+=
'[isolate
$index
]:
${element.name}
${element.type}
\n
'
;
}
index
++;
});
if
(
isolate
!=
null
&&
isolate
.
length
>
1
)
{
isolate
=
isolate
.
substring
(
0
,
isolate
.
length
-
1
);
}
isolate
??=
'-'
;
return
InfoItem
(
'Isolates'
,
isolate
);
}
}
class
InfoItem
extends
StatelessWidget
{
final
String
label
;
final
String
text
;
...
...
Flutter/pubspec.lock
浏览文件 @
148925c9
...
...
@@ -93,6 +93,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.16.1"
isolate:
dependency: "direct main"
description:
name: isolate
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.3"
matcher:
dependency: transitive
description:
...
...
Flutter/pubspec.yaml
浏览文件 @
148925c9
...
...
@@ -15,6 +15,7 @@ dependencies:
vm_service
:
^5.5.0
package_info
:
^0.4.3+2
shared_preferences
:
^0.5.12+4
isolate
:
^2.0.3
dev_dependencies
:
flutter_test
:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录