Skip to content

Conversation

TheBlueMatt
Copy link
Contributor

No description provided.

@pstratem pstratem mentioned this pull request Oct 23, 2015
void CCoinsViewCache::Uncache(const uint256& hash)
{
CCoinsMap::iterator it = cacheCoins.find(hash);
if (it != cacheCoins.end() && it->second.flags == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can do slightly better:
if (it != cacheCoins.end() && (((it->second.flags & CCoinsCacheEntry::DIRTY) == 0) || ((it->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned())))

This will also allow removing entries that were created and spent entirely within a cache.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such an entry should probably be removed without a call to Uncache, no?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh, right, and it already is... never mind!

@sipa
Copy link
Member

sipa commented Oct 26, 2015

Do you feel like pulling in sipa@4186ac9 ?

@TheBlueMatt
Copy link
Contributor Author

sipa@4186ac9 seems pretty nasty to me....completely clearing the cache when we add a transaction that pushes our cache over 90% usage seems like a really bad idea.

@sipa
Copy link
Member

sipa commented Oct 26, 2015 via email

@TheBlueMatt
Copy link
Contributor Author

Wiping the cache sounds like a dirty hack to me. I'd rather evict random elements until the cache is reasonably-sized than that.

@TheBlueMatt
Copy link
Contributor Author

Also, we should fix it to not dump the entire cache after each new block.

@sipa
Copy link
Member

sipa commented Oct 26, 2015 via email

@TheBlueMatt
Copy link
Contributor Author

Sure, making the cache smarter would be nice, but lets not rush to fix it with a dirty hack when we're not even gonna ship the fix for a few months anyway.

@sipa
Copy link
Member

sipa commented Oct 26, 2015 via email

@morcos
Copy link
Contributor

morcos commented Oct 26, 2015

Have you guys looked into how expensive all this work is?

@sipa Once we've made it so that you can't bloat memory usage with txs that aren't accepted (as accomplished by this pull) then it seems to me the right approach is to just set your maxmempool size low enough that the unknown and variable multiple of that that is the size of your cache is also small enough for you. IMHO, the default dbcache size is too small. I'm with @TheBlueMatt that it seems bad to randomly wipe it unless we think that'll be very rare.

I'd actually argue we might not even need to remove cache entries that are due to evicted tx's, because there is a relay cost that is paid to create those.

@@ -830,13 +842,17 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
view.SetBackend(viewMemPool);

// do we already have it?
if (view.HaveCoins(hash))
if (view.HaveCoins(hash)) {
vHashTxnToUncache.push_back(hash);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, then we might remove this transaction from the cache even though there may be in-mempool spends of it, right? I think we want some kind of check like you have in TrimToSize, where you only uncache if there's nothing in the mempool that spends it.

(Alternatively, if HaveCoins somehow reported whether any new caching happened, that might be helpful, but that seems like a harder change to make.)

@TheBlueMatt
Copy link
Contributor Author

Sure, if the eventual solution is to tweak FlushStateToDisk to be
smarter (LRU or some priority metric based on what's in mempool), then
that would be reasonable. I am, however, worried we'd merge it and
forget to tweak the coins cache, making it even easier (maybe, though
maybe there are easier ways anyway) for an attacker to cause lots of
random disk I/O.

On 10/26/15 05:17, Pieter Wuille wrote:

It's orthogonal. We need to enforce memory usage limits after each
transaction, so let's call the function to do that at that time.

How that function works is a different matter, and can be arbitrarily
improved later.

I don't understand your resistance here. I think it's the only solution.


Reply to this email directly or view it on GitHub
#6872 (comment).

@sipa
Copy link
Member

sipa commented Oct 27, 2015

I don't think it's worse than what we have. The cache will already be flushed on the next block.

@TheBlueMatt
Copy link
Contributor Author

Depends on which you find worse, memory usage or DB I/O. Because its easy to optimize for loading lots of crap into the cache, an attacker can obviously tickle the cache to make it do more DB I/O with sipa@4186ac9, but can cause an equivalent increase in memory usage without.

@sipa
Copy link
Member

sipa commented Oct 27, 2015

I think we should move to a model of thinking where exceeding some reasonable but fixed memory limit is equivalent in badness to crashing. People need to be able to rely on the memory usage to remain bounded. So if it's a choice between more I/O and that, I think the first is far better.

@TheBlueMatt
Copy link
Contributor Author

I think thats a fine idea...except that we're so far away from it, it seems a bit premature to be optimizing for it now.

@dcousens
Copy link
Contributor

concept ACK

@sipa
Copy link
Member

sipa commented Oct 27, 2015

Observation:

2015-10-27 20:49:07 dd310afee248d4699e462e5d3826e879cc19d1d2d34e9de0070811d1d5f6e64a from peer=15 was not accepted: rate limited free transaction (code 66)
2015-10-27 20:49:07 ATMT increases coincache by 159 (to 614694) KiB

So when ATMT rejects due to rate limiting, the coincache entries pulled in don't seem to be removed.

@sipa
Copy link
Member

sipa commented Oct 27, 2015

Observation:

2015-10-27 20:52:57 a94894230e8c647d11dc67c2f7d56e91913aab8c6b3f7257f36d2cea30ddfbeb from peer=5 was not accepted: non-mandatory-script-verify-flag (No error) (code 64)
2015-10-27 20:52:57 ATMT increases coincache by 329 (to 991099) KiB

@sipa
Copy link
Member

sipa commented Oct 27, 2015

My observations are likely explained by this patch not updating coinsCachedUsage, so the pcoinsTip->DynamicMemoryUsage() going off the charts.

@sipa
Copy link
Member

sipa commented Oct 27, 2015

New observation:

2015-10-27 21:27:43 cd55b134090117cc7fbf4ad8d1039642f1dd63460daa27c59d1c0ae2aba3e582 from peer=14 was not accepted: mempool min fee not met, 15000 < 24788 (code 66)
2015-10-27 21:27:43 ATMT decreases coincache by 105 (to 67916) KiB

@laanwj laanwj added the Mempool label Oct 29, 2015
@sipa
Copy link
Member

sipa commented Oct 30, 2015

Tested ACK.

@morcos
Copy link
Contributor

morcos commented Oct 30, 2015

I'm a bit hesitant to merge this instead of a cleaner way of smart flushing and I'd still like to see some performance analysis.

@gmaxwell gmaxwell added this to the 0.12.0 milestone Nov 5, 2015
@gmaxwell
Copy link
Contributor

gmaxwell commented Nov 8, 2015

Without this, my mining node with an elevated relay fee (and running mempool limiting) and default dbcache is at 4GB RES. We do need to do more to control the size of the coins cache, if not precisely this change.

@morcos
Copy link
Contributor

morcos commented Nov 9, 2015

I did some benchmarking on this pull. I built it on top of all the other improvements in #6976 except I tried it with and without the hot cache. It caused a significant performance boost to ConnectBlock. Unfortunately on my test days, 10/6 and 10/7 and using 100 M mempool and 200 M dbcache, the total cpu time shot up by over 10%. This seems to be entirely due to the 15kb very low fee transaction spam and increased time to reject these txs. I did not break down where the time was spent, but my guess is that it is not all in the uncaching code and that part of the problem is that these large txs often spent from the same prev hashes. So by uncaching them we cause more time to be spent just calculating the fee of new txs before we can reject them.
It also had the desired effect of reducing cache size, and reduced cache flushes from 38 to 16 over the 2 days.

Here is a summary of the results. I haven't fully reviewed the code yet, but I think this might be a performance hit we could tolerate.

Code Avg time for tx rejected by ATMP (ms) Avg time to connect block (ms)
baseline (#6976 except #6936) 1.7 134
baseline + #6936 1.7 128
baseline + this PR 2.9 109
baseline + this PR + #6936 2.9 104

@laanwj
Copy link
Member

laanwj commented Dec 1, 2015

Still needs rebase

@TheBlueMatt
Copy link
Contributor Author

Yes, sorry, I thought the plan was to go forward with #6936 and skip this one entirely, but it seems there is some consensus to do this as an intermediate until #6936 is fully ready to replace it (probably 0.13). Will try to rebase this tomorrow.

@TheBlueMatt
Copy link
Contributor Author

Rebased, squashed, pulled in sipa@4186ac9 for 0.12.

@maflcko
Copy link
Member

maflcko commented Dec 1, 2015

@TheBlueMatt Needs rebase. (Travis fail is unrelated: #6540)

@TheBlueMatt
Copy link
Contributor Author

Rebased. Again.

@laanwj laanwj merged commit dd5862c into bitcoin:master Dec 2, 2015
laanwj added a commit that referenced this pull request Dec 2, 2015
dd5862c Flush coins cache also after transaction processing (Pieter Wuille)
bde953e Uncache input txn in utxo cache if a tx is not accepted to mempool (Matt Corallo)
97bf377 Add CCoinsViewCache::HaveCoinsInCache to check if a tx is cached (Matt Corallo)
677aa3d Discard txn cache entries that were loaded for removed mempool txn (Matt Corallo)
b2e74bd Get the set of now-uncacheable-txn from CTxMemPool::TrimToSize (Matt Corallo)
74d0f90 Add method to remove a tx from CCoinsViewCache if it is unchanged (Matt Corallo)
@laanwj
Copy link
Member

laanwj commented Dec 2, 2015

Merged this because I want to branch off 0.12 soon, not happy it has no ACKs at all though (oh it does, sorry @sipa). Would still be nice if some reviewers could poshumously ACK this

@morcos
Copy link
Contributor

morcos commented Dec 2, 2015

code review and tested for performance only ACK

(I think most of us tested this before #5967 was merged, but I can't think why that should cause any problems)

@arielgabizon
Copy link

What was the justification for pulling in the flush commit? It seemed from the conversation that there was agreement of @TheBlueMatt and @morcos that it was not a good idea.

@TheBlueMatt
Copy link
Contributor Author

TheBlueMatt commented Dec 27, 2017 via email

random-zebra added a commit to PIVX-Project/PIVX that referenced this pull request Aug 12, 2020
…dded for is removed

2bf0de2 Flush coins cache also after transaction processing (Pieter Wuille)
48baa51 Uncache input txn in utxo cache if a tx is not accepted to mempool (random-zebra)
c7070de Add CCoinsViewCache::HaveCoinsInCache to check if a tx is cached (Matt Corallo)
7d1836d Discard txn cache entries that were loaded for removed mempool txn (random-zebra)
db35bd8 Get the set of now-uncacheable-txn from CTxMemPool::TrimToSize (Matt Corallo)
15e0321 Add method to remove a tx from CCoinsViewCache if it is unchanged (Matt Corallo)

Pull request description:

  backporting bitcoin#6872

ACKs for top commit:
  furszy:
    Code review ACK 2bf0de2 .
  furszy:
     Tested ACK 2bf0de2.
  Fuzzbawls:
    Code ACK 2bf0de2

Tree-SHA512: 06145fcb5eba7b81fc1264ac3ff1fc22a7281c71c7ddf844a4a331055fb58bc8be384961951df68d46b259077f0a7aaf223ab11bab0f546665f6293f7ee7fb6d
markblundeberg pushed a commit to markblundeberg/bitcoin that referenced this pull request Sep 5, 2020
…emaining

Only return confirmed (not from mempool) outpoints in `pvNoSpendsRemaining`,
as is the intended behaviour.

With the previous code, removed chains of tx would have all internally-spent outpoints
included in this vector, which is not the intended result. It seems to have been
incorrectly coded from the very start (bitcoin#6872)
but the bug is benign as this result is only used to uncache coins.

As a bonus, no copying of CTransaction is needed now.

An existing test case is modified to test this behaviour (the modified test fails
under prior behaviour).
markblundeberg pushed a commit to markblundeberg/bitcoin that referenced this pull request Sep 5, 2020
…emaining

Only return confirmed (not from mempool) outpoints in `pvNoSpendsRemaining`,
as is the intended behaviour.

With the previous code, removed chains of tx would have all internally-spent outpoints
included in this vector, which is not the intended result. It seems to have been
incorrectly coded from the very start (bitcoin#6872)
but the bug is benign as this result is only used to uncache coins.

As a bonus, no copying of CTransaction is needed now.

An existing test case is modified to test this behaviour (the modified test fails
under prior behaviour).
ftrader pushed a commit to bitcoin-cash-node/bitcoin-cash-node that referenced this pull request Oct 16, 2020
…aining

Only return confirmed outpoints in `pvNoSpendsRemaining`, as is the intended behaviour.

With the current code, removed chains of tx will have all internally-spent outpoints
included in this vector, which is not the intended result. It seems to have been
incorrectly coded from the very start (bitcoin/bitcoin#6872)
but the bug is benign as this result is only used to uncache coins.

As a bonus, no copying of CTransaction is needed.

An existing test case is modified to test this behaviour (the modified test will fail
under prior behaviour).
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants