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?
    – Tony Dang
    Oct 29, 2018 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, 2018 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, 2018 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
    – Tony Dang
    Oct 29, 2018 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, 2018 at 8:00

2 Answers 2

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, 2018 at 14:02
  • My bad, did not notice the tag. Oct 29, 2018 at 16:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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