@@ -4,6 +4,8 @@ use std::{
4
4
cmp:: { max, min, Reverse } ,
5
5
collections:: { BTreeMap , BTreeSet , BinaryHeap , VecDeque } ,
6
6
} ;
7
+ use std:: fs:: File ;
8
+ use std:: io:: { BufWriter , Write } ;
7
9
8
10
pub ( crate ) type DependentTxsVec = SmallVec < [ TxId ; 1 ] > ;
9
11
@@ -35,6 +37,7 @@ pub(crate) struct TxDependency {
35
37
36
38
pub round : Option < usize > ,
37
39
pub block_height : u64 ,
40
+ tx_states : SharedTxStates ,
38
41
}
39
42
40
43
impl TxDependency {
@@ -46,6 +49,7 @@ impl TxDependency {
46
49
tx_weight : None ,
47
50
round : None ,
48
51
block_height : 0 ,
52
+ tx_states : Default :: default ( ) ,
49
53
}
50
54
}
51
55
@@ -64,6 +68,7 @@ impl TxDependency {
64
68
last_write_tx. insert ( location. clone ( ) , txid) ;
65
69
}
66
70
}
71
+ self . tx_states = tx_states;
67
72
}
68
73
69
74
/// Retrieve the optimal partitions based on the dependency relationships between transactions.
@@ -224,12 +229,14 @@ impl TxDependency {
224
229
counter ! ( "grevm.total_block_cnt" ) . increment ( 1 ) ;
225
230
}
226
231
let mut subgraph = BTreeSet :: new ( ) ;
232
+ let mut two = false ;
227
233
if let Some ( ( _, groups) ) = weighted_group. last_key_value ( ) {
228
234
if self . round . is_none ( ) {
229
235
let largest_ratio = groups[ 0 ] . len ( ) as f64 / num_remaining as f64 ;
230
236
histogram ! ( "grevm.large_graph_ratio" ) . record ( largest_ratio) ;
231
237
if groups[ 0 ] . len ( ) >= num_remaining / 2 {
232
238
counter ! ( "grevm.low_parallelism_cnt" ) . increment ( 1 ) ;
239
+ two = true ;
233
240
}
234
241
}
235
242
if groups[ 0 ] . len ( ) >= num_remaining / 3 {
@@ -240,16 +247,19 @@ impl TxDependency {
240
247
return ;
241
248
}
242
249
250
+ let mut longest_chain: Vec < TxId > = vec ! [ ] ;
243
251
// ChainLength -> ChainNumber
244
252
let mut chains = BTreeMap :: new ( ) ;
245
253
let mut visited = HashSet :: new ( ) ;
246
254
for txid in subgraph. iter ( ) . rev ( ) {
247
255
if !visited. contains ( txid) {
248
256
let mut txid = * txid;
249
257
let mut chain_len = 0 ;
258
+ let mut curr_chain = vec ! [ ] ;
250
259
while !visited. contains ( & txid) {
251
260
chain_len += 1 ;
252
261
visited. insert ( txid) ;
262
+ curr_chain. push ( txid) ;
253
263
let dep: BTreeSet < TxId > =
254
264
self . tx_dependency [ txid - num_finality_txs] . clone ( ) . into_iter ( ) . collect ( ) ;
255
265
for dep_id in dep. into_iter ( ) . rev ( ) {
@@ -259,6 +269,9 @@ impl TxDependency {
259
269
}
260
270
}
261
271
}
272
+ if curr_chain. len ( ) > longest_chain. len ( ) {
273
+ longest_chain = curr_chain;
274
+ }
262
275
let chain_num = chains. get ( & chain_len) . cloned ( ) . unwrap_or ( 0 ) + 1 ;
263
276
chains. insert ( chain_len, chain_num) ;
264
277
}
@@ -282,6 +295,47 @@ impl TxDependency {
282
295
counter ! ( "grevm.large_graph" , "type" => chain_type, "tip" => tip. clone( ) ) . increment ( 1 ) ;
283
296
if self . round . is_none ( ) {
284
297
info ! ( "Block({}) has large subgraph, type={}" , self . block_height, chain_type) ;
298
+ if two && chain_type == "chain" {
299
+ self . draw_dag ( weighted_group, longest_chain) ;
300
+ }
301
+ }
302
+ }
303
+ }
304
+
305
+ fn draw_dag ( & self , weighted_group : & BTreeMap < usize , Vec < DependentTxsVec > > , longest_chain : Vec < TxId > ) {
306
+ let file = File :: create ( format ! ( "dag/block{}.info" , self . block_height) ) . unwrap ( ) ;
307
+ let mut writer = BufWriter :: new ( file) ;
308
+ writeln ! ( writer, "[dag]" ) . unwrap ( ) ;
309
+
310
+ for txid in ( 0 ..self . tx_dependency . len ( ) ) . rev ( ) {
311
+ let deps: BTreeSet < TxId > = self . tx_dependency [ txid] . clone ( ) . into_iter ( ) . collect ( ) ;
312
+ for dep_id in deps. into_iter ( ) . rev ( ) {
313
+ writeln ! ( writer, "tx{}->tx{}" , txid, dep_id) . unwrap ( ) ;
314
+ }
315
+ }
316
+ writeln ! ( writer, "" ) . unwrap ( ) ;
317
+
318
+ let mut locations: HashSet < LocationAndType > = HashSet :: new ( ) ;
319
+ info ! ( "Block({}) has large subgraph, longest chain: {:?}" , self . block_height, longest_chain) ;
320
+ for index in 0 ..longest_chain. len ( ) - 1 {
321
+ let txid = longest_chain[ index] ;
322
+ let dep_id = longest_chain[ index + 1 ] ;
323
+ let rs = self . tx_states [ txid] . read_set . clone ( ) ;
324
+ let ws = self . tx_states [ dep_id] . write_set . clone ( ) ;
325
+ let mut intersection = HashSet :: new ( ) ;
326
+ for l in ws {
327
+ if rs. contains_key ( & l) {
328
+ intersection. insert ( l) ;
329
+ }
330
+ }
331
+ if locations. is_empty ( ) {
332
+ locations = intersection;
333
+ } else {
334
+ let join: HashSet < LocationAndType > = locations. intersection ( & intersection) . cloned ( ) . collect ( ) ;
335
+ if join. is_empty ( ) {
336
+ info ! ( "Block({}) has large subgraph, ==> tx{}: {:?}" , self . block_height, txid, locations) ;
337
+ }
338
+ locations = join;
285
339
}
286
340
}
287
341
}
0 commit comments