rchain / rchain

Blockchain (smart contract) platform using CBC-Casper proof of stake + Rholang for concurrent execution.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

What a fast local loop can do?

hilltracer opened this issue · comments

Introduction

The purpose of this document is to show what speed up we can have when optimizing operations with local variables in rholang.
This work related with two documents:

Now each sending and receiving operation in Rholang is saved in the eventLog:
image

But for data processing, we can avoid local operations, as shown below.
image

But we need to learn how to detect local operations. This question is open.

Why need to avoid saving local values in the eventLog?

Because it's slow. We need to spend time for:

  • Serializing;
  • Hashing;
  • Sorting;
  • Refunding (We must refund the full cost for matched com events);

Also we need spend time and disc space to save in BlockStore and sending to the validators.

We can optimize the operations in the reducer (see the red and green entries in the picture below). But it still won't do much good for data processing.

image

Experimental results

Performance tests:
b5285b7
1 optimization step: removing serialization from charging:
93e416a
2 optimization step for Int: remove substituting and evaluating from List
No change
2 optimization step for List: remove substituting and evaluating from List
29f5c8c
2 optimization step for Map: optimization of Map
29f5c8c
3 optimization step: remove looping from eventLog
44ef594

Sum of Ints

for( @n, @x <= @"loop" ) {
  match (n == 0) {
    true  => @"$outcomeCh"!(x)
    false => @"loop"!((n - 1), x + n)
  }  
}  

image

Num Init 1 step: removing serialization from charging 3 step: remove looping from eventLog
100 882 839 369
200 999 927 437
300 1046 924 286
400 1026 937 277
500 1338 1219 253
600 1281 1304 296
700 1325 1147 212
800 1461 1129 223
900 1561 1213 245
1000 1578 1297 256
1100 1757 1437 280
1200 1833 1441 311
1300 2001 1540 325
1400 2190 1636 346
1500 2318 1805 372
1600 2575 1987 418
1700 2618 2088 391
1800 2740 2225 401
1900 2805 2334 463
2000 2957 2423 468

Append in List

@"loop"!($numberElements, []) |
for( @n, @x <= @"loop" ) {
  match (n == 0) {
    true  => @"$outcomeCh"!(x)
    false => @"loop"!((n - 1), x ++ [1])
  }  
}  

image

Num Init 1 step: removing serialization from charging 2 step: remove substituting and evaluating from List 3 step: remove looping from eventLog
100 1220 1316 923 401
200 1985 2521 1358 583
300 3443 3384 2387 420
400 6669 5889 3386 295
500 9898 8340 5115 261
600 13218 11495 7171 432
700 16926 15465 9649 250
800 22879 21679 11392 276
900 27612 28086 14510 311
1000 32345 35621 16901 327

Append in Map

@"loop"!($numberElements, {}) |
for( @n, @x <= @"loop" ) {
  match (n == 0) {
    true  => @"$outcomeCh"!(x)
    false => @"loop"!((n - 1), x.set(n,n))
  }  
}  

image

Num Init 1 step: removing serialization from charging 2 step: optimization of Map 3 step: remove looping from eventLog
100 3489 3006 1692 604
200 10377 9264 3660 558
300 24632 19869 6896 479
400 46370 35158 11343 429
500 67139 54624 17394 463
600 107936 78667 24792 546

Conclusions

If we want Rholang to be used for data processing, we must optimize the work with local variables. Otherwise, it is justified to use Rholang as an intermediate layer between the user program and storage.

Because when we drawing a cat:
image

We save all intermediat result in blockChain.
image