(中文版本请参看这里)
Matrix for iOS/macOS 中文版
Matrix for android 中文版
Matrix for iOS/macOS
Matrix for android
Matrix is an APM (Application Performance Manage) used in Wechat to monitor, locate and analyse performance problems. It is a plugin style, non-invasive solution and is currently available on iOS, macOS and Android.
The monitoring scope of the current tool includes: crash, lag, and out-of-memory, which includes the following two plugins:
-
WCCrashBlockMonitorPlugin: Based on KSCrash framework, it features cutting-edge lag stack capture capabilities with crash capture.
-
WCMemoryStatPlugin: A performance-optimized out-of-memory monitoring tool that captures memory allocation and the callstack of an application's out-of-memory event.
- Easy integration, no code intrusion.
- Determine whether the app is stuck by checking the running status of the Runloop, and support both the iOS and macOS platform.
- Add time-consuming stack fetching, attaching the most time-consuming main thread stack to the thread snapshot log.
- Live recording every object's creating and the corresponding callstack of its creation, and report it when the application out-of-memory is detected.
- Use a balanced binary tree to store living objects and a hash table to store the callstack to optimize performance to the extreme
-
Install via Cocoapods
- Install CocoaPods;
- Run
pod repo update
to make CocoaPods aware of the latest availablematrix
versions; - In your Podfile, add
pod 'matrix-wechat'
to your app target, from the command line, runpod install
; - Use the .xcworkspace file generated by CocoaPods to work on your project;
- Add
#import <Matrix/Matrix.h>
, then you can use the performance probe tool of WeChat.
-
Install with static framework
- Get source code of Matrix;
- Open terminal, execute
make
in thematrix/matrix-iOS
directory to compile and generate static library. After compiling, the iOS platform library is in thematrix/matrix-iOS/build_ios
directory, and the macOS platform library is in thematrix/matrix-iOS/build_macos
directory. - Link with static framework in the project:
- iOS : Use
Matrix.framework
under thematrix/matrix-iOS/build_ios
path, linkMatrix.framework
to the project as a static library; - macOS : Use
Matrix.framework
under thematrix/matrix-iOS/build_macos
path, linkMatrix.framework
to the project as a static library.
- Add
#import <Matrix/Matrix.h>
, then you can use the performance probe tool of WeChat.
In the following places:
- Program
main
function; application:didFinishLaunchingWithOptions:
ofAppDelegate
;- Or other places running as earlier as possible after application launching.
Add a code similar to the following to start the plugin:
#import <Matrix/Matrix.h>
Matrix *matrix = [Matrix sharedInstance];
MatrixBuilder *curBuilder = [[MatrixBuilder alloc] init];
curBuilder.pluginListener = self; // get the related event of plugin via the callback of the pluginListener
WCCrashBlockMonitorPlugin *crashBlockPlugin = [[WCCrashBlockMonitorPlugin alloc] init];
[curBuilder addPlugin:crashBlockPlugin]; // add lag and crash monitor.
WCMemoryStatPlugin *memoryStatPlugin = [[WCMemoryStatPlugin alloc] init];
[curBuilder addPlugin:memoryStatPlugin]; // add out-of-memory monitor.
[matrix addMatrixBuilder:curBuilder];
[crashBlockPlugin start]; // start the lag and crash monitor.
// [memoryStatPlugin start];
// start out-of-memory monitor
// Be careful, WCMemoryStatPlugin has a large performance loss after it is turned on. It is recommended to turn it on as needed.
Set pluginListener
of the MatrixBuilder
object, implement the MatrixPluginListenerDelegate
// set delegate
MatrixBuilder *curBuilder = [[MatrixBuilder alloc] init];
curBuilder.pluginListener = <object conforms to MatrixPluginListenerDelegate>;
// MatrixPluginListenerDelegate
- (void)onInit:(id<MatrixPluginProtocol>)plugin;
- (void)onStart:(id<MatrixPluginProtocol>)plugin;
- (void)onStop:(id<MatrixPluginProtocol>)plugin;
- (void)onDestroy:(id<MatrixPluginProtocol>)plugin;
- (void)onReportIssue:(MatrixIssue *)issue;
Each plugin added to MatrixBuilder
will call back the corresponding event via pluginListener
.
Important: Get the monitoring data of the Matrix via onReportIssue:
, the data format info reference to Matrix for iOS/macOS Data Format Description
At this point, Matrix has been integrated into the app and is beginning to collect crash, lag, and out-of-memory data. If you still have questions, check out the example: samples/sample-apple/MatrixDemo
.
-
APK Checker:
Analyse the APK package, give suggestions of reducing the APK's size; Compare two APK and find out the most significant increment on size
-
Resource Canary:
Detect the activity leak and bitmap duplication basing on WeakReference and Square Haha
-
Trace Canary:
FPS Monitor, Startup Performance, UI-Block / Slow Method Detection
-
SQLite Lint:
Evaluate the quality of SQLite statement automatically by using SQLite official tools
-
IO Canary:
Detect the file IO issues, including performance of file IO and closeable leak
- Easy-to-use. Matrix provides a JAR tool, which is more convenient to apply to your integration systems.
- More features. In addition to APK Analyzer, Matrix find out the R redundancies, the dynamic libraries statically linked STL, unused resources, and supports custom checking rules.
- Visual Outputs. supports HTML and JSON outputs.
- Separated detection and analysis. Make possible to use in automated test and in release versions (monitor only).
- Pruned Hprof. Remove the useless data in hprof and easier to upload.
- Detection of duplicate bitmap.
- High performance. Dynamically modify bytecode at compile time, record function cost and call stack with little performance loss.
- Accurate call stack of ui-block. Provide informations such as call stack, function cost, execution times to solve the problem of ui-block quickly.
- Non-hack. High compatibility to Android versions.
- More features. Automatically covers multiple fluency indicators such as ui-block, startup time, activity switching, slow function detection.
- Easy-to-use. Non-invasive.
- High applicability. Regardless of the amount of data, you can discover SQLite performance problems during development and testing.
- High standards. Detection algorithms based on best practices, make SQLite statements to the highest quality.
- May support multi-platform. Implementing in C++ makes it possible to support multi-platform.
- Easy-to-use. Non-invasive.
- More feature. Including performance of file IO and closeable leak.
- Compatible with Android P.
- Configure
MATRIX_VERSION
in gradle.properties.
MATRIX_VERSION=0.6.0
- Add
matrix-gradle-plugin
in your build.gradle:
dependencies {
classpath ("com.tencent.matrix:matrix-gradle-plugin:${MATRIX_VERSION}") { changing = true }
}
- Add dependencies to your app/build.gradle.
dependencies {
implementation group: "com.tencent.matrix", name: "matrix-android-lib", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-android-commons", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-trace-canary", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-resource-canary-android", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-resource-canary-common", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-io-canary", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-sqlite-lint-android-sdk", version: MATRIX_VERSION, changing: true
}
apply plugin: 'com.tencent.matrix-plugin'
matrix {
trace {
enable = true //if you don't want to use trace canary, set false
baseMethodMapFile = "${project.buildDir}/matrix_output/Debug.methodmap"
blackListFile = "${project.projectDir}/matrixTrace/blackMethodList.txt"
}
}
- Implement
PluginListener
to receive data processed by Matrix.
public class TestPluginListener extends DefaultPluginListener {
public static final String TAG = "Matrix.TestPluginListener";
public TestPluginListener(Context context) {
super(context);
}
@Override
public void onReportIssue(Issue issue) {
super.onReportIssue(issue);
MatrixLog.e(TAG, issue.toString());
//add your code to process data
}
}
- Implement
DynamicConfig
to change parameters of Matrix.
public class DynamicConfigImplDemo implements IDynamicConfig {
public DynamicConfigImplDemo() {}
public boolean isFPSEnable() { return true;}
public boolean isTraceEnable() { return true; }
public boolean isMatrixEnable() { return true; }
public boolean isDumpHprof() { return false;}
@Override
public String get(String key, String defStr) {
//hook to change default values
}
@Override
public int get(String key, int defInt) {
//hook to change default values
}
@Override
public long get(String key, long defLong) {
//hook to change default values
}
@Override
public boolean get(String key, boolean defBool) {
//hook to change default values
}
@Override
public float get(String key, float defFloat) {
//hook to change default values
}
}
- Init Matrix in the
onCreate
of your application.
Matrix.Builder builder = new Matrix.Builder(application); // build matrix
builder.patchListener(new TestPluginListener(this)); // add general pluginListener
DynamicConfigImplDemo dynamicConfig = new DynamicConfigImplDemo(); // dynamic config
// init plugin
IOCanaryPlugin ioCanaryPlugin = new IOCanaryPlugin(new IOConfig.Builder()
.dynamicConfig(dynamicConfig)
.build());
//add to matrix
builder.plugin(ioCanaryPlugin);
//init matrix
Matrix.init(builder.build());
// start plugin
ioCanaryPlugin.start();
For more Matrix configurations, look at the sample.
Note: You can get more about Matrix output at the wiki The output of Matrix;
APK Checker can run independently in Jar (matrix-apk-canary-0.6.0.jar) mode, usage:
java -jar matrix-apk-canary-0.6.0.jar
Usages:
--config CONFIG-FILE-PATH
or
[--input INPUT-DIR-PATH] [--apk APK-FILE-PATH] [--unzip APK-UNZIP-PATH] [--mappingTxt MAPPING-FILE-PATH] [--resMappingTxt RESGUARD-MAPPING-FILE-PATH] [--output OUTPUT-PATH] [--format OUTPUT-FORMAT] [--formatJar OUTPUT-FORMAT-JAR] [--formatConfig OUTPUT-FORMAT-CONFIG (json-array format)] [Options]
Options:
-manifest
Read package info from the AndroidManifest.xml.
-fileSize [--min DOWN-LIMIT-SIZE (KB)] [--order ORDER-BY ('asc'|'desc')] [--suffix FILTER-SUFFIX-LIST (split by ',')]
Show files whose size exceed limit size in order.
-countMethod [--group GROUP-BY ('class'|'package')]
Count methods in dex file, output results group by class name or package name.
-checkResProguard
Check if the resguard was applied.
-findNonAlphaPng [--min DOWN-LIMIT-SIZE (KB)]
Find out the non-alpha png-format files whose size exceed limit size in desc order.
-checkMultiLibrary
Check if there are more than one library dir in the 'lib'.
-uncompressedFile [--suffix FILTER-SUFFIX-LIST (split by ',')]
Show uncompressed file types.
-countR
Count the R class.
-duplicatedFile
Find out the duplicated resource files in desc order.
-checkMultiSTL --toolnm TOOL-NM-PATH
Check if there are more than one shared library statically linked the STL.
-unusedResources --rTxt R-TXT-FILE-PATH [--ignoreResources IGNORE-RESOURCES-LIST (split by ',')]
Find out the unused resources.
-unusedAssets [--ignoreAssets IGNORE-ASSETS-LIST (split by ',')]
Find out the unused assets file.
-unstrippedSo --toolnm TOOL-NM-PATH
Find out the unstripped shared library file.
Learn more about Matrix-APKChecker
Any problem?
- Learn more from Sample
- Source Code
- Wiki & FAQ
- Contact us for help
If you are interested in contributing, check out the CONTRIBUTING.md, also join our Tencent OpenSource Plan.
Matrix is under the BSD license. See the LICENSE file for details
Matrix 是一款微信研发并日常使用的应用性能接入框架,支持iOS, macOS和Android。 Matrix 通过接入各种性能监控方案,对性能监控项的异常数据进行采集和分析,输出相应的问题分析、定位与优化建议,从而帮助开发者开发出更高质量的应用。
当前工具监控范围包括:崩溃、卡顿和爆内存,包含以下两款插件:
-
WCCrashBlockMonitorPlugin: 基于 KSCrash 框架开发,具有业界领先的卡顿堆栈捕获能力,同时兼备崩溃捕获能力。
-
WCMemoryStatPlugin: 一款性能优化到极致的爆内存监控工具,能够全面捕获应用爆内存时的内存分配以及调用堆栈情况。
- 接入简单,代码无侵入
- 通过检查 Runloop 运行状态判断应用是否卡顿,同时支持 iOS/macOS 平台
- 增加耗时堆栈提取,卡顿线程快照日志中附加最近时间最耗时的主线程堆栈
- 在应用运行期间获取对象存活以及相应的堆栈信息,在检测到应用爆内存时进行上报
- 使用平衡二叉树存储存活对象,使用 Hash Table 存储堆栈,将性能优化到极致
-
通过 Cocoapods 安装
- 先安装 CocoaPods;
- 通过 pod repo update 更新 matrix 的 Cocoapods 版本;
- 在 Podfile 对应的 target 中,添加 pod 'matrix-wechat',并执行 pod install;
- 在项目中使用 Cocoapods 生成的 .xcworkspace运行工程;
- 在你的代码文件头引入头文件 #import <Matrix/Matrix.h>,就可以接入微信的性能探针工具了!
-
通过静态库安装
- 获取 Matrix 源码;
- 打开命令行,在
matrix/matrix-iOS
代码目录下执行make
进行编译生成静态库;编译完成后,iOS 平台的库在matrix/matrix-iOS/build_ios
目录下,macOS 平台的库在matrix/matrix-iOS/build_macos
目录下; - 工程引入静态库:
- iOS 平台:使用
matrix/matrix-iOS/build_ios
路径下的Matrix.framework
,将Matrix.framework
以静态库的方式引入工程; - macOS 平台:使用
matrix/matrix-iOS/build_macos
路径下的Matrix.framework
,将Matrix.framework
以静态库的方式引入工程。
- 添加头文件
#import <Matrix/Matrix.h>
,就可以接入微信的性能探针工具了!
在以下地方:
- 程序
main
函数入口; AppDelegate
中的application:didFinishLaunchingWithOptions:
;- 或者其他应用启动比较早的时间点。
添加类似如下代码,启动插件:
#import <Matrix/Matrix.h>
Matrix *matrix = [Matrix sharedInstance];
MatrixBuilder *curBuilder = [[MatrixBuilder alloc] init];
curBuilder.pluginListener = self; // pluginListener 回调 plugin 的相关事件
WCCrashBlockMonitorPlugin *crashBlockPlugin = [[WCCrashBlockMonitorPlugin alloc] init];
[curBuilder addPlugin:crashBlockPlugin]; // 添加卡顿和崩溃监控
WCMemoryStatPlugin *memoryStatPlugin = [[WCMemoryStatPlugin alloc] init];
[curBuilder addPlugin:memoryStatPlugin]; // 添加内存监控功能
[matrix addMatrixBuilder:curBuilder];
[crashBlockPlugin start]; // 开启卡顿和崩溃监控
// [memoryStatPlugin start];
// 开启内存监控,注意 memoryStatPlugin 开启之后对性能损耗较大,建议按需开启
设置 MatrixBuilder 对象中的 pluginListener,实现 MatrixPluginListenerDelegate。
// 设置 delegate
MatrixBuilder *curBuilder = [[MatrixBuilder alloc] init];
curBuilder.pluginListener = <一个遵循 MatrixPluginListenerDelegate 的对象>;
// MatrixPluginListenerDelegate
- (void)onInit:(id<MatrixPluginProtocol>)plugin;
- (void)onStart:(id<MatrixPluginProtocol>)plugin;
- (void)onStop:(id<MatrixPluginProtocol>)plugin;
- (void)onDestroy:(id<MatrixPluginProtocol>)plugin;
- (void)onReportIssue:(MatrixIssue *)issue;
各个添加到 MatrixBuilder 的 plugin 会将对应的事件通过 pluginListener 回调。
重要:通过 onReportIssue:
获得 Matrix 处理后的数据,监控数据格式详见:Matrix for iOS/macOS 数据格式说明
至此,Matrix 已经集成到应用中并且开始收集崩溃、卡顿和爆内存数据,如仍有疑问,请查看示例:samples/sample-apple/MatrixDemo
。
Matrix-android 当前监控范围包括:应用安装包大小,帧率变化,启动耗时,卡顿,慢方法,SQLite 操作优化,文件读写,内存泄漏等等。
- APK Checker: 针对 APK 安装包的分析检测工具,根据一系列设定好的规则,检测 APK 是否存在特定的问题,并输出较为详细的检测结果报告,用于分析排查问题以及版本追踪
- Resource Canary: 基于 WeakReference 的特性和 Square Haha 库开发的 Activity 泄漏和 Bitmap 重复创建检测工具
- Trace Canary: 监控界面流畅性、启动耗时、页面切换耗时、慢函数及卡顿等问题
- SQLite Lint: 按官方最佳实践自动化检测 SQLite 语句的使用质量
- IO Canary: 检测文件 IO 问题,包括:文件 IO 监控和 Closeable Leak 监控
与常规的 APM 工具相比,Matrix 拥有以下特点:
- 具有更好的可用性:JAR 包方式提供,更方便应用到持续集成系统中,从而追踪和对比每个 APK 版本之间的变化
- 更多的检查分析功能:除具备 APKAnalyzer 的功能外,还支持统计 APK 中包含的 R 类、检查是否有多个动态库静态链接了 STL 、搜索 APK 中包含的无用资源,以及支持自定义检查规则等
- 输出的检查结果更加详实:支持可视化的 HTML 格式,便于分析处理的 JSON ,自定义输出等等
- 分离了检测和分析部分,便于在不打断自动化测试的前提下持续输出分析后的检测结果
- 对检测部分生成的 Hprof 文件进行了裁剪,移除了大部分无用数据,降低了传输 Hprof 文件的开销
- 增加了重复 Bitmap 对象检测,方便通过减少冗余 Bitmap 数量,降低内存消耗
- 编译期动态修改字节码, 高性能记录执行耗时与调用堆栈
- 准确的定位到发生卡顿的函数,提供执行堆栈、执行耗时、执行次数等信息,帮助快速解决卡顿问题
- 自动涵盖卡顿、启动耗时、页面切换、慢函数检测等多个流畅性指标
- 接入简单,代码无侵入
- 数据量无关,开发、测试阶段即可发现SQLite性能隐患
- 检测算法基于最佳实践,高标准把控SQLite质量*
- 底层是 C++ 实现,支持多平台扩展
- 接入简单,代码无侵入
- 性能、泄漏全面监控,对 IO 质量心中有数
- 兼容到 Android P
- 在你项目根目录下的 gradle.properties 中配置要依赖的 Matrix 版本号,如:
MATRIX_VERSION=0.6.0
- 在你项目根目录下的 build.gradle 文件添加 Matrix 依赖,如:
dependencies {
classpath ("com.tencent.matrix:matrix-gradle-plugin:${MATRIX_VERSION}") { changing = true }
}
- 接着,在 app/build.gradle 文件中添加 Matrix 各模块的依赖,如:
dependencies {
implementation group: "com.tencent.matrix", name: "matrix-android-lib", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-android-commons", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-trace-canary", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-resource-canary-android", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-resource-canary-common", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-io-canary", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-sqlite-lint-android-sdk", version: MATRIX_VERSION, changing: true
}
apply plugin: 'com.tencent.matrix-plugin'
matrix {
trace {
enable = true //if you don't want to use trace canary, set false
baseMethodMapFile = "${project.buildDir}/matrix_output/Debug.methodmap"
blackListFile = "${project.projectDir}/matrixTrace/blackMethodList.txt"
}
}
- 实现 PluginListener,接收 Matrix 处理后的数据, 如:
public class TestPluginListener extends DefaultPluginListener {
public static final String TAG = "Matrix.TestPluginListener";
public TestPluginListener(Context context) {
super(context);
}
@Override
public void onReportIssue(Issue issue) {
super.onReportIssue(issue);
MatrixLog.e(TAG, issue.toString());
//add your code to process data
}
}
- 实现动态配置接口, 可修改 Matrix 内部参数. 在 sample-android 中 我们有个简单的动态接口实例DynamicConfigImplDemo.java, 其中参数对应的 key 位于文件 MatrixEnum中, 摘抄部分示例如下:
public class DynamicConfigImplDemo implements IDynamicConfig {
public DynamicConfigImplDemo() {}
public boolean isFPSEnable() { return true;}
public boolean isTraceEnable() { return true; }
public boolean isMatrixEnable() { return true; }
public boolean isDumpHprof() { return false;}
@Override
public String get(String key, String defStr) {
//hook to change default values
}
@Override
public int get(String key, int defInt) {
//hook to change default values
}
@Override
public long get(String key, long defLong) {
//hook to change default values
}
@Override
public boolean get(String key, boolean defBool) {
//hook to change default values
}
@Override
public float get(String key, float defFloat) {
//hook to change default values
}
}
- 选择程序启动的位置对 Matrix 进行初始化,如在 Application 的继承类中, Init 核心逻辑如下:
Matrix.Builder builder = new Matrix.Builder(application); // build matrix
builder.patchListener(new TestPluginListener(this)); // add general pluginListener
DynamicConfigImplDemo dynamicConfig = new DynamicConfigImplDemo(); // dynamic config
// init plugin
IOCanaryPlugin ioCanaryPlugin = new IOCanaryPlugin(new IOConfig.Builder()
.dynamicConfig(dynamicConfig)
.build());
//add to matrix
builder.plugin(ioCanaryPlugin);
//init matrix
Matrix.init(builder.build());
// start plugin
ioCanaryPlugin.start();
至此,Matrix就已成功集成到你的项目中,并且开始收集和分析性能相关异常数据,如仍有疑问,请查看 示例.
PS: Matrix 分析后的输出字段的含义请查看 Matrix 输出内容的含义解析
APK Check 以独立的 jar 包提供 (matrix-apk-canary-0.6.0.jar),你可以运行:
java -jar matrix-apk-canary-0.6.0.jar
查看 Usages 来使用它。
Usages:
--config CONFIG-FILE-PATH
or
[--input INPUT-DIR-PATH] [--apk APK-FILE-PATH] [--unzip APK-UNZIP-PATH] [--mappingTxt MAPPING-FILE-PATH] [--resMappingTxt RESGUARD-MAPPING-FILE-PATH] [--output OUTPUT-PATH] [--format OUTPUT-FORMAT] [--formatJar OUTPUT-FORMAT-JAR] [--formatConfig OUTPUT-FORMAT-CONFIG (json-array format)] [Options]
Options:
-manifest
Read package info from the AndroidManifest.xml.
-fileSize [--min DOWN-LIMIT-SIZE (KB)] [--order ORDER-BY ('asc'|'desc')] [--suffix FILTER-SUFFIX-LIST (split by ',')]
Show files whose size exceed limit size in order.
-countMethod [--group GROUP-BY ('class'|'package')]
Count methods in dex file, output results group by class name or package name.
-checkResProguard
Check if the resguard was applied.
-findNonAlphaPng [--min DOWN-LIMIT-SIZE (KB)]
Find out the non-alpha png-format files whose size exceed limit size in desc order.
-checkMultiLibrary
Check if there are more than one library dir in the 'lib'.
-uncompressedFile [--suffix FILTER-SUFFIX-LIST (split by ',')]
Show uncompressed file types.
-countR
Count the R class.
-duplicatedFile
Find out the duplicated resource files in desc order.
-checkMultiSTL --toolnm TOOL-NM-PATH
Check if there are more than one shared library statically linked the STL.
-unusedResources --rTxt R-TXT-FILE-PATH [--ignoreResources IGNORE-RESOURCES-LIST (split by ',')]
Find out the unused resources.
-unusedAssets [--ignoreAssets IGNORE-ASSETS-LIST (split by ',')]
Find out the unused assets file.
-unstrippedSo --toolnm TOOL-NM-PATH
Find out the unstripped shared library file.
由于篇幅影响,此次不再赘述,我们在 Matrix-APKChecker 中进行了详细说明。
还有其他问题?
关于 Matrix 分支管理、issue 以及 pr 规范,请阅读 Matrix Contributing Guide。
腾讯开源激励计划 鼓励开发者的参与和贡献,期待你的加入。
Matrix is under the BSD license. See the LICENSE file for details