目录

  • util.h
  • hash.hpp/cpp
    • mangle函数
    • GenHashSeed函数
    • AwareHash模块
  • LDSketch.hpp/cpp
    • LDSketch更新函数,对一个sketch插入键值对。
    • LD_Sketch的find函数
  • dyn_tbl.hpp/cpp
    • 关键词
    • 哈希键值
    • 比较函数
    • 桶的数据结构
    • 初始化
    • destroy
    • 重置函数
    • 复制函数
    • 输出函数
    • 返回这个桶内的长度

util.h

IP转换函数,将二进制的IP地址转化为点分十进制的形式。/** Convert IP (in network order) to string*/
inline char* ip2a(uint32_t ip, char* addr) {sprintf(addr, "%d.%d.%d.%d", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) &0xff, (ip >> 24) & 0xff);return addr;
}

hash.hpp/cpp

mangle函数

为解决在不同机器上 C++的二进制兼容问题,使用mangle函数转化源码中的函数,因为在不同的编译器或不同的编译器版本,编译后的名称可能会有不同。
(或是使用seq-hash,测量heavy hitter heavy changers,提升了内存使用率,减少了计算开销,最关键的是可以恢复流的信息
把一个key值按照位分为几个段,分别hash进一个二维表里面,最后再把这些二维表的值合并出这个key)

void mangle(const unsigned char* key, unsigned char* ret_key,int nbytes) {unsigned long long new_key = 0;int i;for (i=0; i<nbytes; ++i) {new_key |= key[nbytes-i-1] << (i * 8);}new_key = (new_key * 2083697005) & (0xffffffff);for (i=0; i<nbytes; ++i) {ret_key[i] = (new_key >> (i * 8)) & 0xff;}
}

GenHashSeed函数

产生一个随机数的种子返回值。

uint64_t seed = 0;
uint64_t GenHashSeed(int index) {/*if (index == 0) {srand(0);}*/if (seed == 0) {seed = rand();}uint64_t x, y = seed + index;mangle((const unsigned char*)&y, (unsigned char*)&x, 8);return AwareHash((uint8_t*)&y, 8, 388650253, 388650319, 1176845762);
}

AwareHash模块

接受参数:原数据、原数据长度。哈希值的初始值为388650253,乘以规模388650319,再和数据相加后,向后移动一个数据,数据有多长就跑几次。数据中心的流量是非常巨大的,要将对如此巨大的流量产生随机分布的哈希值,这个哈希值也将非常巨大,也难怪在自己的虚拟机上,把数值调小了几倍还是溢出。最后对1176845762进行异或处理

/*** hash function* @param data the binary to be hashed* @param n the length of binary to be hashed*/
static unsigned int AwareHash(const unsigned char* data, unsigned int n) {unsigned int hash = 388650253;unsigned int scale = 388650319;unsigned int hardener  = 1176845762;while( n ) {hash *= scale;hash += *data++;n--;}return hash ^ hardener;
}

LDSketch.hpp/cpp

LDSketch更新函数,对一个sketch插入键值对。

可在前部分使用mangle函数encode key值。利用LD_Sketch_find 函数,找到一个位置,再更新到桶内

/** Sequential hashign algorithm - encode keys (a.k.a. update step)*/
void LDSketch_update(LDSketch_t* sk, unsigned char* key, long long val) {int j, k;// mangle// mangle(key, key_to_add, tbl->n/8);// add key/val to tablefor (j=0; j<sk->h; ++j) {k = LDSketch_find(sk, key, 0, sk->lgn - 1, j);//tbl->T[j*tbl->w+k] += val;dyn_tbl_update(sk->tbl[j*sk->w+k], key, val);}//tbl->total += val;
}

LD_Sketch的find函数

找到一个sketch内的key的哈希值。把这个key的副本初始化为0,把key值的每一位复制到副本当中,针对这个副本的前八位按照某种方法处理一次,之后的位置就把key原值复制进去。operator为列数乘以哈希函数的id号加上用户输入的桶的位置,并把operator加入这个桶中。输入这个副本和长度,返回这个键值的哈希值。

unsigned int LDSketch_find(LDSketch_t* tbl, const unsigned char* key, int start_bit,int end_bit, int row_no) {unsigned char key_str[50];      // assume n/8 + 4 <= 50unsigned int oper;char bit;unsigned int ret_bucket;int i;// set the key stringmemset(key_str, 0, sizeof(key_str));i = start_bit;      // start_bit == 0 in all caseswhile (i <= end_bit) {if (end_bit - i + 1 >= 8) {key_str[i/8] = key[i/8];    i += 8;} else {bit = (key[i/8] & (1 << (8 - ((i%8) + 1)))) > 0 ?  1 : 0;key_str[i/8] |= (bit << (8 - ((i%8) + 1)));i++;}}// set the operator and add it to key string//oper = part_no * tbl->[part_no] + array_no;oper = tbl->h * tbl->tbl_id + row_no;//oper = row_no;memcpy(key_str + tbl->lgn/8, &oper, sizeof(unsigned int));/*// hashMD5_CTX md5;unsigned char digest[16];MD5_Init(&md5);MD5_Update(&md5, key_str, tbl->n/8 + sizeof(unsigned int));MD5_Final(digest, &md5);memcpy(&ret_bucket, digest, sizeof(unsigned int));  // take 1st 4 bytesret_bucket = (ret_bucket % tbl->K);*/ret_bucket = AwareHash(key_str, (unsigned int)(tbl->lgn/8 + sizeof(unsigned int))) % (tbl->w);// returnreturn ret_bucket;
}

dyn_tbl.hpp/cpp

关键词

关键字的定义,最大长度为13字节。

#define MAX_KEYLEN 13/*** Structure of key*/
typedef struct dyn_tbl_key_s {/// 13-byte keyunsigned char key[MAX_KEYLEN];
} dyn_tbl_key_t;

哈希键值

定义一个哈希函数的对象。返回该键值的哈希值

/*** Object for hash*/
typedef struct {/// overloaded operationlong operator() (const dyn_tbl_key_t &k) const { return AwareHash((unsigned char*)k.key, MAX_KEYLEN); }
} dyn_tbl_key_hash;

比较函数

定义一个比较函数,判断两个字串是否相等

/*** Object for equality*/
typedef struct {/// overloaded operationbool operator() (const dyn_tbl_key_t &x, const dyn_tbl_key_t &y) const {return memcmp(x.key, y.key, MAX_KEYLEN)==0;}
} dyn_tbl_key_eq;

桶的数据结构

包括A(i,j),V(i,j),L(i,j),e(i,j),T,maximum.

/*** Bucket structure*/
typedef struct dyn_tbl_s {/// associative array: A(i,j)std::unordered_map<dyn_tbl_key_t, long long, dyn_tbl_key_hash, dyn_tbl_key_eq> array;/// total sum: V(i,j)long long total;/// maximum length of counters allowed, exceeding this value would trigger expansion: l(i, j)unsigned int max_len;/// total number of decrement: e(i, j)unsigned int decrement;/// expansion parameter: Tlong long T;/// maximum sum among keys, to speed up detectionlong long max_value;/************************ read only members***********************//// length of keysunsigned int lgn;
} dyn_tbl_t;

初始化

有参传参,无参置零

dyn_tbl_t* dyn_tbl_init(unsigned int length, int lgn, long long T) {dyn_tbl_t* ret = (dyn_tbl_t*)calloc(1, sizeof(dyn_tbl_t));ret->lgn = lgn;ret->max_len = length;ret->decrement = 0;ret->total = 0;ret->T = T;ret->max_value = 0;return ret;
}

destroy

free掉这个桶的内存空间

void dyn_tbl_destroy(dyn_tbl_t* dyn_tbl) {free(dyn_tbl);
}

重置函数

将桶的参数置零

void dyn_tbl_reset(dyn_tbl_t* dyn_tbl) {dyn_tbl->array.clear();dyn_tbl->decrement = 0;dyn_tbl->total = 0;dyn_tbl->max_value = 0;
}

复制函数

将桶的参数复制

void dyn_tbl_copy(dyn_tbl_t* dyn_tbl_from, dyn_tbl_t* dyn_tbl_to) {dyn_tbl_to->array = dyn_tbl_from->array;dyn_tbl_to->decrement = dyn_tbl_from->decrement;dyn_tbl_to->total = dyn_tbl_from->total;dyn_tbl_to->max_len = dyn_tbl_from->max_len;dyn_tbl_to->max_value = dyn_tbl_from->max_value;
}

输出函数

输出桶内的值,将值输出到文件中。主要输出的是桶内的IP地址的值。

void dyn_tbl_print(dyn_tbl_t* dyn_tbl, const char* output) {FILE* fp;// open a fileif ((fp = fopen(output, "w")) == NULL) {fprintf(stderr, "ERR: cannot open %s\n", output);exit(-1);}unsigned int len = dyn_tbl->array.size();fprintf(fp, "length: %u\n", len);// for(std::unordered_map<dyn_tbl_key_t, long long>::iterator it = dyn_tbl->array.begin(); it != dyn_tbl->array.end(); ++it) {for(auto it = dyn_tbl->array.begin(); it != dyn_tbl->array.end(); ++it) {dyn_tbl_key_t key = it->first;if (dyn_tbl->lgn == 32) {char addr1[30];unsigned int* ptr = (unsigned int*) key.key;fprintf(fp, "%s %lld\n", ip2a(*ptr, addr1), it->second);}else {char addr1[30];char addr2[30];unsigned int* ptr = (unsigned int*) key.key;fprintf(fp, "%s %s %lld\n", ip2a(*ptr, addr1), ip2a(*(ptr+1), addr2), it->second);}}// close the filefclose(fp);
}

返回这个桶内的长度

int dyn_tbl_length(dyn_tbl_t* dyn_tbl) {return dyn_tbl->array.size();
}

转载于:https://www.cnblogs.com/vancasola/p/9985053.html

LD-sketch源码阅读相关推荐

  1. FreeSWITCH 1.10 源码阅读(3)-sofia 模块原理及其呼入处理流程

    文章目录 1. 前言 2. 源码分析 2.1 sofia 模块的加载 2.2 呼入的处理流程 1. 前言 SIP(Session Initiation Protocol) 是应用层的信令控制协议,有许 ...

  2. 应用监控CAT之cat-client源码阅读(一)

    CAT 由大众点评开发的,基于 Java 的实时应用监控平台,包括实时应用监控,业务监控.对于及时发现线上问题非常有用.(不知道大家有没有在用) 应用自然是最初级的,用完之后,还想了解下其背后的原理, ...

  3. centos下将vim配置为强大的源码阅读器

    每日杂事缠身,让自己在不断得烦扰之后终于有了自己的清静时光来熟悉一下我的工具,每次熟悉源码都需要先在windows端改好,拖到linux端,再编译.出现问题,还得重新回到windows端,这个过程太耗 ...

  4. 源码阅读:AFNetworking(十六)——UIWebView+AFNetworking

    该文章阅读的AFNetworking的版本为3.2.0. 这个分类提供了对请求周期进行控制的方法,包括进度监控.成功和失败的回调. 1.接口文件 1.1.属性 /**网络会话管理者对象*/ @prop ...

  5. 源码阅读:SDWebImage(六)——SDWebImageCoderHelper

    该文章阅读的SDWebImage的版本为4.3.3. 这个类提供了四个方法,这四个方法可分为两类,一类是动图处理,一类是图像方向处理. 1.私有函数 先来看一下这个类里的两个函数 /**这个函数是计算 ...

  6. mybatis源码阅读

    说下mybatis执行一个sql语句的流程 执行语句,事务等SqlSession都交给了excutor,excutor又委托给statementHandler SimpleExecutor:每执行一次 ...

  7. 24 UsageEnvironment使用环境抽象基类——Live555源码阅读(三)UsageEnvironment

    24 UsageEnvironment使用环境抽象基类--Live555源码阅读(三)UsageEnvironment 24 UsageEnvironment使用环境抽象基类--Live555源码阅读 ...

  8. Transformers包tokenizer.encode()方法源码阅读笔记

    Transformers包tokenizer.encode()方法源码阅读笔记_天才小呵呵的博客-CSDN博客_tokenizer.encode

  9. 源码阅读笔记 BiLSTM+CRF做NER任务 流程图

    源码阅读笔记 BiLSTM+CRF做NER任务(二) 源码地址:https://github.com/ZhixiuYe/NER-pytorch 本篇正式进入源码的阅读,按照流程顺序,一一解剖. 一.流 ...

  10. 源码阅读:AFNetworking(八)——AFAutoPurgingImageCache

    该文章阅读的AFNetworking的版本为3.2.0. AFAutoPurgingImageCache该类是用来管理内存中图片的缓存. 1.接口文件 1.1.AFImageCache协议 这个协议定 ...

最新文章

  1. oracle 进制,Oracle进制转换函数
  2. Win7系统中必需记住的14个常用快捷键
  3. python当前时间怎么弄_python获取当前时间
  4. python控制gpio产生固定数量的脉冲_STM32L151用dma控制GPIO口发出指定的脉冲个数的疑惑!...
  5. ajax写删除程序,ajax处理程序删除标记
  6. PAYPAL 支付,sandbox测试的时候遇到异常:请求被中止: 未能创建 SSL/TLS 安全通道,以及解决方法。
  7. 为imageView添加图片实现动画
  8. SVN汉化包安装后无效果(已解决)
  9. antdesign 新增页面_ant design pro 新增页面
  10. 【BZOJ4589】【SRM 518 Div1】Hard Nim(FWT)
  11. 时序逻辑电路的设计(一) -- 模10的计数器电路(附Multisim)
  12. 利用原生js实现随机点名
  13. UE官网ARPG游戏学习笔记1
  14. 荣耀4a鸿蒙,赵明:6 月起芯片供应将全面恢复,荣耀未来会考虑用华为鸿蒙系统...
  15. px、em、rem、rpx 用法 与 区别
  16. 08s01 mysql_mysql报错 code:08S01,msg:SQLSTATE
  17. mysql使得df和du不一致_df和du显示的磁盘空间使用情况不一致的原因及处理
  18. XINLINX VC707 的学习
  19. Bilibili综合分析
  20. java发送html模板的高逼格邮件

热门文章

  1. 《CCNA无线640-722认证考试指南》——5.4节其他无线拓扑
  2. MySQL 5.7新特性
  3. synchronized锁自旋2
  4. hive on tez踩坑记1-hive0.13 on tez
  5. centOS下JDK1.8的安装
  6. 应用场景之Dynamic End Point(DEP)IPSec的配置
  7. C++泛型算法的小总结
  8. c 本地html解析,使用selenium解析本地HTML文件方法
  9. 如何安装CocoaPods,以便在Xcode中快速添加第三方库
  10. 图神经网络(GNN)综述