[Gradle翻译]图形、Gradle和Talaiot

197 阅读9分钟

本文由 简悦SimpRead 转码,原文地址 proandroiddev.com

在介绍了Talaiot的基础知识后,又介绍了默认的发布器之一InfluxDbPublisher, n......

image.png

在介绍了Talaiot的基础知识和默认的发布器之一InfluxDbPublisher之后,现在是深入了解最近在Talaiot 0.2.0发布的新发布器系列的时刻:TaskDependencyGraphPublishers。

你还记得图论吗?也许你还记得大学里的一些概念,或者你曾为Google或Facebook准备过面试。Dijkstra、DFS或BFS是其中的一些基本概念。然而,这仅仅是冰山一角。

在数学中,图论是对图的研究,它是用来为对象建模的数学结构。在计算机科学中,图被用来表示通信网络、数据组织、计算设备,但它在其他分支如生物学、化学或语言学中有其他应用。

一个图可以表示为一个有序的对,如G=(V,E)其中V是顶点(节点),E是边(关系)。我们有不同类型的图,取决于不同的属性,如边的方向、分配给每条边的权重或图是否包含循环。

图无处不在,从垃圾收集器/内存管理到搜索引擎中的网页排名算法(PageRank),当然,我们在Android/Kotlin世界中也有例子。

例如,在我们喜爱的UI测试框架Espresso中,有一个TreeIterables类,用作迭代树形结构项目的实用方法。在这种情况下,树状结构将是我们被测试的UI视图的视图层次结构。该类包括DFS和BFS静态遍历方法。

image.png

发现的一个用法是在PositionAsserions中,用于断言UI上元素的相对位置。

Iterables.filter(breadthFirstViewTraversal(root),viewPredicate)
         .iterator()

在上一次Kotlin Konf中,Nikolay Igotti的精彩演讲 "Kotlin/Native Concurrency Model "提供了一个更高级的例子。在这次会议中,Nikolay深入探讨了Kotlin Native平台的并发问题和设计原则。在谈到不变性的其中一节中,他暴露了在复杂的图对象关系中运行复杂的可达性算法的问题。解决这个问题的方法之一是应用图论原理:任何对象图都可以浓缩为一个有向无环图,其较强的连接部分可以避免对整个图运行可达性算法。

image.png

www.youtube.com/watch?v=nw6…

Gradle中的图

Gradle是一个基于任务的构建系统。一个Task是一个构建的工作单元,例如,有些任务我们非常熟悉:compileKotlintestassembleDebug。一个任务可能依赖于其他任务,也可能被安排在另一个任务之后运行。Gradle确保所有任务的依赖关系都在其所有的依赖关系之后执行。所有任务和依赖关系的组成被表示为一个有向无环图(DAG)。

如果我们以默认的Java Plugin为例,我们可以注意到在执行build任务时包含的任务和它们的依赖关系。

image.png

docs.gradle.org/current/use…

jar任务只有在classes任务完成后才会被执行。这是有道理的,因为我们不想在前一个任务完成之前打包由编译器生成的类,同样,我们可以注意到我们需要先执行compileJavaprocessResources任务来执行classes任务。

也许你想知道我们如何知道哪些任务是依赖于某个特定的任务。如果我们想给一个给定的任务添加一个依赖关系,我们可以使用:Task.dependOn(java.lang.Object[]),但是不同的插件中包含的任务呢?

对于每个任务,在评估阶段,Gradle为构建组装任务执行图。这发生在所有项目被评估之后,任何任务执行开始之前。这些信息可以通过主任务接口的TaskDependency getTaskDependencies()来访问。

作为TaskDepdency类型。

image.png

在这里,Talaiot正在收集和提供一个给定任务的依赖信息。这些数据将被提供给后来被发布者使用的主要聚合任务实体。

TaskDependencyGraphPublisher

这是0.2.0版本中发布的新的发布器。 它包括三种不同的输出/发布器和额外的配置,根据你对CI/本地构建的要求,包含/避免执行。

基本配置是。

TaskDependencyGraphPublisher中包含的默认发布者是HtmlPublisher、DotPublisher和GexfPublisher。

一旦构建完成,Talaiot将在${project.rootDit}/$TALAIOT_OUTPUT_DIR中创建通过发布者配置定义的文件。

image.png

HtmlPublisher

第一个包含的Publisher是HtmlPublisher,它使用了库vis.js(感谢warat wongmaneekitPanjamapong Sermsawatsri的推荐)。它有助于显示任务的依赖性图。

image.png

Kotlin模块的简单DAG

Publisher对于低密度的图来说效果很好,这意味着小模块或一个模块的特定任务。在高密度图的情况下,可视化变得更加困难。

image.png

然而,由于该库,你可以缩放和分组不同的任务。结果是按模块分类的。

DotPublisher

DOT是套件GraphViz的文本文件格式。它有一个流畅的语法来描述网络数据,包括子图和元素的出现。

digraph graphname {
    assemble -> compileJava -> compileKotlin;
    compileJava -> classes;
}

现在的用法已经非常广泛了,许多插件和工具都在使用这种格式,例如可以查看Vinay Shetty这篇文章,他解释了为Tinder的有限状态机的Kotlin DSL State Machine Library创建的插件,用来表示状态机图。

如果你喜欢检查该格式的不同可能性,GraphViz提供了一个网络版来开始玩。

让我们回到Publisher,一旦我们完成了构建,并使用DotPublisher对Talaiot进行了配置,就会产生一个带有任务依赖图信息的png。

image.png

github.com/cdsap/Kotli… 的核心-域组合

发布者使用graphviz-java来创建graphviz模型并将其转换成漂亮的图形。

GexfPublisher

GEXF格式是一种用于描述复杂网络结构的语言。它开始于2007年的Gephi项目,是一个开放的图形Viz平台。一个简单的图将是。

<?xml version="1.0" encoding="UTF-8"?>
<gexf xmlns="http://www.gexf.net/1.2draft" version="1.3">
    <meta>
        <creator>Talaiot</creator>
        <description>Graph Dependency</description>
    </meta>
    <graph mode="static" defaultedgetype="directed">
      <node id="0" label="compileKotlin"/>
      <node id="1" label="compileJava"/>
      <edge id="0" source="1" target="0" />
    </graph>
</gexf>

在这里我们定义了图的主要组成部分节点作为节点图的子节点。此外,格式规范允许你为图定义更多的属性。Talaiot正在提供额外的属性,模块和缓存。

<attributes class="node">
   <attribute id="0" title="module" type="string"/>
   <attribute id="1" title="cached" type="boolean">
         <default>false</default>
    </attribute>
</attributes>
<node id="4" label="preDebugBuild">
    <attvalues>
        <attvalue for="0" value=":core"/>
        <attvalue for="1" value="false"/>
    </attvalues>
</node>

为了实现数据的可视化,我们将使用Gephi

image.png

这是一个很好的工具,可以用所提供的数据应用过滤器、布局和不同的统计数据。你有三个主要组成部分。

  • 概述。你可以可视化地将不同的布局应用到所提供的数据上。此外,你还可以应用过滤器
  • 数据实验室。你将在概览中以表格的形式应用信息,在这里你可以合并、导出和过滤信息。
  • 预览。对当前工作区的结果进行可视化和导出。

使用案例。GexfPublisher与Plaid应用程序

现在我们要探索GexfPublisher的更多选项以及与Gephi的整合。在这个例子中,我们将使用Google Plaid的资源库。

github.com/android/pla…

Plaid是作为Android中材料设计在实际应用中的展示而编写的。后来,Plaid被用来展示与Android平台上的常见问题有关的最佳实践:架构、测试和模块化。

一旦我们拉出资源库并配置了Talaiot(使用taskGraphDependencyPublisher与gexf = true),我们需要执行构建assembleDebug。一旦构建完成,.gexf文件将被生成。

当我们在Gephi中打开该文件时,会出现一个对话框,其中提供了图形的基本信息。

image.png

我们正在加载一个有335个节点和1106个边的有向图。

正如我们之前提到的,我们包括自定义属性模块和缓存任务。在Gephi的帮助下,我们将使用这些数据对图形进行分组,并有更好的可视化效果。

image.png

将属性应用到图表中。

image.png

Plaid的任务依赖图与Force Atlas2分布的关系

我们可以注意到一个正态分布,一些任务与不同的模块相邻。测试模块(:test-shared)比其他模块更独立。

下一个例子将使用结合两个过滤器,但在这种情况下,只有:app模块的任务和那些被缓存的任务。

image.png

Gephi还包括对图形应用不同指标的可能性,这些指标用不同的算法来分析网络、节点和边缘,让我们看看其中的一些指标。

度数中心性

衡量一个节点的关系数量,这种关系可以是传入或传出的。度中心度算法可以帮助我们找到图中的热门节点。对于Plaid项目中的 "assembleDebug",我们有这样的整体分布。

image.png

在数据实验室部分,我们可以用图中应用的算法的结果来探索数据。

image.png

加权度

我们注意到:app模块的generateDebugFeatureTransitiveDep任务包含最高的值(50/2)。如果我们把总度数分解为in-degree和out-degree,结果是。

image.png

加权的入站度。与总学位的结果类似,以建设前的配置任务为主

image.png

加权传出度。编译和打包任务是影响较大的节点

同时,我们可以在图形的可视化中应用一个过滤器,例如这里的加权度的值高于27。

image.png

Betweenness Centrality

Betweenness算法是一种检测一个节点对图中信息流的影响程度的方法。首先计算每对节点之间的最短路径。每个节点收到一个分数,基于通过该节点的这些最短路径的数量。最经常位于这些最短路径上的节点将有更高的介于中心性得分。

在Plaid项目中,我们有这样的分布。

image.png

另外,在数据实验室的信息。

image.png

这些信息显示了放置在":core "和":app "模块上的任务的强烈影响。这些任务在传入度社区结果上显示出之前的高价值。

每当我们在图上应用不同的算法时,数据实验室中就会有更多的数据。这里是:core:assembleDebug的结果,意味着执行:core:bypass模块。

proandroiddev.com/media/f7f46…

检查完整的构建输出这里

感谢Gephi,我们可以更深入地对我们的构建进行图谱分析。BFS/DFS/最短路径理论仅仅是真正的图论的开始。如果你想探索更多关于图算法的知识,可以看看这本最近出版的书。

image.png

neo4j.com/graph-algor…

最后的话

图论是惊心动魄的! 在我们的案例中,我们可以利用图论的知识来更好地理解Gradle的构建。例如,了解哪些任务支持更重要的责任,或者确定在哪些情况下CPU的数量会对任务的并行执行产生真正的影响。

在Talaiot的新版本(0.2.0)中,你可以用构建系统的任务依赖图来生成你的dot/html/gexf文件。我们希望在未来探索更多与Neo4J或Spark的高级集成,并探索HtmlPlublisher的不同可视化技术,例如按模块聚类。

谢谢你的阅读,记住Talaiot是开源的,你可以为开发做出贡献和帮助。

github.com/cdsap/Talai…


www.deepl.com 翻译