Fast and Accurate Graph Stream Summarization
Abstract
A graph stream is a continuous sequence of data items, in which each item indicates an edge, including its two endpoints and edge weight. It forms a dynamic graph that changes with every item in the stream. Graph streams play important roles in cyber security, social networks, cloud troubleshooting systems and other fields. Due to the vast volume and high update speed of graph streams, traditional data structures for graph storage such as the adjacency matrix and the adjacency list are no longer sufficient. However, prior art of graph stream summarization, like CM sketches, gSketches, TCM and gMatrix, either supports limited kinds of queries or suffers from poor accuracy of query results. In this paper, we propose a novel Graph Stream Sketch (GSS for short) to summarize the graph streams, which has the linear space cost (, E is the edge set of the graph) and the constant update time complexity () and supports all kinds of queries over graph streams with the controllable errors. Both theoretical analysis and experiment results confirm the superiority of our solution with regard to the time/space complexity and query results’ precision compared with the state-of-the-art.
Index Terms:
graph, data stream, sketch, approximate queryI Introduction
I-A Background and Motivations
In the era of big data, data streams propose some technique challenges for existing systems. Furthermore, the traditional data stream is modeled as a sequence of isolated items, and the connections between the items are rarely considered. However, in many data stream applications, the connections often play important roles in data analysis, such as finding malicious attacks in the network traffic data, mining news spreading paths among the social network. In these cases the data is organized as graph streams. A graph stream is an unbounded sequence of items, in which each item is a vector with at least three fields (denoted by ), where represents an edge between nodes and , and is the edge weight. These data items together form a dynamic graph that changes continuously and we call it streaming graph for convenience. Below we discuss three examples to demonstrate the usefulness of streaming graph problems.
Use case 1: Network traffic. The network traffic can be seen as a large dynamic graph, where each edge indicates the communication between two IP addresses. With the arrival of packets in the network, the network traffic graph changes rapidly and constantly. In the network traffic graph, various kinds of queries are needed, like performing node queries to find malicious attackers, or subgraph queries to locate certain topology structures in the dynamic networks.
Use case 2: Social networks. In a social network, the interactions among the users can form a graph. The edges between different nodes may be weighted by the frequencies of interactions. In such a graph, queries like finding the potential friends of a user and tracking the spreading path of a piece of news are often needed.
Use case 3: Troubleshooting in data centers. Cloud systems may need to analyze communication log stream to perform real time troubleshooting. In this situation the graph stream is the sequence of communication log entries where each entry is a description of a communication from a source machine to a destination machine. In such a graph, we may perform traversal query to find out if massages created by a certain application on a source machine can reach a destination machine, or perform edge query to find the detailed information of a communication log.
These streaming graphs are very large and change fast. For example, in Twitter, there are about million user login data, with million tweets posted per day. For another example, in large ISP or data centers[1], there could be millions of packets every second in each link. The large volume and high dynamicity make it hard to store the graph streams efficiently with traditional data structures like adjacency lists or adjacency matrices. In the context of graph streams, there are two requirements for designing a new data structure : (1) the linear space cost (2) the constant update time. To meet these two requirements, we can either apply approximated query data structures for data streams, like the CM sketch[2], the CU sketch [3] and other sketches [4, 5], or use specialized graph summarization techniques such as gSketches [6], TCM [7] and gMatrix [8]. However, existing solutions either support limited query types or have poor query accuracy. For example, CM sketches and gSketches fail to answer queries involved with topology like reachability queries, successor queries and so on. Though TCM and gMatrix can support these queries, they have poor accuracy. More details about the related work are given in Section II. In this paper, we design a novel data structure–Graph Stream Sketch (GSS for short), which can support all kinds of queries over streaming graphs with controllable errors in query results. Both theoretical analysis and experiment results show that the accuracy of our method outperforms state-of-the-art by orders of magnitudes.
I-B Our Solution
In this paper we propose GSS, which is an approximate query data structure for graph streams with linear memory usage, high update speed, high accuracy and supports all kinds of graph queries and algorithms like [9, 10, 11]. GSS can also be used in exiting distributed graph systems [12, 13, 14, 15]
Like TCM, GSS uses a hash function to compress the streaming graph into a smaller graph which is named a graph sketch. Each node in is mapped into a hash value . Nodes with the same hash value are combined into one node in , and the edges connected to them are also aggregated. An example of the graph stream and the graph sketch can be referred in Fig.1 and Fig.2. The compression rate can be controlled by the size of the value range of , which we represent with . The higher the compression rate is, the lower the accuracy is, as more nodes and edges will be combined.
Different from TCM which uses an adjacency matrix to store the graph sketch , GSS uses a novel data structure to store it. This data structure is specially designed for sparse graphs and can store a much bigger graph sketch with the same space. As the graph is sparse, the number of nodes is large, but each node is connected to few edges. Therefore, different from adjacency matrix which stores edges with the same source node / destination node in one row / column, we store edges with different source nodes / destination nodes in the one row / column, and distinguish them with fingerprints. Each edge in the graph sketch is mapped to a bucket in the matrix depending on its endpoints, and marked with a fingerprint pair. If the bucket it is mapped is already occupied by other edges, we store this edge in a buffer , which is composed of adjacency lists. With a matrix we can represent a graph sketch with at most nodes in GSS, where is the size of the value range of the fingerprint (for example, a 16-bit fingerprint has ). On the other hand, the adjacency matrix can only store a a graph sketch with at most nodes. With a much larger graph sketch, the accuracy is also much higher compared to TCM.
In GSS, the memory cost and update speed are greatly influenced by the size of the buffer . As the buffer takes additional memory, and update speed in an adjacency list is linear with its size. In order to restrict its size, we propose a technique called square hashing. In this technique each edge is mapped to multiple buckets, and stored in the first empty one among them. This enlarges the chance that an edge finds an empty bucket. Besides, a few nodes in a sparse graph may still have very high degrees. If one node emits a lot of edges, these edges have high probability to evict each other when stored in one row. To solve this problem, In square hashing edges with source node are no longer mapped to one row, but rows, sharing memory with other source nodes. The higher degree a node has, the more buckets it may take. It is similar in the view of columns and destination nodes. This helps to ease the congestion brought by the skewness in node degrees. Experiments show that after this modification the buffer only stores less than of the edges in the graph stream.
The key contributions of this paper are as follows:
- 1.
We propose GSS, a novel data structure for graph stream summarization. It has small memory usage, high update speed, and supports almost all kinds of queries for graphs. Most important of all, it uses a combination of fingerprints and hash addresses to achieve very high accuracy.
- 2.
We propose a technique called square hashing in the implementation of GSS. It helps to decrease the buffer size, improve update speed and reduce memory cost. It also eases the influence brought by the skewness in node degrees.
- 3.
We define graph query primitives and give details about how GSS supports them. Almost all algorithms for graphs can be implemented with these primitives.
- 4.
We carry out theoretical analysis and extensive experiments to evaluate the performance of GSS, which show that when using 1/256 memory size of the state-of-the-art graph summarization algorithm, our algorithm still significantly outperforms it for most queries.
II Related Work
In this part we will give a brief introduction about the related works. The prior arts of graph stream summarization can be divided into two kinds. The first kind is composed of counter arrays and stores each data item in these arrays independently, ignoring the connections between them. They only support queries for edge weights, but do not support any queries involved with topology of the graph. This kind includes CM sketches[2], CU sketches[3], gSketches[6] and so on. The second kind supports all queries in the streaming graph, but suffers from poor accuracy. This kind includes TCM[7] and gMatrix[8]. Because of space limitation, in this section we only introduce the second kind which is more relevant to our work.
TCM [7] is the state-of -the-art of data structures for graph stream summarization. It is composed of an adjacency matrix that stores the compression of the streaming graph. It uses a hash function to compress the streaming graph into a smaller graph sketch . For each node in , TCM maps it to node in . For each edge in , TCM maps it to edge in . The weight of an edge in is an aggregation of the weights of all edges mapped to it. A hash table that stores the hash value and the original ID pairs can be built in this map procedure to retrieve the original node IDs for some queries. Then TCM uses an adjacency matrix to represent the graph sketch. If we represent the size of the value range of with , we need to build an adjacency matrix. Each bucket in the matrix contains a counter. The weight of edge in the graph sketch is added to the counter in the bucket in row , column .
When the memory is sufficient, we can also build multiple sketches with different hash functions, and report the most accurate value in queries.
In order to satisfy the demand on memory usage, the size of the adjacency matrix, has to be within , which means for a sparse streaming graph where is usually within . This means the graph sketch is usually much smaller than , a lot of nodes and edges will be aggregated. As a result, the accuracy of TCM is poor.
The gMatrix [8] is a variant of TCM. Its structure is similar to TCM. But it uses reversible hash functions to generate graph sketches. It also extends TCM to more queries like edge heavy hitters and so on. However, different from the accurate hash tables, the reversible hash function introduces additional errors in the reverse procedure. Therefore the accuracy of gMatrix is no better than TCM, sometimes even worse.
III Problem Definition
Definition 1
Graph Stream: A graph stream is an unbounded timing evolving sequence of items , where each item indicates a directed edge11 1 The approach in this paper can be easily extended to handle undirected graphs. from node to node , with wight . The timepoint is also referred as the timestamp of . Thus, the edge streaming sequence forms a dynamic directed graph that changes with the arrival of every item , where and denote the set of nodes and the set of edges in the graph, respectively. We call a streaming graph for convenience.
In a graph stream , an edge may appear multiple times with different timestamps. The weight of such edge in the streaming graph is SUM of all edge weights sharing the same endpoints. The weight can be either positive or negative. An item with means deleting a former data item.
Example 1
A sample graph stream and the corresponding streaming graph are both shown in Fig. 1. Each node has an ID that uniquely identifies itself. If an edge appears multiple times, its weights are added up as stated above.
In practice, is usually a large, sparse and high speed dynamic graph. The large volume and high dynamicity make it hard to store graph streams using traditional data structures such as adjacency lists and adjacency matrices. The large space cost of rules out the possibility of using the adjacency matrix to represent a large sparse graph. On the other hand, the adjacency list has memory cost, which is acceptable, but the time cost of inserting an edge is , which is unacceptable due to the high speed of the graph stream.
The goal of our study is to design a linear space cost data structure with efficient query and update algorithms over high speed graph streams. To meet that goal, we allow some approximate query results but with small and controllable errors. However, traditional graph stream summarization approaches either cannot answer graph topology queries such as reachability queries (such as CM sketches [2] and gSketches [6]) or fail to provide accurate query results (such as TCM [7] and gMatrix [8]). Therefore, in this paper, we design a novel graph stream summarization strategy.
In order to give a definition of the graph stream summarization problem, First we define the graph sketch as follows:
Definition 2
Graph Sketch: a graph sketch of is a samller graph where and . A map function is used to map each node in to a node in , and edge in is mapped to edge in . The weight of an edge in is the SUM of the weights of all edges mapped to it.
Formally, we define our graph stream summarization problem as follows.
Definition 3
Graph Stream Summarization: Given a streaming graph , the graph stream summarization problem is to design a graph sketch , and the corresponding data structure to represent , where the following conditions hold:
- 1.
There is a function that map nodes in to nodes in ;
- 2.
The space cost of is ;
- 3.
changes with each new arriving data item in the streaming graph and the time complexity of updating should be ;
- 4.
supports answering any query over the original streaming graph with small and controllable errors.
In the context of streaming graphs, changes with every data item in the graph stream , which is mapped to updating the graph sketch , and conducted in data structure . For every new item in , we map edge in to edge in with weight and then insert it into . Similarly, queries over are also mapped to the same kind of queries over the graph sketch . In order to support any kind of graph queries, we first define three graph query primitives as follows, since many kinds of graph queries can be answered using these primitives.
Definition 4
Graph Query Primitives: Given a graph , the three graph query primitives are:
- •
Edge Query: given an edge , return its weight if it exists in the graph and return if not.
- •
-hop Successor Query: given a node , return a set of nodes that are 1-hop reachable from , and return if there is no such node;
- •
-hop Precursor Query: given a node , return a set of nodes that can reach node in 1-hop, and return if there is no such node.
With these primitives, we can re-construct the entire graph. We can find all the node IDs in the hash table. Then by carrying out 1-hop successor queries or 1-hop precursor queries for each node, we can find all the edges in the graph. The weight of the edges can be retrieved by the edge queries. As the graph is reconstructed, all kinds of queries and algorithms can be supported. In fact, in many situations, it is not necessary to re-construct the entire graph. We can just follow the specific algorithm and use the primitives to get the information when needed. Therefore, The data structure needs to support these query primitives.
IV GSS: Basic Version
In this section, we describe a conceptually simple scheme to help illustrate intuition and benefit of our approach. The full approach, presented in Section V, is designed with more optimizations. As stated above, to produce a graph stream summarization, we first need to design a graph sketch for the streaming graph . Initially, we use the same strategy as TCM to generate the graph sketch. We choose a hash function with value range , then is generated as following:
- 1.
Initialization: Initially, , and .
- 2.
Edge Insertion: For each edge in with weight , we compute hash values and . If either node with ID or is not in yet, we insert it into . Then we set . If is not in , we insert into and set its weight . If is in already, we add to the weight.
is empty at the beginning and expands with every data item in the graph stream. We can store pairs with hash tables to make this mapping procedure reversible. This needs additional memory, as , the overall memory requirement is still within .
Example 2
Obviously, the size of the value range of the map function , which we represent with , will significantly influence the accuracy of the summarization, especially in the 1-hop successor / precursor query primitives. In a uniform mapping with the hash function, each node in has the probability to collide with another, which means they are mapped to the same node in . When there are nodes, the probability that a node does not collide with any other nodes is . In the 1-hop successor / precursor queries, if collides with others, the query result about it will definitely have errors. Therefore we have to use a large to maximize this probability.
Figure 3 shows the theoretical results of the relationship between and the accuracy of the query primitives . The results are computed according to analysis in Section VI-B. (In the figure of the edge query, and means the in-degree of the source node and the out-degree of the destination node of the queried edge. In the figure of the 1-hop successor / precursor query, and means the in-degree and the out-degree of the queried node, respectively). The figure shows that we have to use a large to achieve high accuracy in the query primitives, which is not possible in the prior works. According to Figure 3, only when , the accuracy ratio is larger than in 1-hop successor / precursor queries. When , the accuracy ratio falls down to nearly , which is totally unacceptable.
Both TCM and the gMatrix resort to an adjacency matrix to represent . In this case, the matrix rank equals to , i.e, the value range of the map function. To keep the memory usage of the graph sketch within (Condition 2 in Definition 3), must be less than , that means for a sparse streaming graph. According to our theoretical analysis22 2 The detailed analyses are given in Section VI-B in Figure 3, the query results’ accuracy is quite low in them. Our experiments in Section VII also confirm the theoretical analysis.
Considering the above limitations, we design a novel data structure for graph stream summarization, called GSS.
Definition 5
GSS: Given a streaming graph , we have a hash function with value range to map each node in graph to node in graph sketch . Then we use the following data structure to represent the graph sketch :
- 1.
consists of a size adjacency matrix and an adjacency list buffer for left-over edges.
- 2.
For each node in sketch graph , we define an address and a fingerprint where and , .
- 3.
Each edge in the graph sketch is mapped to a bucket in the row , column of the matrix . We record in the corresponding bucket of the matrix, where is the edge weight and , are fingerprints of the two endpoints.
- 4.
Adjacency list buffer records all left-over edges in , whose expected positions in the matrix have been occupied by other previous inserted edges already.
When implementing a GSS for a graph stream, in order to satisfy the memory cost requirement, we usually set , where should be a constant approximate to . To achieve high accuracy, we set . This can be achieved by setting large , in other words, using long fingerprints. When the memory is not sufficient, we can also set smaller with smaller and , but this will decrease the accuracy.
Example 3
We discuss the insertion and primitive query operations over GSS as follows:
Edge Updating: When a new item comes in the graph stream , we map it to an edge with weight in graph sketch . Then we find the bucket in row , column . If the bucket is empty, we store the fingerprints pair together with the edge weight in the bucket. If it is not empty, we compare the fingerprint pair of this edge with the fingerprint pair that is in the bucket already. If they are same, we add the weight to the existing one; otherwise, it means this bucket has been occupied by other edges, and we store edge in the adjacency list in the buffer . We call this kind of edges as left-over edges.
Graph Query Primitives: The three primitives (defined in Definition 4) are all supported with our proposed data structure GSS.
Edge Query: Given an edge query , we work as follows. We check the bucket in row , column in the matrix. Let be the fingerprint pair stored at the bucket. If equals to the the fingerprint pair of edge , we return the weight in the bucket. Otherwise we search the buffer for edge using the adjacency list. If we cannot find it in the matrix or in the buffer , we return , i.e. reporting that the edge does not exists.
-hop Successor Query: To find the 1-hop successors of node , we work as follows. First, we search all buckets in row of the matrix . If a bucket in row and column has a fingerprint pair , we add node to the 1-hop successors set . After that, we also need to search the buffer area to find all edges with source node , and add its destination node to the 1-hop successors set . We return if we find no result, i.e., . Otherwise, for each in successors set , we obtain the original node IDs by accessing the hash table.
-hop Precursor Query: To find the 1-hop precursors of node , we have the analogue operations with -hop Successor Query if we switch the columns and the rows in the matrix . The details are omitted due to space limit.
In GSS, we store edges with different source nodes in in one row of the matrix, because the graph is sparse and each node is usually connected to very few edges. We can use fingerprints to distinguish them. For example, edge and edge are all stored in row , but they have different source node fingerprints, namely and , thus we know exactly which nodes they are from. It is similar in columns. Fingerprints also help us to distinguish edges when they are mapped into the same bucket. This enables us to apply a map function with a much larger value range, and generate a much larger graph sketch with the same size of matrix as TCM. With a matrix as in Figure 2, TCM can only support a map function with , and the number of nodes in the graph sketch will be no more than , thus the accuracy will he much poorer.
V GSS: Augmented Algorithm
As we know, GSS has two parts: a size matrix and an adjacency list buffer for left-over edges. Obviously, we only need time to insert an edge into , but the linear time if the edge must goto the buffer , where represents the number of all left-over edges. Therefore both influences the memory and time cost. In this section, we design several solutions to reduce the size of buffer .
V-A Square Hashing
In the basic version, an edge is pushed into buffer if and only if its mapped position in the matrix has been occupied. The most intuitive solution is to find another bucket for it. Then where to find an empty bucket? We further notice the skewness in node degrees. In the real-world graphs, node degrees usually follow the power law distribution. In other words, a few nodes have very high degrees, while most nodes have small degrees. Consider a node that has out-going edges in the graph sketch . For a adjacency matrix in GSS (see Definition 5), there are at least edges that should be inserted into buffer , as these edges must be mapped to the same row (in ) due to the same source vertex . These high degree nodes lead to crowed rows and result in most left-over edges in buffer . On the other hand, many other rows are uncrowded. We have the same observation for columns of matrix . Is it possible to make use of the unoccupied positions in uncrowded rows/columns? It is the motivation of our first technique, called square hashing.
For each node with ID in , we compute a sequence of hash addresses for it. Edge is stored in the first empty bucket among the buckets with addresses
where is the row index and is the column index. We call these buckets mapped buckets for convenience. Note that we consider row-first layout when selecting the first empty bucket.
Example 4
An example of square hashing is shown in Figure 5. The inserted edge is mapped to buckets, and the first 2 with address and have been already occupied. Therefore the edge is inserted in the third mapped bucket. In the bucket, we store the weight, the fingerprint pair, together with an index pair which indicates the position of this bucket in the mapped buckets sequence. We will talk about the use of index pair later.
The following issue is how to generate a good hash address sequence for a vertex . There are two requirements:
Independent: For two nodes and , we use to represent the probability that . Then we have . In other words, the randomness of each address in the sequence will not be influenced by others. This requirement will help to maximize the chance that an edge finds an empty bucket among the mapped buckets.
Reversible: Given a bucket in row and column and the content in it, we are able to recover the representation of the edge in the graph sketch : , where is the edge in that bucket. This property of indexing is needed in the 1-hop successor query and the 1-hop precursor query. As in these queries, we need to check the potential buckets to see if they contain edges connected to the queried node and retrieve the other end point in each qualified bucket.
To meet the above requirements, we propose to use linear congruence method[22] to generate a sequence of random values with as seeds. We call this sequence the linear congruential (LR) sequence for convenience. The linear congruence method is as following: select a timer , small prime and a module , then
| (1) |
By choosing , and carefully, we can make sure the cycle of the sequence we generate is much larger than , and there will be no repetitive numbers in the sequence [22]. Then we generate a sequence of hash addresses as following:
| (2) |
When storing edge in the matrix, besides storing the pair of fingerprints and the edge weight, we also store an index pair , supposing that the bucket that contains this room has an address . As the length of the sequence, , is small, the length of each index will be less than bits. Therefore storing such a pair will cost little.
Note that the hash sequence generated by the linear congruence method are both independent and reversible. The independence property has been proved in [8]. We show how to recover the original hash value based on the , and the index as follows. First, we compute the LR sequence with following equation 4. Second we use the equation to compute the original hash address . As , the equation has unique solution. At last we use to compute . Given a bucket in the matrix, the fingerprint pair and the index pair are all stored in it, and we have , , where and are the row index and the column index of the bucket in the matrix, respectively. Therefore we can retrieve both and as above.
Example 5
Compared to the basic version, in the modified version all edges are stored in the matrix, and the number of memory accesses we need to find an edge in the matrix is within . In fact in the example we only need one memory access to find most edges, and for a few ones.
In the following, we illustrate the four basic operators in this data structure GSS.
Edge Updating: When a new item comes in the graph stream , we map it to edge in the graph sketch with weight . Then we compute two hash address sequences and and check the mapped buckets with addresses one by one. For a bucket in row and column , if it is empty, we store the fingerprint pair and the index pair and weights in it, and end the procedure. If it is not empty, we check the fingerprint pair and the index pair stored in the bucket. If the fingerprint pair and the index pair are all equal to the corresponding pairs of the new inserted edge , we add to the weights in it, and end the procedure. Otherwise it means this bucket has been occupied by other edges and we consider other hash addresses following the hash sequence. If all buckets have been occupied, we store edge with weight in the buffer , like the basic version of GSS.
Graph Query Primitives: The three graph query primitives are supported in the modified data structure as follows:
Edge Query: When querying an edge , we map it to edge in the graph sketch, and use the same square hashingmethod to find the mapped buckets and check them one by one. Once we find a bucket in row and column which contains the fingerprint pair and the index pair , we return its weight as the result. If we find no results in the buckets, we search the buffer for edge and return its weights. If we still can not find it, we return .
1-hop Successor Query: to find the 1-hop successors of node , we map it to node in . Then we compute its hash address sequence according to , and check the rows with index . If a bucket in row , column contains fingerprint pair and index pair where is any integer in range and is any integer in range , we use , and to compute as stated above. Then we add to the 1-hop successor set . After searching the rows, we also need to check the buffer to see if there are any edges with source node and add their destination node to . We return if we find no result, otherwise we obtain the original node IDs from by accessing the hash table .
1-hop Precursor Query: to answer an 1-hop precursor query, we have the analogue operations with -hop Successor Query if we switch the columns and the rows in the matrix . The details are omitted due to space limit.
After applying square hashing, the edges with source node in are on longer stored in a single row, but spread over rows with addresses . Similarly, edges with destination node are stored in the different columns. These rows or columns are shared by the edges with different source nodes or destination nodes. The higher degree a node has, the more buckets its edges may take. This eases the congestion brought by skewness in node degrees. Moreover, as each bucket has multiple mapped buckets, it has higher probability to find an empty one. Obviously, square hashing will reduce the number of left-over edges.
V-B Further Improvements
There are some other improvements which can be implemented to GSS.
V-B1 Mapped Buckets Sampling
In the modified version of GSS, each edge has mapped buckets. We usually set to integers from to . When the skewness of node degrees is serious, can be larger. If we check all the buckets when inserting an edge, it will be time consuming. To improve the updating speed, which is very important for graph stream summarization, we can use a sampling technique to decrease the time cost. Instead of check all the buckets, we select buckets as a sample from the mapped buckets, we call these buckets candidate buckets for short. For each edge we only check these buckets in updating and query, and the operations are the same as above. The method to select these buckets for an edge is also a linear congruence method. We add the fingerprint of the source node and the destination node of to get a seed , then we compute a length sequence as
| (4) |
where , and are the same integers used above. We choose the buckets with address
| (5) |
and are the hash address sequence of the source node and the destination node, respectively.
V-B2 Multiple Rooms
When the memory is sufficient, we do not need to use multiple matrices to increase accuracy as TCM, as the accuracy is already very high. Instead, in order to further decrease the buffer size, we can separate each bucket in the matrix into segments, and each segments contains an edge, including the weight, the fingerprint pair and the index pair. We call each segment a room for convenience. When performing the basic operators, we use the same process as above the find the buckets we need to check, and search all the rooms in them to find qualified edges or empty rooms.
However, when the rooms in each bucket are stored separately, the speed will probably decrease, as we can not fetch the rooms in one memory access in most cases, and multiple memory accesses increase the time cost. As shown in Fig. 7, we separate the bucket into area: the index area, the fingerprint area, and the weight area. Each area contains the corresponding parts of the rooms. When we check this bucket to find certain edges, we can first check all the index pairs. If we find a matched index pair, we check the corresponding fingerprint pair, and if the fingerprint pair is also matched, we fetch the corresponding weights. If we do not find any matched index pair, we can just move on and do not need to check the fingerprint pairs any more. As the index pairs are very small, usually no more than byte, we can fetch all the index pairs in one memory access. This will omit a lot of unnecessary memory accesses.
VI Analysis
VI-A Memory and Time Cost Analysis
As stated above, GSS has memory cost and constant update speed. The memory cost of GSS is , to be precise, where is the number of edges in the graph sketch and is the size of buffer. When we use hash table to store the original ID, additional memory is needed, but the overall memory cost is still . The update time cost is , where is the number of sampled buckets and is a small constant. When an edge is stored in the matrix, we only need to check at most candidate buckets, which takes time. Each edge has probability to be stored in the buffer. When it is stored in the buffer, the update takes additional time, as the buffer is an adjacency list. In implementations the buffer stores edges in most cases, which will be shown in section VI-D and VII-G. Therefore is also a small constant. When it is necessary to store the ID of nodes in applications, one insertion to the hash table is needed, which also takes constant time. Overall, the update time cost is .
The time cost of queries is based on the algorithms we use. We consider the time cost of the operators as an evaluation. The time cost of the edge query operator is the same as the update, and the time cost of the 1-hop successor query and 1-hop precursor query is , where is the side length of the matrix and is the length of the hash address sequence.
VI-B Accuracy Analysis
In this part we evaluate the accuracy of GSS. Before we analyze the probability of errors, we first propose the following theorem:
Theorem 1
The storage of the graph sketch in the data structure of GSS is accurate. Which means for any edge and in , the weights of them will be added up if and only if .
As the buffer is an adjacency list that stores edges in accurately, we only need to check the matrix. If we want to prove the storage of the graph sketch is accurate, we need to prove that if such collision happens to and , we have in , in other words, .We assume that the bucket contains the wights of and is in row and column in the matrix. Obviously and must have the same fingerprint pair, otherwise it will be easy for us to differentiate them. With the same fingerprints, these two edges will produce the same LR sequences and . Moreover, this bucket must have the same index pair for these two edges, and we represent this pair with . Then we have
| (6) |
and
| (7) |
With these equations, we can get that , when . With the same fingerprint pair and hash values, we have , . and are the same edge in . Therefore the storage of is accurate.
This theorem means we only need to consider the procedure of mapping to , as all errors happen in this procedure. We use to represent the probability of the following event:
Definition 6
Edge Collision: An edge collision means that given an edge , there is at least one in and which satisfies in the compressed graph .
We set , and is the main component of the error rate of all the graph query primitives.
In the edge query, is just the correct rate. In the 1-hop successor query for a node , the correct rate is , where is the number of nodes in , and is the out-degree of the queried node. Because we will get a correct answer if and only if for each in which is not a 1-hop successor of , does not collide with any existing edges, and the probability of such an event is . It is the same in the 1-hop precursor query. Therefore we need to compute to evaluate the accuracy of GSS.
VI-C Collision Rate
Now we show the probability that an edge suffers from edge collision, . For in , we assume there are edges with source node or destination node in besides , and there are totally edges in . We represent the size of the value range of the map function with .
For an edge share no common endpoints with , it will collide with when both its source node and destination node collide with the corresponding node of . The probability that it collides with in map function is:
| (8) |
The probability that all the edges have no collisions with is
| (9) |
For those edges connected to , as one of the two end points is the same, the probability that such an edge has a collision with is
| (10) |
The probability that all the edges have no collisions with is
| (11) |
Therefore the correct rate of , in other words, all the edges do not have collisions with in mapping is
| (12) | ||||
And . In GSS we have , where is the length of the matrix, and is the maximum size of the fingerprints. The above correct rate is usually very high in applications. For example, suppose that the fingerprints we use are -bit, in other words, , and when querying an edge , we have ,. We use a matrix with side length . Then the correct rate of this edge query is . On the other hand, in TCM the accuracy analysis is the same as GSS but we have . This lead to the difference on accuracy with the same size of matrix. With the same matrix size, TCM only has a probability of to get a correct weight for .
VI-D Buffer Size Analysis
After all the improvements, the buffer in GSSis very small. The mathematical expression of the buffer size is very complicated and is influenced by many details of the graph. Therefore we give an expression of the probability that a new edge becomes a left-over edge, which means inserted into the buffer, as a measurement. Assuming that there are already different edges in the graph stream, and among them edges have common source node or common destination node with . The length of the matrix is , and each bucket in the matrix has rooms. For each node we compute a hash address sequence with length . For each edge we choose candidate buckets among the mapped buckets. Then the probability that becomes a left-over edge is: For each candidate bucket of , as the non-adjacent edges are randomly inserted into the matrix with area , the probability that there are non-adjacent edges inserted into it is:
| (13) | ||||
As the adjacent edges are randomly inserted in an area of ( rows or columns in the matrix), the probability that there are adjacent edges inserted into this bucket is:
| (14) | ||||
The probability that there are already edges inserted into this bucket is:
| (15) |
The probability that there are less than edges inserted into this bucket is:
| (16) | ||||
This is also the lower bound that the bucket is still available for . The probability that can not be inserted into the matrix is the probability that all the candidate buckets are not available, which is:
| (17) |
where
| (18) |
Notice that this is an upper bound as we ignore collisions in the map procedure from to . This probability is rather small. For example if , , we still set the side length of the matrix to , and set , , , the upper bound probability of insertion failure is only . Experiments show that when the size of matrix is nearly equal to the number of edges, there will be almost no edges inserted into the buffer.
VII Experimental Evaluation
In this section, we show our experimental studies of GSS. We compare GSS with TCM on the three graph query primitives: edge query , 1-hop successor query, 1-hop precursor query (VII-D) and two compound queries, node queries (VII-E) and reachability queries (VII-F). We also evaluate the size of buffer (VI-D)and update speed of GSS (VII-H). Then we further compare GSS with the state-of-the-art graph processing algorithms on triangle counting and subgraph matching VII-I.
All experiments are performed on a server with dual 6-core CPUs (Intel Xeon CPU E5-2620 @2.0 GHz, 24 threads) and 62 GB DRAM memory, running Ubuntu. All algorithms including GSS and TCM are implemented in C++.
VII-A Data Sets
We choose three real world data sets. Details of three data sets are described as follows:
1)email-EuAll 33 3 http://snap.stanford.edu/data/email-EuAll.html.This data set is communication network data generated using email data from a large European research institution for a period of 18 months. Each node in the directed graph corresponds to an email address. Each edge between node src and dst represents src sent at least one email to dst. The directed graph contains 265214 nodes and 420045 edges. We use the Zipfian distribution to add the weight to each edge and the edge weight represents the appearance times in the stream.
2)cit-HepPh44 4 http://snap.stanford.edu/data/email-EuAll.html.It is the Arxiv HEP-PH (high energy physics phenomenology) citation graph. If a paper src cites paper dst, the data set contains a directed edge from src to dst. The data set covers 34,546 papers as nodes with 421,578 edges. The edge weights are also added using Zipfian distribution.
3)web-NotreDame 55 5 http://konect.uni-koblenz.de/networks/lkml-reply.It is a web graph collected from the University of Notre Dame. Nodes represent web pages and directed edges represent hyperlinks between pages. The data set contains 325729 nodes and 1497134 edges. We use the Zipfian distribution to generate weights for the edges in the data set, and insert the edges into the data structure one by one to simulate the procedure of real-world incremental updating.
4)lkml-reply66 6 http://konect.uni-koblenz.de/networks/lkml-reply.It is a collection of communication records in the network of the Linux kernel mailing list. It contains 63399 email addresses (nodes) and 1096440 communication records(edges). Each edge is weighted by its frequency in the data set, and has a timestamp indicating the communication time. We feed the data items to the data structure according to their timestamps to simulate a graph stream.
5)Caida-networkflow 77 7 www.caida. org It is the “CAIDA Internet Anonymized Traces 2015 Dataset”. It contains 445440480 communication records (edges) concerning 2601005 different IP addresses (nodes). Each edge is weighted by its frequency in the data set, and has a timestamp indicating the communication time. We feed the data items to the data structure according to their timestamps to simulate a graph stream.
The function we use to cumulate the edge weights is addition. In this case, TCM and GSS only have over-estimations. The codes are open sourced88 8 https://github.com/Puppy95/Graph-Stream-Sketch
VII-B Metrics
In this part we give a definition of the metrics we use in experiments.
Average Relative Error (ARE): ARE measures the accuracy of the reported weights in edge queries and node queries. Given a query , the relative error is defined as
where and are the real answer and the estimated value of . When giving a query set, the average relative error () is measured by averaging the relative errors over all queries int it. A more accuracy data structure will have smaller .
Average Precision We use average precision as the evaluation metric in 1-hop successor queries, 1-hop precursor queries and graph pattern matching. Given such a query , we use to represent the accurate set of 1-hop successors / precursors of the queried node , and to represent the set we get by . As TCM and GSS、 have only false positives, which means , we define the precision of as:
Average precision of a query set is the average value of the precision of all queries in it. A more accuracy data structure will have higher Average Precision
True Negative Recall: It measures the accuracy of the reachability query. Because connectives of all edges are kept, there is no false negatives in TCM and GSS, which means if we can travel to from in the streaming graph, the query result of these data structures will be definitely yes. Therefore in experiments we use reachability query sets where , source node and destination node in are unreachable. True negative recall is defined as the number of queries reported as unreachable divided by the number of all queries in .
Buffer Percentage: It measures buffer size of GSS. Buffer percentage is defined as the number of edges that the buffer contains divided by the total number of edges in the graph stream.
VII-C Experiments settings
In experiments, we implement two kinds of GSS with different fingerprint sizes: 12 bits and 16 bits, and vary the matrix size. We use fsize to represent the fingerprint size by short. We apply all improvements to GSS, and the parameters are as follows. Each bucket in the matrix contains rooms. The length of the address sequences is , and the number of candidate buckets for each edge is (, for the small data set email-EuAlland cit-HepPh). As for , we apply graph sketches to improve its accuracy, and allow it to use larger memory, because otherwise the gap between it and GSS will be so huge that we can hardly compare them in one figure. In edge query primitives, we allow TCM to use times memory, and in other queries we implement it with times memory, as its accuracy is too poor in these queries (in web-NotreDame, we implement it with times memory because of the limitation of the memory of the server). This ratio is the memory used by all the 4 sketches in TCM divided by the memory used by GSS with 16 bit fingerprint. When the size of GSS varies, the size of matrix in TCM also varies correspondingly to keep the ratio unchanged.
VII-D Experiments on query primitives
In this section, we evaluate the performance of GSS in the 3 basic graph query primitives: the edge query, the 1-hop precursor query and the 1-hop successor query. Figure 8, Figure 9, and Figure 10 show that ARE of edge queries and average precision of 1-hop precursor / successor queries for the data sets, respectively. To reduce random error introduced by the selection of the data sample, the edge query set contains all edges in the graph stream, and the 1-hop precursor / successor query set contains all nodes in the graph stream. The results tell us that GSS performs much better in supporting these query primitives than TCM, especially in the 1-hop precursor / successor query primitives. In both GSS and TCM, the ARE decreases, and the precision increases with the growth of the width of the matrix. This trend is not very significant in GSS as the accuracy is high and there are no errors in most experiments. Also, when the length of fingerprint becomes longer, the accuracy of GSS increases.
VII-E Experiments on Node Query
In this section, we evaluate the performance of GSS in estimating the accuracy of node query. A node query for a node is to compute the summary of the weights of all edges with source node . For each dataset, node query set contains all nodes in the graph stream. Figure 11 shows the ARE of node queries in data sets email-EuAll, cit-HepPh and web-NotreDame, respectively. The figure shows that although we unfairly fix the ratio of memory used by TCM and GSS, GSS still can achieve better performance than TCM.
VII-F Experiments on Reachability Query
In this section, we evaluate the performance of GSS in supporting reachability queries. Each reachability query set contains 100 unreachable pairs of nodes which are randomly generated from the graph.
Figure 12 shows the true negative recall of reachability query for the data sets email-EuAll, cit-HepPh and web-NotreDame, respectively. From the figures we can see that the accuracy of GSS is much higher than TCM even when TCM uses much larger memory. The gap varies with the size of the graph. Along with increasing the memory and the length of the fingerprint, GSS can achieve better performance. We can also see that the accuracy of TCM is so poor that it can barely support this query.
VII-G Experiments on Buffer Size
Figure 13 shows the buffer percentage for the three larger data sets web-NotreDame,lkml-replyand Caida-networkflow. The four curves in the figure represent 1)GSS with 1 room in each bucket and no square hashing. 2) GSS with 2 rooms in each bucket and no square hashing. 3) GSS with 1 room in each bucket and square hashing. 4) GSS with 2 rooms in each bucket and square hashing. The x-label, , is the side length of the matrices for the schemes with rooms in each bucket. When GSS has 1 room in each bucket, the width of the matrix is times larger to make the memory unchanged. The above results show that the decrement in buffer size brought by using square hashing and multiple rooms is significant, especially the square hashing. The results also show that the buffer percentage in the fully improved GSS (2 rooms each bucket, with square hashing) becomes in most experiments when the matrix size is close to . In this case, the overhead brought by the insertion failure in the matrix is nearly 0.
VII-H Experiment on update speed
In this section we evaluate the update speed of GSS. We compare the update speed of GSS, TCM and adjacency lists, the result is shown in Table I. The adjacency list is accelerated using a map that records the position of the list for each node. Because the update speed changes little with the matrix size, we only show the average speed here. The fingerprint size is 16-bit. TCM is still implemented with the same settings as above experiments. In each data set we insert all the edges into the data structure, repeat this procedure 100 times and calculate the average speed. The unit we use is Million Insertions per Second (Mips). From the figure we can see that the speed of GSS is similar to TCM, because though more memory accesses are needed, GSS computes less hash functions. Both of them are much higher than the adjacency list. We also show the speed of GSS without candidate bucket sampling. We can see that the speed without candidate sampling is lower than the full optimized one. The gap is not very large because most edges find empty bucket in few searches.
| Data Structure | email-EuAll | cit-HepPh | web-NotreDame |
|---|---|---|---|
| GSS | |||
| GSS(no sampling) | |||
| TCM | |||
| Adjacency Lists |
VII-I Experiment on Other Compound Queries
We compare GSS with state-of-the-art graph processing algorithms in triangle counting and subgraph matching in this Section. We compare GSS with TRIEST [23] in triangle counting with the same memory. We use relative error between the reported results and the true value as evaluation metrics. TRIEST does not support multiple edges. Therefore we unique the edges in the dataset for it. The results are shown in Figure 14. The results show that they achieve similarly high accuracy with relative error less than . We compare GSS with SJ-tree[24] in subgraph matching. As SJ-tree is an accurate algorithm, we set GSS to of its memory. We use VF2 algorithm when querying in GSS, other algorithms can also be used. We use web-NotreDame and search for subgraphs in windows of the data stream. The edges in the graph are labeled by the ports and the protocol. We carry out experiment on window sizes, and for each window size, we randomly select windows in the stream. In each window, we generate kinds of subgraphs with , , and edges and instances in each kind by random walk. We use the correct rate as evaluation metrics, which means the percentage of correct matches in the matches for each window size. Experimental results are shown in Figure 15. We can see that GSS has nearly correct rate. Both TRIEST an SJ-tree have throughput less than edges per second, much lower than the update speed of GSS, and high update speed is important in high speed streams.
VIII Conclusion
Graph stream summarization is a problem rising in many fields. However, as far as we know, there are no prior work that can support all kinds of queries with high accuracy. In this paper, we propose graph stream summarization data structure Graph Stream Sketch (GSS). It has memory usage where is the number of edges in the graph stream, and update speed. It supports almost queries based on graphs and has accuracy which is higher than state-of-the-art by magnitudes. Both mathematical analysis and experiment results confirm the superiority of our work.
References
- [1] S. Guha and A. McGregor, “Graph synopses, sketches, and streams: A survey,” PVLDB, vol. 5, no. 12, pp. 2030–2031, 2012.
- [2] G. Cormode and S. Muthukrishnan, “An improved data stream summary: The count-min sketch and its applications,” in Latin American Symposium on Theoretical Informatics, pp. 29–38, 2004.
- [3] C. Estan and G. Varghese, “New directions in traffic measurement and accounting: Focusing on the elephants, ignoring the mice,” ACM Transactions on Computer Systems (TOCS), vol. 21, no. 3, pp. 270–313, 2003.
- [4] P. Roy, A. Khan, and G. Alonso, “Augmented sketch: Faster and more accurate stream processing,” in SIGMOD, pp. 1449–1463, ACM, 2016.
- [5] D. Thomas, R. Bordawekar, C. C. Aggarwal, and S. Y. Philip, “On efficient query processing of stream counts on the cell processor,” in ICDE, pp. 748–759, IEEE, 2009.
- [6] P. Zhao, C. C. Aggarwal, and M. Wang, “gsketch: on query estimation in graph streams,” PVLDB, vol. 5, no. 3, pp. 193–204, 2011.
- [7] N. Tang, Q. Chen, and P. Mitra, “Graph stream summarization: From big bang to big crunch,” in SIGMOD, pp. 1481–1496, 2016.
- [8] A. Khan and C. Aggarwal, “Query-friendly compression of graph streams,” in IEEE/ACM International Conference on Advances in Social Networks Analysis and Mining, pp. 130–137, 2016.
- [9] M. Elkin, “Streaming and fully dynamic centralized algorithms for constructing and maintaining sparse spanners,” in ICALP, pp. 716–727, Springer, 2007.
- [10] V. Braverman, R. Ostrovsky, and D. Vilenchik, “How hard is counting triangles in the streaming model?,” in ICALP, pp. 244–254, Springer, 2013.
- [11] J. Feigenbaum, S. Kannan, A. McGregor, S. Suri, and J. Zhang, “On graph problems in a semi-streaming model,” Theoretical Computer Science, vol. 348, no. 2-3, pp. 207–216, 2005.
- [12] J. E. Gonzalez, R. S. Xin, A. Dave, D. Crankshaw, M. J. Franklin, and I. Stoica, “Graphx: Graph processing in a distributed dataflow framework.,” in OSDI, vol. 14, pp. 599–613, 2014.
- [13] J. E. Gonzalez, Y. Low, H. Gu, D. Bickson, and C. Guestrin, “Powergraph: distributed graph-parallel computation on natural graphs.,” in OSDI, vol. 12, p. 2, 2012.
- [14] G. Malewicz, M. H. Austern, A. J. Bik, J. C. Dehnert, I. Horn, N. Leiser, and G. Czajkowski, “Pregel: a system for large-scale graph processing,” in SIGMOD, pp. 135–146, ACM, 2010.
- [15] Y. Low, D. Bickson, J. Gonzalez, C. Guestrin, A. Kyrola, and J. M. Hellerstein, “Distributed graphlab: a framework for machine learning and data mining in the cloud,” PVLDB, vol. 5, no. 8, pp. 716–727, 2012.
- [16] S. Raghavan and H. Garcia-Molina, “Representing web graphs,” in ICDE, pp. 405–416, IEEE, 2003.
- [17] W. Fan, J. Li, X. Wang, and Y. Wu, “Query preserving graph compression,” in SIGMOD, pp. 157–168, ACM, 2012.
- [18] D. A. Spielman and N. Srivastava, “Graph sparsification by effective resistances,” SIAM Journal on Computing, vol. 40, no. 6, pp. 1913–1926, 2011.
- [19] J. Gao, C. Zhou, J. Zhou, and J. X. Yu, “Continuous pattern detection over billion-edge graph using distributed framework,” in ICDE, pp. 556–567, IEEE, 2014.
- [20] C. Wang and L. Chen, “Continuous subgraph pattern search over graph streams,” in ICDE, pp. 393–404, IEEE, 2009.
- [21] C. Song, T. Ge, C. Chen, and J. Wang, “Event pattern matching over graph streams,” PVLDB, vol. 8, no. 4, pp. 413–424, 2014.
- [22] P. L’Ecuyer, “Tables of linear congruential generators of different sizes and good lattice structure,” Mathematics of Computation, vol. 68, no. 225, pp. 249–260, 1999.
- [23] L. D. Stefani, A. Epasto, M. Riondato, and E. Upfal, “Triest:counting local and global triangles in fully-dynamic streams with fixed memory size,” in ACM SIGKDD International Conference on Knowledge Discovery and Data Mining, pp. 825–834, 2016.
- [24] S. Choudhury, L. Holder, G. Chin, K. Agarwal, and J. Feo, “A selectivity based approach to continuous pattern detection in streaming graphs,” Computer Science, vol. 93, no. 8, pp. 939–945, 2015.