精华内容
下载资源
问答
  • Ruby代码(轨道或其他代码)的可视化工具,它分析您的代码并提取模块定义和使用的类/模块,并使用D3将所有这些信息呈现为有向力图。 注意: 从2.0.0版本开始,该项目不再是http服务器,它会生成一个自包含HTML文件...
  • 分析你的代码,并提取模块的定义和使用的类/模块,并使用D3呈现所有这些信息为有向力图。
  • 扫描所有源文件,使用cpp(The C Preprocessor)过滤掉注释后,使用sed提取#include,生成依赖条目 将所有依赖条目拼成.dot文件,然后使用graphviz中的dot工具将.dot文件转为.png图片 代码 代码的Github仓库为dep,...

    流程

    流程并不复杂:

    1. 使用find命令搜索指定目录所有C/C++源文件
    2. 扫描所有源文件,使用cpp(The C Preprocessor)过滤掉注释后,使用sed提取#include,生成依赖条目
    3. 将所有依赖条目拼成.dot文件,然后使用graphviz中的dot工具将.dot文件转为.png图片

    代码

    代码的Github仓库为dep,为了方便~~(以及凑字数)~~放在这里一份:

    #!/bin/bash
    #################################################################################
    # MIT License
    # 
    # Copyright (c) 2020 Jia Lihong
    # 
    # Permission is hereby granted, free of charge, to any person obtaining a copy
    # of this software and associated documentation files (the "Software"), to deal
    # in the Software without restriction, including without limitation the rights
    # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    # copies of the Software, and to permit persons to whom the Software is
    # furnished to do so, subject to the following conditions:
    # 
    # The above copyright notice and this permission notice shall be included in all
    # copies or substantial portions of the Software.
    # 
    # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    # SOFTWARE.
    #################################################################################
    #
    # Usage: $(basename $0) [OPTION]... DIRECTORY
    # Scan and visualize C/C++ source file dependencies.
    # 
    # Options:
    #   -h              show help
    #   -e              show extern dependencies
    #   -o FILENAME     specify the output png name, default is "dep.png"
    #
    err() {
        echo "ERROR: $*" >&2
        exit 1
    }
    display_help() {
        echo "Usage: $(basename "$0") [OPTION]... DIRECTORY"
        echo "Scan and visualize C/C++ source file dependencies."
        echo ""
        echo "Options:"
        echo "  -h              show help"
        echo "  -e              show extern dependencies"
        echo "  -o FILENAME     specify the output png name, default is \"dep.png\""
        echo ""
    }
    contains() {
        local result="false"
        local grep_result
        grep_result="$(echo "$1" | grep "^$2$")"
        if [ -n "${grep_result}" ]; then
            result="true"
        fi
        echo "${result}"
    }
    check_dot() {
        if ! type "dot" >/dev/null 2>&1; then
            err "graphviz is not installed"
        fi
    }
    main() {
        DISPLAY_HELP="false"
        SHOW_EXTERN="false"
        OUTPUT_NAME="dep.png"
        while getopts "eho:" opt
        do
            case "$opt" in
            e) SHOW_EXTERN="true" ;;
            h) DISPLAY_HELP="true" ;;
            o) OUTPUT_NAME="${OPTARG}" ;;
            *) echo "Unknown option $opt"; exit 1 ;;
            esac
        done
        readonly DISPLAY_HELP
        readonly SHOW_EXTERN
        readonly OUTPUT_NAME
        if [[ "${DISPLAY_HELP}" == "true" ]]; then
            display_help
            exit 0
        fi
        check_dot
        shift $(( OPTIND - 1))
        if [ -n "$1" ]; then
            readonly DIR="$1"
        else
            echo "Missing directory"
            display_help
            exit 1
        fi
        readonly NEWLINE=$'\n'
        echo "SHOW_EXTERN: ${SHOW_EXTERN}"
        echo "OUTPUT_NAME: ${OUTPUT_NAME}"
        echo "DIR = ${DIR}"
        readonly FILEPATH_LIST="$(find "${DIR}" -regex ".*\.\(h\|hxx\|hpp\|hh\|c\|cxx\|cpp\|cc\)")"
        readonly FILENAME_LIST="$(echo "${FILEPATH_LIST}" | awk -F'/' '{print $NF}')"
        readonly FILE_NUM="$(echo "${FILEPATH_LIST}" | wc -l)"
        extern_list=""
        dep_inner_list=""
        dep_extern_list=""
        echo "FILE_NUM = ${FILE_NUM}"
        i=0
        for filepath in ${FILEPATH_LIST}; do
            i="$(( "$i" + 1 ))"
            echo -n "[$i/${FILE_NUM}] Scanning ${filepath} ... "
            filename="$(echo "${filepath}" | awk -F'/' '{print $NF}')"
            include_list="$(cpp -fpreprocessed "${filepath}" | sed -ne 's/^\s*#include\s*<\(.*\)>\s*$/\1/p; s/^\s*#include\s*\"\(.*\)\"\s*$/\1/p')"
            for include_path in ${include_list}; do
                include_name="$(echo "${include_path}" | awk -F'/' '{print $NF}')"
                if [[ "$(contains "${FILENAME_LIST}" "${include_name}")" == "false" ]]; then
                    dep_extern_list="${dep_extern_list}${NEWLINE}\"${filename}\" -> \"${include_name}\""
                    if [[ "$(contains "${extern_list}" "${include_name}")" == "false" ]]; then
                        extern_list="${extern_list}${NEWLINE}${include_name}"
                    fi
                else
                    dep_inner_list="${dep_inner_list}${NEWLINE}\"${filename}\" -> \"${include_name}\""
                fi
            done
            echo "done"
        done
        IFS=$'\n'
        echo -n "Generating .dot file ... "
        dot_result="digraph dep {"
        for filename in ${FILENAME_LIST}; do
            if [[ -n "${filename}" ]]; then
                dot_result="${dot_result}${NEWLINE}\"${filename}\";"
            fi
        done
        for dep in ${dep_inner_list}; do
            dot_result="${dot_result}${NEWLINE}${dep};"
        done
        if [[ "${SHOW_EXTERN}" == "true" ]]; then
            for filename in ${extern_list}; do
                if [[ -n "${filename}" ]]; then
                    dot_result="${dot_result}${NEWLINE}\"${filename}\" [color=red];"
                fi
            done
            for dep in ${dep_extern_list}; do
                dot_result="${dot_result}${NEWLINE}${dep};"
            done
        fi
        dot_result="${dot_result}${NEWLINE}}"
        echo "done"
        readonly TEMP_DOT="$(mktemp)"
        echo -n "Writing .dot file ... "
        echo "${dot_result}" > "${TEMP_DOT}"
        echo "done"
        echo -n "Generating .png file ... "
        dot -o "${OUTPUT_NAME}" -Tpng "${TEMP_DOT}"
        echo "done"
    }
    main "$@"
    

    用法

    Usage: dep.sh [OPTION]... DIRECTORY
    Scan and visualize C/C++ source file dependencies.
    
    Options:
      -e              show extern dependencies
      -h              show help
      -o FILENAME     specify the output png name, default is "dep.png"
    

    下面是一个样例工程的输出:

    在这里插入图片描述
    默认不输出对外部文件的依赖,如果指定了-e选项,则进行输出。

    在这里插入图片描述

    注意事项

    最好不要使用这个工具分析中大型项目(比如说超过50个源文件),一方面因为shell脚本比较慢,另一方面是最终输出的图片可读性会比较差。

    展开全文
  • 用于以各种方式处理可视化中的样式,分析或视觉差异的代码。 该代码是进行的学术项目的一部分,该项目是学术论文 ”的一部分。 本文提供了更多详细信息,但是该项目的核心是用户可以创建图表的 JSON规范以及支持...
  • 在LLVM中可视化代码结构

    千次阅读 2019-03-20 14:32:25
    在LLVM中可视化代码结构1. Abstract2. 调用图、控制和数据流2.1 调用图2.2 CFG(基本块)2.3 CFG & DFG(指令)2.4 指令2.5 Zeller’s Ex....本文概述了LLVM创建人类可读的代码结构可视化和相关依赖分析passes的功能...

    1. 摘要

    本文概述了LLVM创建人类可读的代码结构可视化和相关依赖分析passes的功能。
    程序代码示例(vector_sum)

    void vector_sum(int length, float * in1, float * in2, float * out){
    	for(int i = 0; i < length; i++)
    		out[i] = in1[i] + in2[i];
    }
    #include<malloc.h>
    #include<stdio.h>
    #include<stdlib.h>
    int main(int argc, char* argv[]){
    	if(argc != 2) return 1;
    	int length = atoi(argv[1]);
    	float* in1 = (float*)malloc(length * sizeof(float));
    	float* in2 = (float*)malloc(length * sizeof(float));
    	float* out = (float*)malloc(length * sizeof(float));
    	for(int i = 0; i < length; i++){
    		in1[i] = drand48();
    		in2[i] = drand48();
    	}
    	vector_sum(length, in1, in2, out);
    	printf("%f\n", out[length−1]);
    	return 0;
    }
    

    这个函数的LLVM IR (vector_sum)

    $ clang −emit − llvm example.c −O1 −S −o − | less
    define void @vector_sum ( i32 %length , float * nocapture readonly %in1 , float * nocapture readonly %in2 , float * nocapture %out ) #0 {
    entry :
    	%cmp9 = icmp sgt i32 %length , 0
    	br i1 %cmp9 , label %for.body , label %for.end
    	
    for.body :														; preds = %entry, %for.body
    	%indvars.iv = phi i64 [ %indvars.iv.next , %for.body ] , [ 0 , %entry ]
    	%arrayidx = getelementptr inbounds float * %in1 , i64 %indvars.iv
    	%0 = load float * %arrayidx , align 4 , ! tbaa ! 1
    	%arrayidx2 = getelementptr inbounds float * %in2 , i64 %indvars.iv
    	%1 = load float * %arrayidx2 , align 4 , ! tbaa ! 1
    	%add = fadd float %0 , %1
    	%arrayidx4 = getelementptr inbounds float * %out , i64 %indvars.iv
    	store float %add , float * %arrayidx4 , align 4 , ! tbaa ! 1
    	%indvars.iv.next = add nuw nsw i64 %indvars.iv , 1
    	%lftr.wideiv = trunc i64 %indvars.iv.next to i32
    	%exitcond = icmp eq i32 %lftr.wideiv , %length
    	br i1 %exitcond , label %for.end , label %for.body
    	
    for.end :														; preds = %for.body, %entry
    	ret void
    }
    

    2. 调用图、控制和数据流

    在LLVM中,从命令行可以得到两种形式的图:

    1. 调用图
    2. CFG(基本块)
    3. CFG & DFG(指令)
    2.1 调用图

    在这里插入图片描述

    2.2 CFG(基本块)

    在这里插入图片描述

    2.3 CFG & DFG(指令)

    在这里插入图片描述

    2.4 指令
    1. 调用图 —— 内置LLVM pass + dot
      $ clang −emit − llvm −S −c example . c −o − | opt −O1 | opt −dot − callgraph −o / dev / null && dot −Tpdf callgraph . dot −o callgraph . pdf
      
    2. CFG(基本块) —— 内置LLVM pass + dot
      $ clang −emit − llvm −S −c example . c −o − | opt −O1 | opt −dot − cfg −o / dev / null && dot −Tpdf cfg . vector_sum . dot −o cfg . vector_sum . pdf
      
    3. CFG & DFG(指令) —— 由Paul Sokolovsky编写的llvmpy脚本 + dot
      $ . / graph − llvm − ir . / example . ll && dot −Tpdf vector_sum . dot −o vector_sum . pdf
      
    2.5 Zeller’s Ex. 7.1 的 CFG & DFG
    /* fibo.c -- Fibonacci C program to be debugged */
    #include<stdio.h>
    int fib(int n){
    	int f, f0 = 1, f1 = 1;
    	while(n > 1){
    		n = n − 1;
    		f = f0 + f1;
    		f0 = f1;
    		f1 = f;
    	}
    	return f;
    }
    int main(){
    	int n = 9;
    	while(n > 0){
    		printf("fib(%d)=%dN", n, fib(n));
    		n = n − 1;
    	}
    	return 0;
    }
    

    注意,未初始化的int f变成了undef
    在这里插入图片描述

    3. 依赖分析Pass

    关注依赖关系的两个LLVM passes:

    1. 内存依赖分析
    2. 依赖分析

    两者都利用别名分析(Alias Analysis)来降低 O(n^2) 的强度。

    3.1 内存依赖分析
    • 功能齐全
    • 分析内存引用之间的依赖关系:
      • Clobber —— clobbers内存的指令,例如一个may-aliased store
      • Def —— 指令定义/生成所需的内存位置
      • NonLocal —— 在当前基本块之外(需要检查前一个块)
      • NonFuncLocal —— 在当前函数外部
    • 无可视化图形输出
    • 打印输出不是很清晰(如下)
    define void @vector_sum ( i32 %length , float * nocapture readonly %in1 , float * nocapture readonly %in2 , float * nocapture %out ) #0 {
    entry :
    	%cmp9 = icmp sgt i32 %length , 0
    	br i1 %cmp9 , label %for.body , label %for.end
    	
    for.body :									; preds = %entry, %for.body
    	%indvars.iv = phi i64 [ %indvars.iv.next , %for.body ] , [ 0 , %entry ]
    	%arrayidx = getelementptr inbounds float * %in1 , i64 %indvars.iv
    	%0 = load float * %arrayidx , align 4 , ! tbaa ! 1
    	%arrayidx2 = getelementptr inbounds float * %in2 , i64 %indvars.iv
    	%1 = load float * %arrayidx2 , align 4 , ! tbaa ! 1
    	%add = fadd float %0 , %1
    	%arrayidx4 = getelementptr inbounds float * %out , i64 %indvars.iv
    	store float %add , float * %arrayidx4 , align 4 , ! tbaa ! 1
    	%indvars.iv.next = add nuw nsw i64 %indvars.iv , 1
    	%lftr.wideiv = trunc i64 %indvars.iv.next to i32
    	%exitcond = icmp eq i32 %lftr.wideiv , %length
    	br i1 %exitcond , label %for.end , label %for.body
    
    for.end :									; preds = %for.body, %entry
    	ret void
    }
    

    内存依赖分析打印输出:

    $ clang −emit − llvm example.c −O1 −S −o − | opt −memdep −print−memdeps −o / dev / null
    Function vector_sum memory dependencies :
    
    		Unknown in block %for.body
    		Unknown in block %entry
    	%0 = load float * %arrayidx , align 4 , ! tbaa ! 1
    	
    		Unknown in block %for.body
    		Unknown in block %entry
    	%1 = load float * %arrayidx2 , align 4 , ! tbaa ! 1
    
    		Def from :	%1 = load float * %arrayidx2 , align 4 , ! tbaa ! 1
    	store float %add , float * %arrayidx4 , align 4 , ! tbaa ! 1
    

    为什么store只依赖于两次load中的一次?

    3.2 依赖分析
    • 进行中的工作
    • 在Goff, Kennedy, Tseng – PLDI 1991的“Practical Dependence Testing”之后,由Preston Briggs实现
    • 全面依赖分析:
      • Output —— 写后写
      • Flow (true) —— 写后读
      • Anti - 读后写
    • 无可视化图形输出
    展开全文
  • 代码可视化算法流程

    2014-02-17 12:01:00
    下面是代码可视化的算法流程: 收集代码元素的词频向量 词频向量的每一个元素是一个词的出现次数,而一个代码元素(类或函数)对应一个词频向量。词语从类名、函数名、函数代码之中提取。这一步听起来容易,做...

    这个是暂时的效果,一个点是一个类或者全局函数。高度场暗示依赖关系,高度高的会依赖高度低的。

     

     

    下面是代码可视化的算法流程:

    1. 收集代码元素的词频向量

    词频向量的每一个元素是一个词的出现次数,而一个代码元素(类或函数)对应一个词频向量。词语从类名、函数名、函数代码之中提取。这一步听起来容易,做起来难,因为要对代码做语法分析,而C++的语法是出名多变复杂的。当前主要是根据代码树来分析,代码树就是指一个工程有什么类,每个类有什么成员,每个函数又用了什么局部变量这样的层次关系。

     

      2.根据词频向量,做潜在语义分析(Latent Sematic Indexing, LSI)。

    把每个代码元素的词频向量排成一个矩阵。矩阵的每一行对应一个代码元素的词频向量,每一列对应一个词语在不同代码元素的出现次数。对此矩阵ASVD分解,A = UΣVT。

    矩阵U*Σ1/2的每一行表示一个文档与各个主题的相关程度。

    矩阵Σ1/2*VT 的每一列表示一个词语与各个主题的相关程度。

    于是,可以把文档、词语都用“主题空间”的点表示,如下图:

     

    图中红色点是一个词,蓝色点是一个文档,纵横轴分别表示两个主题。数据点的位置就表示这个词或文档蕴含的两个主题的强度。

    在实现中发现,文档稍微更改时(例如在类中添加一个变量),各个主题的奇异值相对大小会发生突变,但是U V值基本不变。

     

    LSI的第二步是,取前k个大的奇异值,其余的奇异值设为0,有些文章提到把最大的奇异值也忽略,因为它与文档的长度有关。之后重新构造出来的矩阵A’就去除了同义词和多义词的影响,这一点具体解释还不清楚。不过现在并不需要重新去构造A’,只是利用了U*Σ1/2 矩阵作为文档的特征向量(一行一个文档,一列一个主题,也就是特征)。利用特征向量的余弦度量文档的相似程度。

     

      3.降维

    LSI之后,文档的特征向量大概有几十维(现在取20),相比之前的词频向量(几百上千维)短多了,这样可以降低计算量。现在的问题是,想办法把这些向量降至二维,而且在文档发生改变时,尽可能保持降维结果的稳定。现在第一个目标是做到了,但是结果不太稳定。

     

    降维用到的办法称为MDSMultidimensional Scaling),实际上这是一大类算法的统称。MDS的输入是高维数据两两之间的相似度构成的方阵。其目的是,尽可能使得对于降维后的低维数据,其两两的相似度度量也跟原来的吻合。“相似度”可以是数据之间的欧氏距离、夹角余弦等等度量。

     

    最直接想到的是使得高维和低维数据彼此之间的欧氏距离尽可能吻合。根据这个目标,产生一类算法,称为Stress MDS,这类算法构造一个评分函数(称为 stress function),函数求每对数据的高低维欧氏距离差的平方和,算法的目标就是使得此函数最小,即:

     

    最小化这个函数有很多算法,但很多都难免收敛于局部最优。其中一个最简单的算法就是在每次迭代中,考虑所有点对,把过于远(低维相似度比高维小)的点对拉近(两个点向着对方靠近),把过于近的点对推远。Stress MDS还有一个共同缺点,就是对初始位置太敏感,不同的初始低维位置会导致不同的收敛结果。在实现中,似乎点数少的时候更敏感一些。

     

    由于对初始位置敏感,所以需要有一个确定的算法来计算初始位置。PCA是一种(就是取高维数据在前几个特征向量上的投影作为初始位置),另一种称为经典MDS,这种算法在相似度矩阵为欧氏距离时,结果和PCA相同,但是它的思路是不一样的。经典MDS的目标是使得数据的低维内积尽可能接近数据的高维内积。但是此时高维内积不知道(输入的只有“相似度”),于是需要由相似度反推内积。其过程如下:

    假设输入n个数据,排成一个nh列矩阵X,彼此之间相似度为D。假定这种相似度为数据的欧氏距离,而且数据关于每一维做了中心化(每个数据每维减去所有数据在该维的均值)。这样的假定使得经典MDS的几何意义(保内积)明确。下面对此说明:

     

    定义矩阵 J = I - 1/n * E  ,I是单位阵,E是全1阵。

    设D2 为相似度矩阵各元素的平方组成的矩阵,可以证明如下等式,

      -0.5 * J * D2 * J =(J X)(J X)T =B

    (J X)(J X)T 即为对X每一维做中心化之后的高维数据X’的内积。

    之后设B的特征值为λ1,λ2,λ3…… ,特征列向量为v1,v2,v3…… ,则 [λ1v1,λ2v2,λ3v3 ……]为降维后的位置。解释如下:

     

    经典MDS实际上是最小化以下函数:

     

    X此处为低维坐标,一行一个数据,一列一维。B与前文的B一样。B为高维内积,XXT为低维内积,所以说此种算法的目标是使得低维内积尽可能逼近高维内积。此处是两个矩阵的逼近问题,又知道B的特征分解后取前k个特征值与特征向量构成的X能最小化上述函数(具体过程现在我还没有完全搞懂)。 于是X就是经典MDS的结果了。

     

    经典MDS的算法是不需要初始化的,于是用其结果作为Stress MDS的初始位置。整个降维算法也就不含随机性了。

     

    MDS算法是一种广泛使用的降维算法。但是它有一个缺点,就是每个高维数据点的移动都会对其他点产生影响。例如,如果加入一个文档,其特征向量与已有的其他文档都不相似,它对应的低维点就会把其他点推开,以保持这种不相似;反过来,一个拥有其他文档公共特征的文档又会把其他文档向自己拉近。这些都是当前布局不稳定的可能原因。在大量文档的场合中,很可能有一部分文档由于太短,其特征与其他文档都不太相似,导致第一种不稳定情况的发生。

     

    针对此种情况,现在准备的解决方法是使用一种称为ISOMap的算法。这个算法把高维数据的彼此空间距离变成图的距离。算法首先是建立一个图,图的每个节点对应每个高维数据。对于每个高维数据,再找与其最接近(欧氏距离或其他距离最小)的几个数据,在图上与这几个数据建立边连接。最后,两个节点的距离就定义为图上最短路径的长度,而不是原来高维空间的距离。根据这个新定义的距离,运行MDS算法,即得到降维后的结果。这个算法的好处是,如果个别数据出现变动,可能只会影响一部分边,而不会产生全局的影响(当然如果它恰好把原先的几个连通分量连起来了,那影响就大了)。在流形学习中,它的好处更加突出,就是能捕捉到嵌入到高维的低维数据(例如把一个三维螺旋卷展开, 卷本身是二维的,只是嵌入到三维空间(被卷起来了))。不过现在只是想找一个稳定的降维办法,而且代码特征也不一定包含所谓流形信息,所以这点好处不能套过来说。

     

    IsoMap还没有实现,距之前做代码可视化的那个人说,效果好一些,理由就是上面所说的。下一步准备试试。

     

     

      4.绘图

     

    这一步其实没有什么算法可言,基本上就是每个低维数据点给一个高斯核,各个核加起来就是高度场。但有一点值得说说,由于希望高度场能表达体系结构上的“底层”和“高层”,也就是说希望高的类依赖低的类,所以预先要建一个依赖图。如果一个类A用了类B的变量,那就是说类A依赖了类B,根据这些依赖关系,可以建一个有向图,A依赖B,就有一条AB的边。最后由只有入边的节点开始遍历,就可以依次定出各个节点的等级。(当然要用些小技巧解决循环依赖的问题)

     

    当前画出来的图有点粗糙(因为效率比较低,所以像素不敢设太多),下一步着手改进一下。另外就是加入更多的信息。例如在图中表示函数的调用关系,用不同的图标表示每个类每个函数的具体情况,画出每个工程每个类的“领土”范围等等。

     

      5.总结

     

    我觉得当前这个东西值得研究的点主要是寻找一个稳定的,但是又能暗示代码某些关系的布局方案,以及尽可能把丰富的信息有条理地呈现在图中,让用户可以根据地图来提取需要的信息。

    转载于:https://www.cnblogs.com/dydx/p/3552402.html

    展开全文
  • 基于WebGL的大规模地理空间数据可视化分析框架。 在WebGL的支持下,L7的渲染技术支持大数据的快速高效渲染,2D / 3D渲染,这可以通过GPU并行计算对空间数据进行计算和分析来实现。 L7致力于地理数据的表达,交互...
  • 是基于的开源,多平台数据分析可视化应用程序。 首次公开发布于2002年10月宣布。此后,在 ,,,以及其他各种政府和商业机构以及学术合作伙伴之间的共同努力下,该项目得到了发展。 学习资源 常规信息可在。 ...
  • 您将看到一个带有两个按钮的页面,这些按钮可导致不同的可视化效果,以及有关项目的更多详细信息。 PS CodeMapper在查看JavaScript繁重的项目时表现最为出色,因为我们能够提供有关JavaScript文件的更多详细信息。
  • VizTracer是一个低开销的日志记录/调试/概要分析工具,可以跟踪和可视化您的python代码执行。 您可以查看多个示例程序的结果。 用户界面由。 使用“ AWSD”进行缩放/导航。 单击“?”可以找到更多帮助。 在右上角...
  • Metropolis是一种代码审查和分析工具,可帮助您突出显示感兴趣或关注的领域。 要了解更多信息,请访问我们的。 如何安装 Windows说明 安装 在上安装NodeJS npm install -g metropolis 目前,Metropolis仅支持...
  • 【Spark SQL实战】日志分析(三)结果可视化 目录 一、使用ECharts可视化框架 1、基本使用 2、静态测试 3、创建工程,添加依赖,编写代码 4、前端代码 5、修改web.xml 二、使用Zeppelin 代码及需要的js...

    笔记目录:

    【Spark SQL实战】日志分析(一)介绍、数据清洗

    【Spark SQL实战】日志分析(二)实现项目需求

    【Spark SQL实战】日志分析(三)结果可视化

     

    目录

    一、使用ECharts可视化框架 

    1、基本使用

    2、静态测试

    3、创建工程,添加依赖,编写代码

    4、前端代码

    5、修改web.xml

    二、使用Zeppelin


    代码及需要的js文件下载

    一、使用ECharts可视化框架 

    1、基本使用

    ECharts使用教程

    2、静态测试

    1)将下载下来的文件echarts.min.js放在js文件夹下

    2)在webapp下创建test.html

    test.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>ECharts USE</title>
        <!-- 引入 ECharts 文件 -->
        <script src="js/echarts.min.js"></script>
    </head>
    <body>
    
    <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
    <div id="main" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));
    
        // 指定图表的配置项和数据
        var option = {
            title: {
                text: '某站点用户访问来源',
                subtext: '纯属虚构',
                x: 'center'
            },
            tooltip: {
                trigger: 'item',
                formatter: "{a} <br/>{b} : {c} ({d}%)"
            },
            legend: {
                orient: 'vertical',
                left: 'left',
                data: ['直接访问', '邮件营销', '联盟广告', '视频广告', '搜索引擎']
            },
            series: [
                {
                    name: '访问来源',
                    type: 'pie',
                    radius: '55%',
                    center: ['50%', '60%'],
                    data: [
                        {value: 335, name: '直接访问'},
                        {value: 310, name: '邮件营销'},
                        {value: 234, name: '联盟广告'},
                        {value: 135, name: '视频广告'},
                        {value: 1548, name: '搜索引擎'}
                    ],
                    itemStyle: {
                        emphasis: {
                            shadowBlur: 10,
                            shadowOffsetX: 0,
                            shadowColor: 'rgba(0, 0, 0, 0.5)'
                        }
                    }
                }
            ]
        };
    
        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);
    </script>
    </body>
    </html>

    结果: 

    3、创建工程,添加依赖,编写代码

    pom.xml

    <!-- 添加依赖 -->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
        </dependency>
    
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jsp-api</artifactId>
          <version>2.0</version>
        </dependency>
    
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.38</version>
        </dependency>
    
        <dependency>
          <groupId>net.sf.json-lib</groupId>
          <artifactId>json-lib</artifactId>
          <version>2.4</version>
          <classifier>jdk15</classifier>
        </dependency>

    VideoAccessTopN.java

    package com.lihaogn.domain;
    
    public class VideoAccessTopN {
    
        private String name;
        private long value;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public long getValue() {
            return value;
        }
    
        public void setValue(long value) {
            this.value = value;
        }
    }
    

     MySQLUtils.java

    package com.lihaogn.utils;
    
    import java.sql.*;
    
    /**
     * MySQL工具类
     */
    public class MySQLUtils {
    
        private static final String USERNAME = "root";
        private static final String PASSWORD = "rootroot";
        private static final String DRIVERCLASS = "com.mysql.jdbc.Driver";
        private static final String URL = "jdbc:mysql://localhost:3306/sparkSql_project";
    
        /**
         * 获取数据库连接
         */
        public static Connection getConnection() {
            Connection connection=null;
            try {
                Class.forName(DRIVERCLASS);
                connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return connection;
        }
    
        /**
         * 释放资源
         */
        public static void release(Connection connection, PreparedStatement pstmt, ResultSet rs) {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    
            if (pstmt != null) {
                try {
                    pstmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
    
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) {
            System.out.println(getConnection());
        }
    }
    

     VideoAccessTopNDAO.java

    package com.lihaogn.dao;
    
    import com.lihaogn.domain.VideoAccessTopN;
    import com.lihaogn.utils.MySQLUtils;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class VideoAccessTopNDAO {
    
        static Map<String, String> courses = new HashMap<String, String>();
    
        static {
            courses.put("2402", "Mysql");
            courses.put("1309", "php");
            courses.put("3078", "Java 网络通信");
            courses.put("2801", "Mysql 优化");
            courses.put("1336", "scala");
            courses.put("3369", "Java 基础");
    
        }
    
        /**
         * 根据课程编号查询课程名称
         */
        public String getCourseName(String id) {
            return courses.get(id);
        }
    
    
        /**
         * 根据day查询当天的最受欢迎的topN课程
         */
        public List<VideoAccessTopN> query(String day) {
            List<VideoAccessTopN> list = new ArrayList<VideoAccessTopN>();
    
            Connection connection = null;
            PreparedStatement psmt = null;
            ResultSet rs = null;
    
            try {
                connection = MySQLUtils.getConnection();
                String sql = "select class_id,times from day_vedio_access_topn_stat where day=? order by times desc limit 5";
                psmt = connection.prepareStatement(sql);
                psmt.setString(1, day);
    
                rs = psmt.executeQuery();
    
                VideoAccessTopN domain = null;
    
                while (rs.next()) {
                    domain = new VideoAccessTopN();
    
                    domain.setName(getCourseName(rs.getLong("class_id") + ""));
                    domain.setValue(rs.getLong("times"));
    
                    list.add(domain);
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                MySQLUtils.release(connection, psmt, rs);
            }
            return list;
        }
    
        public static void main(String[] args) {
            VideoAccessTopNDAO dao = new VideoAccessTopNDAO();
            List<VideoAccessTopN> list = dao.query("20161110");
            for (VideoAccessTopN result : list) {
                System.out.println(result.getName() + "," + result.getValue());
            }
        }
    }
    

    VideoAccessTopNServlet.java

    package com.lihaogn.web;
    
    import com.lihaogn.dao.VideoAccessTopNDAO;
    import com.lihaogn.domain.VideoAccessTopN;
    import net.sf.json.JSONArray;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.List;
    
    /**
     * 最受欢迎的topN课程
     */
    public class VideoAccessTopNServlet extends HttpServlet{
    
        private VideoAccessTopNDAO dao;
    
        @Override
        public void init() throws ServletException {
            dao=new VideoAccessTopNDAO();
        }
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            String day = req.getParameter("day");
    
            List<VideoAccessTopN> results = dao.query(day);
    
            JSONArray json = JSONArray.fromObject(results);
    
            resp.setContentType("text/html;charset=utf-8");
    
            PrintWriter writer=resp.getWriter();
            writer.println(json);
            writer.flush();
            writer.close();
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doPost(req, resp);
        }
    }
    

    4、前端代码

    在js文件夹下放入文件jquery.js

    topn.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>ECharts USE</title>
        <!-- 引入 ECharts 文件 -->
        <script src="js/echarts.min.js"></script>
        <script src="js/jquery.js"></script>
    </head>
    <body>
    
    <!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
    <div id="main" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">
        // 基于准备好的dom,初始化echarts实例
        var myChart = echarts.init(document.getElementById('main'));
    
        // 指定图表的配置项和数据
        var option = {
            title: {
                text: '最受欢迎的top5课程',
                x: 'center'
            },
            tooltip: {
                trigger: 'item',
                formatter: "{a} <br/>{b} : {c} ({d}%)"
            },
            legend: {
                orient: 'vertical',
                left: 'left',
            },
            series: [
                {
                    name: '访问次数',
                    type: 'pie',
                    radius: '55%',
                    center: ['50%', '60%'],
                    data: (function () {
                        var courses = [];
                        $.ajax({
                            type: "GET",
                            url: "/stat?day=20161110",
                            dataType: 'json',
                            async: false,
                            success: function (result) {
                                for (var i = 0; i < result.length; i++) {
                                    courses.push({"value": result[i].value, "name": result[i].name});
                                }
                            }
                        })
                        return courses;
                    })(),
                    itemStyle: {
                        emphasis: {
                            shadowBlur: 10,
                            shadowOffsetX: 0,
                            shadowColor: 'rgba(0, 0, 0, 0.5)'
                        }
                    }
                }
            ]
        };
    
        // 使用刚指定的配置项和数据显示图表。
        myChart.setOption(option);
    </script>
    </body>
    </html>

    5、修改web.xml

    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
    
      <servlet>
        <servlet-name>stat</servlet-name>
        <servlet-class>com.lihaogn.web.VideoAccessTopNServlet</servlet-class>
      </servlet>
    
      <servlet-mapping>
        <servlet-name>stat</servlet-name>
        <url-pattern>/stat</url-pattern>
      </servlet-mapping>
    </web-app>
    

    6、结果 

    二、使用Zeppelin

    Zeppelin官网

    1、下载,解压,配置环境变量 
    2、启动

    zeppelin/bin/zeppelin-daemon.sh start

    3、打开web页面并配置使用

    // 浏览器输入
    localhost:8080

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    展开全文
  • 数据专家:Python库,可轻松进行数据分析可视化,探索和建模 最新发布的 发行状态 执照 建立状态 下载总次数 每月下载 来源排名 推特 它是什么? datasist是一个python软件包,可为流行和常用的功能或技术...
  • PhpDependencyAnalysis PhpDependencyAnalysis是面向对象PHP项目的可扩展...注意:要创建图形,您的计算机上需要 ,这是一个开源的图形可视化软件,适用于大多数平台。 $ composer require --dev mamuz/php-depende
  • 使用echarts可视化工具将之前统计好的数据进行展示。 2 开发环境 IDEA+maven spring boot + ECharts 3 编程 代码地址 1)pom.xml,添加依赖 &amp;lt;repositories&amp;gt; &amp;lt;repository&...
  • 提供了多种构架工具,来帮助开发人员分析和理解已有的代码库(Legacy Codebase),这些工具包括:依赖项关系图、顺序图以及体系结构资源管理器,Jennifer Marsman在她的博客 中详细介绍了如何使用这些工具。然而在...
  • '''依赖模块 pip install requests ''' import re import requests url = input('请输入B站视频链接: ') res = requests.get(url) cid = re.findall(r'"cid":(.*?),', res.text)[-1] url = f'...
  • 今年4月发布的Visual Studio 2010 (以下简称VS2010)的旗舰版提供了多种构架工具,来帮助开发人员分析和理解已有的代码库(Legacy Codebase),这些工具包括:依赖项关系图、顺序图以及体系结构资源管理器,Jennifer...
  • 在上一篇博客《写一个小工具来可视化VisualStudio中项目之间的依赖关系(1.针对sln中的信息)》中,我通过实验的方式知道了.sln文件中是如何存储依赖关系的,并编写了代码解析它。但问题是之后发现在.vcxproj中也有...
  • 众所周知,GItHub是可以调用API的 API:Web API 是网站的一部分...依赖于外部数据资源的大多数应用程序都依赖于API的调用, 如集成社交媒体网站的应用程序。 实现代码如下: # -*- coding: utf-8 -*- """ API...
  • 成果展示 项目地址爬取弹幕可以看我之前写的这篇文章:10行代码下载B站弹幕下载代码# download.py'''依赖模块pip install requests'''import reimport requestsurl = input('请输入B站视频链接: ')res = requests....
  • HoloViews是一个Python库,旨在使数据分析可视化变得无缝和简单。 使用HoloViews,您通常可以用很少的几行代码表达您想要做的事情,让您专注于要尝试探索和传达的内容,而不是绘图过程。 请访问以获取大量示例和...
  • 出现 emerge是一种代码分析工具,可用于收集有关源...该项目的主要目标是创建一个免费/开源工具,任何对软件开发,体系结构,指标和可视化感兴趣的人都可以轻松使用该工具,以收集有关这些主题的更多见解。 它应该促进
  • vprof是一个Python软件包,可为各种Python程序特征(例如运行时间和内存使用情况)提供丰富的交互式可视化。 它支持Python 3.4+,并在BSD许可下分发。 该项目正在积极开发中,其某些功能可能无法按预期工作。 屏幕...
  • 深度学习库 caffe使用 源码分析 依赖分析 caffe glog gflags...caffe网络模型结构在线可视化 CAFFE使用 源码分析等 caffe 模型配置文件 prototxt 详解 caffe.proto 系统变量层类型参数配置文件 caffe...
  • 第二部分将会介绍webpack内部插件与钩子关系的可视化展示工具📈,用一张图理清webpack内部这种错综复杂的关系。 <p><strong>可视化工具使用效果图:</strong></p> <p><img alt="" src=...
  • 该软件包专注于处理离群值和缺失值,缩放和关联可视化的任务。 安装 $ pip install -i https://test.pypi.org/simple/ eda_utils_py 功能 此软件包中包含的四个功能如下: imputer :插补缺失值的功能 outlier_...
  • 在 Linux 环境下,借助工具 Code Vize 可提取出开源软件中函数以及函数之间的依赖关系,并将分析结果以文本形式输出到文件中,然后借助于可视化工具 Graphviz 可将节点以及节点之间的依赖关系以图形化的方式 展示...
  • 文章来自:优阅达大数据生态Tableau 直观且易于使用的可视化操作界面,帮助数据分析师乃至是其他领域的人们都可以看到并理解他们的数据。当然,同样包括像数据科学家或统计学家这样老练的数据分析用户。为什么特别...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 208
精华内容 83
关键字:

代码依赖分析可视化