IssueFrom and Publish performance as asset number grows

+1 vote

Hi

I've noticed the performance of both the IssueFrom and Publish calls degrade significantly as the number of assets on the chain grows, even at relatively small numbers.

I found that the first issue command took 4ms, but the 10,000th issuance took over 100ms

My setup is a Node JS app and chain(single node) spun up with docker-compose. 

Multichain version is 1.0.5.

I have been using the multichain-node library but also tried my own code to directly talk to the chain. There wasn't much performance difference (my own code was actually a bit slower).

Apologies for the code snippet below but is there something I'm doing wrong? Any help would be appreciated.

async function issue(counter) {
  const assetId = uuid.v4().replace(/-/g, '');
  const metadata = {
    streamId: `streamId-${counter}`,
    cData: `c-${counter}`,
    lData: `l-${counter}`,
    sData: `s-${counter}`,
    mData: `m-${counter}`,
    dateCreated: new Date().toString(),
  };

  const body = JSON.stringify({ jsonrpc: '1.0', id: 'curltest', method: 'issuefrom', params: [MY_ADDRESS, MY_ADDRESS, assetId, 1, 1, 0, metadata] });

  const url = `http://${multichainHost}:8571`;
  const options = {
    url,
    method: 'POST',
    headers:
    {
      'content-type': 'text/plain',
    },
    auth: {
      user: 'user',
      pass: `${multichainPassword}`,
    },
    body,
  };

  const start = now();
  const response = await rp(options);
  const end = now();
  const duration = (end - start).toFixed(1);
  console.log(`${counter}, ${duration}`);
  return response.body;
}

async function directTest() {
  const nToCreate = 10000;
  for (let i = 0; i < nToCreate; i += 1) {
    await issue(i);
  }
}
asked Jul 10 by John
Please let me know if there is any other information I can provide

1 Answer

0 votes

Please check the utxocount value of getwalletinfo is not growing into the thousands. A likely explanation is that you are inflating the number of unspent transaction outputs being tracked by the wallet, because each time you issue an asset you are sending it to an address in the wallet, but that address does not have send permissions, so it cannot perform auto-combining of unspent outputs.

answered Jul 11 by MultiChain
Thanks for the reply. I know by default that all addresses can send and receive due to the anyon-can-send and anyone-can-receive Params being sent to true (and have tested). I'll be able to check utxocount on Monday when I get back to the office but can you think of any other possible causes? The address in question was also explicitly granted the issue permission. Thanks again for your help
Hi,

I've done some more investigation today and found that the performance does seem to be directly related to the utxocount which does increase over time, but also decrease thanks to the defaults of -autocombine.

Would you be able to check my configuration or help me debug further?

I've created a small sample for you to try: https://github.com/j-mccloskey/mc-performance-sample
It is a single command to run and instructions are in the README.md

The project I'm working on is looking at a test launch within the next month and aims to support 500,000 to 1 million assets across about 1000 users. Any help resolving these performance issues will be greatly appreciated
The issue is not the total number of assets in the chain, but rather the total number of different assets being held in an individual wallet. There's a limit to how many assets can be combined together in a single UTXO, which depends on the max-std-element-size blockchain parameter. But in any event with the current version of MultiChain you'll get slow performance if you hold a million different assets in a single node wallet. We'll be working to improve this in future but that's the situation for now.
Do you have a recommendation for the max number of different assets held by an individual wallet? Trying to understand roughly how many nodes would be required. We had planned to launch with 3 nodes but I suspect more will be required
One possible option I'm considering is issuing all these assets to an address not managed by the wallet and using rawtransactions and external key management to move them when needed.

In testing, issuing assets to an address outside the wallet (even if its watched using importaddress) is consistently fast and working out around 200 issuances a second.

I'm not sure if there are any major disadvantages to this approach but it currently seems like the best option
To answer both questions, we recommend no more than a few thousand different assets in a wallet. And yes, the approach of using raw transactions and external key management will solve your performance problems. You just need some kind of external database to manage the list of UTXOs.
...