Reduce memory allocations when generating the merkle root

When generating the merkle root, the previous code calls `malloc`
once for every transaction, which is not ideal for performance.

The new code allocates a 32 KiB buffer once and reuses it for all
transactions. If a TX is bigger than the current buffer size, the
buffer is reallocated with double the current buffer size.
This commit is contained in:
Axel Gembe 2020-11-10 16:30:53 +07:00
parent 173a497e60
commit 6661ca7e1b
No known key found for this signature in database
GPG key ID: 1CB3AA2143109AAC

View file

@ -351,6 +351,7 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
uint32_t target[8]; uint32_t target[8];
int cbtx_size; int cbtx_size;
unsigned char *cbtx = NULL; unsigned char *cbtx = NULL;
unsigned char *tx = NULL;
int tx_count, tx_size; int tx_count, tx_size;
unsigned char txc_vi[9]; unsigned char txc_vi[9];
unsigned char (*merkle_tree)[32] = NULL; unsigned char (*merkle_tree)[32] = NULL;
@ -581,6 +582,8 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
/* generate merkle root */ /* generate merkle root */
merkle_tree = malloc(32 * ((1 + tx_count + 1) & ~1)); merkle_tree = malloc(32 * ((1 + tx_count + 1) & ~1));
size_t tx_buf_size = 32 * 1024;
tx = malloc(tx_buf_size);
sha256d(merkle_tree[0], cbtx, cbtx_size); sha256d(merkle_tree[0], cbtx, cbtx_size);
for (i = 0; i < tx_count; i++) { for (i = 0; i < tx_count; i++) {
tmp = json_array_get(txa, i); tmp = json_array_get(txa, i);
@ -594,18 +597,21 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
} }
memrev(merkle_tree[1 + i], 32); memrev(merkle_tree[1 + i], 32);
} else { } else {
unsigned char *tx = malloc(tx_size); if (tx_size > tx_buf_size) {
free(tx);
tx_buf_size = tx_size * 2;
tx = malloc(tx_buf_size);
}
if (!tx_hex || !hex2bin(tx, tx_hex, tx_size)) { if (!tx_hex || !hex2bin(tx, tx_hex, tx_size)) {
applog(LOG_ERR, "JSON invalid transactions"); applog(LOG_ERR, "JSON invalid transactions");
free(tx);
goto out; goto out;
} }
sha256d(merkle_tree[1 + i], tx, tx_size); sha256d(merkle_tree[1 + i], tx, tx_size);
free(tx);
} }
if (!submit_coinbase) if (!submit_coinbase)
strcat(work->txs, tx_hex); strcat(work->txs, tx_hex);
} }
free(tx); tx = NULL;
n = 1 + tx_count; n = 1 + tx_count;
while (n > 1) { while (n > 1) {
if (n % 2) { if (n % 2) {
@ -662,6 +668,7 @@ static bool gbt_work_decode(const json_t *val, struct work *work)
rc = true; rc = true;
out: out:
free(tx);
free(cbtx); free(cbtx);
free(merkle_tree); free(merkle_tree);
return rc; return rc;