0

I build a smart contract on solidty and website with Nethereum.

One of variable include the current status of all the users like this :

mapping(address => Status) public StatusUsers;

I did a loop(offchain) and call this public variable to get the status of all users that take 9 seconds for 31 wallets address .

The problem that I need to call the variable for every address to get the current status and its very very slow.

If someone can help me and find a better way and much faster .

Thanks you.

5
  • Can you share your offchain code?
    – Ha ĐANG
    Oct 29 '18 at 7:39
  • public static async Task<List<Status>> getAllStatusUsers(List<Status> s) { ---initweb3 -- code --------------- var StatusUsersFunction = contract.GetFunction("StatusUsers"); StatusUser statusUserService; for (int i = 0; i < s.Count; i++) { statusUserService = await StatusUsersFunction.CallDeserializingToObjectAsync<StatusUser>(s[i].address); s[i].state=statusUserService.state; } return s; } Oct 29 '18 at 7:49
  • I gave you a part of the code because is too long to show . but the most important is inside the loop. Oct 29 '18 at 7:51
  • I want to see the code that get value for s array s[i].address because it might the cause to make the program slow
    – Ha ĐANG
    Oct 29 '18 at 7:54
  • s[i].address is list of address offchain on database is faster, I debug the code, the cause to make the program slow is this line .statusUserService = await StatusUsersFunction.CallDeserializingToObjectAsync<StatusUser>(s[i].publickey); When I call the variable from the blockchain is not instantly and when you do a loop of 31 address it takes a total of 9 seconds. Oct 29 '18 at 8:00
1

I figurerd it out and found a solution based Tasks in C#.

By replacing await with Task.WaitAll I'm able to run all the requests concurrently.

        StatusUser statusUserService;

        List<Task<StatusUser>> tasks = new List<Task<StatusUser>>();

        for (int i = 0; i < s.Count; i++)
        {
            tasks.Add(StatusUsersFunction.CallDeserializingToObjectAsync<StatusUser>(s[i].address));                
        }

        Task.WaitAll(tasks.ToArray());

        for (int i = 0; i < s.Count; i++)
        {
            Status status = new Status();
            statusUserService = tasks[i].Result;

            // -- code --

        }
        return s;
    }
0

The slowness is due to the fact that you're doing one by one requests ( most likely using an HTTP Provider ).

There are ways you can speed things up:

1 - Use the WS Provider instead of HTTP

  • Speeds things up because it does not need to recreate the connection to the node for each request you make.

2 - You can "batch" your requests in one call, by using web3.BatchRequest see official docs.

  • Supports both HTTP and WS Providers ( WS is faster, see explanation at #1 ) and is faster because you just send 1 call to the node.

3 - Batch all requests into one call that is executed in one EVM instance using the Read A Lot method: see details

  • This is the fastest and most optimised version you can use. Because it bundles all calls into one binary call that is then executed in one EVM instance on the node.
2
  • 1
    it helps in general, but not entirely helpful for Nethereum
    – Aquila
    Oct 29 '18 at 14:02
  • My bad, did not notice the tag. Oct 29 '18 at 16:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.