sparkline这个单词,我第一次看的时候。也不知道这什么意思啊,曾经根本没听过啊,可是这真真实实的出如今了redis的代码中了,刚刚開始以为这也是属于普通的队列嘛。就把他分在了struct包里了。

好来分析完了。与原本我所想的差太大了。sparkline英文中的意思“微线图”,这么说吧。类似于折线图,由一个一个信息点构成。所以看到这个意思。你也许就明确了sparkline.c是干什么用的了吧,就是绘图用的。

我们看看这个绘图的内部结构是什么,绘图须要的元素是哪些:

/* sparkline.h -- ASCII Sparklines header file
*
* ---------------------------------------------------------------------------
*
* Copyright(C) 2011-2014 Salvatore Sanfilippo <antirez@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/ #ifndef __SPARKLINE_H
#define __SPARKLINE_H /* sparkline是一类信息体积小和数据密度高的图表。 眼下它被用作一些測量,
*相关的变化的信息呈现的方式。如平均温度,股市交投活跃。sparkline经常以一组多条的形式出如今柱状图,折线图其中。 *能够理解为一个图线信息 */
/* A sequence is represented of many "samples" */
/* 能够理解为图像上的一个信息点,有文字,有值的大小 */
struct sample {
double value;
char *label;
}; /* 图线信息结构体,包含n个元素点。能够据此描写叙述出图,画图的可不是直接按点和值直接绘制的 */
struct sequence {
//当前元素点个数
int length;
//总共的文字个数,有些点没有label描写叙述。为NULL
int labels;
//元素点列表
struct sample *samples;
//元素中的最大值,最小值
double min, max;
}; /* 定义了一些渲染图时候一些属性操作设置 */
#define SPARKLINE_NO_FLAGS 0
#define SPARKLINE_FILL 1 /* Fill the area under the curve. */
#define SPARKLINE_LOG_SCALE 2 /* Use logarithmic scale. */ struct sequence *createSparklineSequence(void); //创建图线序列结构体
void sparklineSequenceAddSample(struct sequence *seq, double value, char *label); //在图线序列中加入一个信息点
void freeSparklineSequence(struct sequence *seq); //释放图线序列
sds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags); //渲染图线序列为一个图,事实上就是得到一个字符串组成的图
sds sparklineRender(sds output, struct sequence *seq, int columns, int rows, int flags); //方法同上,仅仅是少可一个偏移量 #endif /* __SPARKLINE_H */

我们看到上面的sample结构体事实上“信息点”元素的意思了。里面非常easy。一个文字label,一个value值,简洁明了。然后sequence就自然是图线了,里面就定义了元素点列表了。里面还有线的长度,和最大值。最小值,信息还挺全面的线。

后序的绘图操作都是依据这个图线序列结构体操作的。结构体一点都不复杂。

可是绘图的实现一点都不简单,怎样依据给定的一些点信息画出一个类似折线的图线呢。可别忘了,这是要在命令行窗体的图线哦,所以不会像高级语言中的GUI的操作那样非常方便。我们看看redis代码中是怎么写的。

/* sparkline.c -- ASCII Sparklines
* This code is modified from http://github.com/antirez/aspark and adapted
* in order to return SDS strings instead of outputting directly to
* the terminal.
*
* ---------------------------------------------------------------------------

在sparkline.c中的凝视声明,此代码改动自 http://github.com/antirez/aspark,原来是开源的代码实现,可是一開始真的不知道还有这么个叫aspark的东西,都跟BigData里的spark搞混了,然后我点击此地址,官方解释来了:

aspark is a C program to display ASCII Sparklines.
It is completely useless in 2011.

不错。意思就是说aspark就是用来在C程序上显示图线效果的。后来,我看了下,的确代码差点儿相同,redis的代码在上面加了自己的东西,稍稍改动,aspark的图线展现有几种形式,第一种。最简单的展示:

$ ./aspark 1,2,3,4,10,7,6,5
`-_
__-` `

第二张把行数扩展为很多其它行,展示很多其它的数据,上面的这个为2行展示。数据多的时候,调节行数,默认输出2行展示

$ ./aspark 1,2,3,4,5,6,7,8,9,10,10,8,5,3,1 --rows 4
_-``_
_`
-` `
_-` `_

当然能够更加可视化,在空白处填充字符。看起来更舒服:

$ ./aspark 1,2,3,4,5,6,7,8,9,10,10,8,5,3,1 --rows 4 --fill
_o##_
_#|||||
o#|||||||#
_o#||||||||||#_

用了"|"符号,非常有想象力的哦,最最关键的我们看怎样实现这种效果呢,核心代码例如以下:

/* Render part of a sequence, so that render_sequence() call call this function
* with differnent parts in order to create the full output without overflowing
* the current terminal columns. */
/* 渲染出这个图线信息 */
sds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags) {
int j;
double relmax = seq->max - seq->min;
int steps = charset_len*rows;
int row = 0;
char *chars = zmalloc(len);
int loop = 1;
int opt_fill = flags & SPARKLINE_FILL;
int opt_log = flags & SPARKLINE_LOG_SCALE; if (opt_log) {
relmax = log(relmax+1);
} else if (relmax == 0) {
relmax = 1;
} while(loop) {
loop = 0;
memset(chars,' ',len);
for (j = 0; j < len; j++) {
struct sample *s = &seq->samples[j+offset];
//value派上用处了
double relval = s->value - seq->min;
int step; if (opt_log) relval = log(relval+1);
//最后会算出相关的step
step = (int) (relval*steps)/relmax;
if (step < 0) step = 0;
if (step >= steps) step = steps-1; if (row < rows) {
/* Print the character needed to create the sparkline */
/* step控制输出的字符是哪一个 */
int charidx = step-((rows-row-1)*charset_len);
loop = 1;
if (charidx >= 0 && charidx < charset_len) {
chars[j] = opt_fill ? charset_fill[charidx] :
charset[charidx];
} else if(opt_fill && charidx >= charset_len) {
//用"|"填充内容,更加可视化
chars[j] = '|';
}
} else {
/* Labels spacing */
if (seq->labels && row-rows < label_margin_top) {
loop = 1;
break;
}
/* Print the label if needed. */
if (s->label) {
int label_len = strlen(s->label);
int label_char = row - rows - label_margin_top; if (label_len > label_char) {
loop = 1;
chars[j] = s->label[label_char];
}
}
}
}
if (loop) {
row++;
output = sdscatlen(output,chars,len);
output = sdscatlen(output,"\n",1);
}
}
zfree(chars);
return output;
}

因为本人能力有限,有点不太懂里面的详细细节,大概看了下,把变量用到的地方稍稍看了下,上面的代码都是很优秀的代码,值得我们学习。今天至少让我知道了什么叫sparkline叫什么 了,哈哈。

Redis源代码分析(五)--- sparkline微线图的更多相关文章

  1. Redis源代码分析(十一年)--- memtest内存测试

    今天,我们继续redis源代码test下测试在封装中的其它文件.今天读数memtest档,翻译了,那是,memory test 存储器测试工具..可是里面的提及了非常多东西,也给我涨了非常多见识,网上 ...

  2. Redis源代码分析(一)--Redis结构解析

    从今天起,本人将会展开对Redis源代码的学习,Redis的代码规模比較小,很适合学习,是一份很不错的学习资料,数了一下大概100个文件左右的样子,用的是C语言写的.希望终于能把他啃完吧,C语言好久不 ...

  3. redis 源代码分析(一) 内存管理

    一,redis内存管理介绍 redis是一个基于内存的key-value的数据库,其内存管理是很重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数进行了一层封装,程序中 ...

  4. Redis源代码分析(23)--- CRC循环冗余算法RAND随机数的算法

    他今天就开始学习Redis源代码的一些工具来实现,在任何一种语言工具.算法实现的原理应该是相同的,一些比較经典的算法.比方说我今天看的Crc循环冗余校验算法和rand随机数产生算法. CRC算法全称循 ...

  5. [Android] Volley源代码分析(五岁以下儿童)Q \\ u0026一个

    Volley源代码分析系列那里一段时间,告诉我,有许多私人留言,同时一些问题抛出.对于一些简单的问题,我们跳,这两天被连接到朋友@smali提出的问题.告诉我你不得不赞叹查看源代码时的详细程度,大家一 ...

  6. Redis源代码分析(三十五)--- redis.c服务端的实现分析(2)

    在Redis服务端的代码量真的是比較大,假设一个一个API的学习怎么实现,无疑是一种效率非常低的做法,所以我今天对服务端的实现代码的学习,重在他的运行流程上.而对于他的模块设计在上一篇中我已经分析过了 ...

  7. Redis源代码分析(六)--- ziplist压缩列表

    ziplist和之前我解析过的adlist列表名字看上去的非常像.可是作用却全然不同.之前的adlist主要针对的是普通的数据链表操作. 而今天的ziplist指的是压缩链表.为什么叫压缩链表呢.由于 ...

  8. Redis源代码分析(十)--- testhelp.h小测试框架和redis-check-aof.c 日志检测

    周期分析struct结构体redis代码.最后,越多越发现很多的代码其实大同小异.于struct有袋1,2不分析文件,关于set集合的一些东西,就放在下次分析好了,在选择下个分析的对象时,我考虑了一下 ...

  9. Redis源代码分析(三)---dict哈希结构

    昨天分析完adlist的Redis代码.今天立即马不停蹄的继续学习Redis代码中的哈希部分的结构学习,只是在这里他不叫什么hashMap,而是叫dict.并且是一种全新设计的一种哈希结构,他仅仅是通 ...

随机推荐

  1. [scrapy] scrapy 使用goose作为正文提取

    import scrapy from goose import Goose class Article(scrapy.Item): title = scrapy.Field() text = scra ...

  2. LOJ #6277. 数列分块入门 1-分块(区间加法、单点查询)

    #6277. 数列分块入门 1 内存限制:256 MiB时间限制:100 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2   题目描述 给出 ...

  3. AndroidManifest.xml文件详解(meta-data)

    http://blog.csdn.net/think_soft/article/details/7567189 语法(SYNTAX): <meta-dataandroid:name=" ...

  4. js判断上传图片宽高及文件大小

    <input id="file" type="file"> <input id="Button1" type=" ...

  5. 【BZOJ 4650】【UOJ #219】【NOI 2016】优秀的拆分

    http://www.lydsy.com/JudgeOnline/problem.php?id=4650 http://uoj.ac/problem/219 这里有非常好的题解qwq 接着道题复习一下 ...

  6. 【容斥原理】【分解质因数】poj1091 跳蚤

    题意转化为求一个线性组合a1*x1+a2*x2+...+an*xn+m*xn+1=1在什么时候可以有解.(ai在1~m的范围内任取) 易得当且仅当gcd(a1,a2,...,an)=1时可能有解. 然 ...

  7. 【set】【Splay】【pb_ds】bzoj1208 [HNOI2004]宠物收养所

    每次来的如果是人,且宠物数不为零,就从宠物中选出一个与其差距最小的,累加答案:若为零,就把他放入另一个集合里. 如果是宠物,则同上. 各种平衡树都可过,我蛋疼地用了pb_ds. Code: #incl ...

  8. opensue fstab故障恢复

    date: 20140505 author: Jin 故障背景: 早上启动本本 无法启动,报错信息(几个关键) WARNING:Failed to connect to lvmetad: No suc ...

  9. Eclipse错误导致无法启动The workspace exited with unsaved changes in the previous session

    MyOpenSUSE:/home/jin/workspace # tail -f .metadata/.log !SESSION 2014-05-04 11:35:58.869 ----------- ...

  10. fedora19/opensuse13.1 配置svn client

    Date: 20140208Auth: Jin 一.install zypper install  subversion yum install  subversion 二.操作 1.将文件check ...