Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client/db/bolt: omit copy of buffer and upgrade in separate db txns #1070

Merged
merged 1 commit into from
Apr 29, 2021

Conversation

chappjc
Copy link
Member

@chappjc chappjc commented Apr 26, 2021

This attempts to address high memory utilization (both VIRT and RES) during a db upgrade with the following changes:

  • Eliminate the copy of two buffers from a db.Get because they are not used outside the db.Tx and thus do not need to be copies.
  • Put each upgrade into a separate transaction. This reduced memory use in my tests noticeably, but this means that if one upgrade in series of several version upgrades fails, it does not rollback to the starting version in the series, just the one version.
  • A handful of preallocation optimizations, excluding cancel matches when loading an orders matches with MatchesForOrder, and not re-saving cancel matches in reloadMatchProofs since they will always lack both revoke bools and txdata fields that are added in these upgrades. d977162 However, I'm uncertain now if reloadMatchProofs really needs to be done ever since DecodeMatchProof ensures old encodings load the same way as new encodings.
  • The v2 upgrade no longer sets maxFeeRate for old cancel orders. These are and should be stored as zero anyway (see tryCancelTrade), so ^uint8(0) was incorrect here previously. But the maxFeeRate is correctly ignored for cancel matches in (*dexConnection).parseMatches. Skipping these updates to cancel orders further improves memory utilization and speed. 68a6cb3

These changes will be needed for the 0.2 upgrade since there are some rather large client DBs out there that are going to have similar troubles.

Comment on lines +28 to 31
// {"testnetbot", v1Upgrade, verifyV1Upgrade, "dexbot-testnet.db.gz", 3}, // only for TestUpgradeDB
{"upgradeFromV0", v1Upgrade, verifyV1Upgrade, "v0.db.gz", 1},
{"upgradeFromV1", v2Upgrade, verifyV2Upgrade, "v1.db.gz", 2},
{"upgradeFromV2", v3Upgrade, verifyV3Upgrade, "v2.db.gz", 3},
Copy link
Member Author

@chappjc chappjc Apr 26, 2021

Choose a reason for hiding this comment

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

Test a big upgrade by commenting out these three and uncommenting the other one, which is only for TestUpgradeDB.

Then see how it goes with go test -v -count 1 -run TestUpgradeDB.

If it succeeds, you can try a mem profile:

go test -v -count 1 -run TestUpgradeDB -memprofile mem.out
go tool pprof bolt.test mem.out
# top and web are easiest

This PR only changes two things that could help memory: two unneeded copies inside db txns (the buffer from Get is not used outside the db tx), and doing the upgrades in separate db txns. EDIT: plus a couple other optimizations and shortcuts with cancel matches.

Copy link
Member

Choose a reason for hiding this comment

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

does not oom for me

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for checking. I suspect breaking each upgrade into different db txns allowed cleanup (GC or other OS business). So I guess this PR is needed then.

Copy link
Member

@JoeGruffins JoeGruffins left a comment

Choose a reason for hiding this comment

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

(pprof) top
Showing nodes accounting for 3810.92MB, 92.13% of 4136.67MB total
Dropped 21 nodes (cum <= 20.68MB)
Showing top 10 nodes out of 45
      flat  flat%   sum%        cum   cum%
  678.63MB 16.41% 16.41%   678.63MB 16.41%  go.etcd.io/bbolt.Open.func1
  575.58MB 13.91% 30.32%   575.58MB 13.91%  go.etcd.io/bbolt.(*node).dereference
  457.83MB 11.07% 41.39%   457.83MB 11.07%  go.etcd.io/bbolt.(*node).read
  447.71MB 10.82% 52.21%   447.71MB 10.82%  go.etcd.io/bbolt.(*node).put
  417.71MB 10.10% 62.31%   417.71MB 10.10%  decred.org/dcrdex/dex/encode.ExtractPushes
  380.76MB  9.20% 71.51%   380.76MB  9.20%  go.etcd.io/bbolt.(*Bucket).write
  310.18MB  7.50% 79.01%   359.18MB  8.68%  go.etcd.io/bbolt.(*Bucket).openBucket
  215.01MB  5.20% 84.21%   215.01MB  5.20%  go.etcd.io/bbolt.(*Cursor).search
  183.50MB  4.44% 88.64%   641.33MB 15.50%  go.etcd.io/bbolt.(*Bucket).node
  144.02MB  3.48% 92.13%   144.02MB  3.48%  decred.org/dcrdex/dex/encode.BuildyBytes.AddData

Looks to work well for me. Is it using too much memory? Possibly related? boltdb/bolt#253

@chappjc
Copy link
Member Author

chappjc commented Apr 27, 2021

Added commit 914d140 to see if helps to run each upgrade in its own db tx vs all upgrades in one db tx. @dajohi

@chappjc chappjc changed the title (for debugging) client/db/bolt: omit copy of buffer used only in db txns client/db/bolt: omit copy of buffer and upgrade in separate db txns Apr 27, 2021
@chappjc chappjc marked this pull request as ready for review April 27, 2021 18:46
@chappjc chappjc added this to the 0.2 milestone Apr 27, 2021
@chappjc
Copy link
Member Author

chappjc commented Apr 27, 2021

@JoeGruffins could I trouble you for a re-review after having split the upgrades into separate db txns?

@@ -848,7 +848,7 @@ func (db *BoltDB) DEXOrdersWithActiveMatches(dex string) ([]order.OrderID, error
}

// Inactive if refunded.
proofB := getCopy(mBkt, proofKey)
proofB := mBkt.Get(proofKey)
Copy link
Member Author

Choose a reason for hiding this comment

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

In this method, DEXOrdersWithActiveMatches, the proof bytes are only used inside the db.Tx to check revoked and refunded status, but not outside the tx, so no copy is safe.

@@ -197,7 +209,7 @@ func reloadMatchProofs(tx *bbolt.Tx) error {
if mBkt == nil {
return fmt.Errorf("match %x bucket is not a bucket", k)
}
proofB := getCopy(mBkt, proofKey)
proofB := mBkt.Get(proofKey)
Copy link
Member Author

Choose a reason for hiding this comment

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

In reloadMatchProofs, the proof bytes are decoded, reencoded, and re-saved inside the transaction, so also safe to elide the copy.

Comment on lines +210 to +211
archive.Close()
dbFile.Close()
Copy link
Member Author

Choose a reason for hiding this comment

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

We're done with both the archive and the extracted db here. The NewDB call back in the test loads the DB by its file name.

Comment on lines 87 to 108
// Each upgrade its own tx.
for i, upgrade := range upgrades[version:] {
err = db.Update(func(tx *bbolt.Tx) error {
return doUpgrade(tx, upgrade, version+uint32(i)+1)
})
if err != nil {
return err
}
return nil
})
}
return nil

// All upgrades in a single tx.
// return db.Update(func(tx *bbolt.Tx) error {
// // Execute all necessary upgrades in order.
// for i, upgrade := range upgrades[version:] {
// err := doUpgrade(tx, upgrade, version+uint32(i)+1)
// if err != nil {
// return err
// }
// }
// return nil
// })
Copy link
Member Author

@chappjc chappjc Apr 27, 2021

Choose a reason for hiding this comment

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

Will remove this commented chunk. I feel like it's not horrible if a rollback only goes to one version up instead of all the way to the starting version because at least the DB isn't hosed (there's also a file backup created at the initial version). It does have an impact on memory, so I don't think we have a choice. See the TestUpgradeDB test with the dexbot-testnet.db.gz archive.

All in 1 txn:

File: bolt.test
Type: alloc_space
Time: Apr 27, 2021 at 2:41pm (CDT)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 3861.84MB, 92.23% of 4187.32MB total
Dropped 8 nodes (cum <= 20.94MB)
Showing top 10 nodes out of 45
      flat  flat%   sum%        cum   cum%
  673.61MB 16.09% 16.09%   673.61MB 16.09%  go.etcd.io/bbolt.Open.func1
  583.08MB 13.92% 30.01%   583.08MB 13.92%  go.etcd.io/bbolt.(*node).dereference
  464.23MB 11.09% 41.10%   464.23MB 11.09%  go.etcd.io/bbolt.(*node).put
  451.83MB 10.79% 51.89%   451.83MB 10.79%  go.etcd.io/bbolt.(*node).read
  442.72MB 10.57% 62.46%   442.72MB 10.57%  decred.org/dcrdex/dex/encode.ExtractPushes
  407.78MB  9.74% 72.20%   407.78MB  9.74%  go.etcd.io/bbolt.(*Bucket).write
  314.68MB  7.52% 79.72%   369.18MB  8.82%  go.etcd.io/bbolt.(*Bucket).openBucket
  211.51MB  5.05% 84.77%   211.51MB  5.05%  go.etcd.io/bbolt.(*Cursor).search
  165.38MB  3.95% 88.72%   617.21MB 14.74%  go.etcd.io/bbolt.(*Bucket).node
  147.02MB  3.51% 92.23%   147.02MB  3.51%  decred.org/dcrdex/dex/encode.BuildyBytes.AddData

Separate txns:

File: bolt.test
Type: alloc_space
Time: Apr 27, 2021 at 2:38pm (CDT)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 3212.76MB, 91.10% of 3526.49MB total
Dropped 24 nodes (cum <= 17.63MB)
Showing top 10 nodes out of 45
      flat  flat%   sum%        cum   cum%
  453.32MB 12.85% 12.85%   453.32MB 12.85%  go.etcd.io/bbolt.(*node).read
  435.18MB 12.34% 25.20%   435.18MB 12.34%  go.etcd.io/bbolt.(*node).put
  420.21MB 11.92% 37.11%   420.21MB 11.92%  decred.org/dcrdex/dex/encode.ExtractPushes
  398.27MB 11.29% 48.40%   398.27MB 11.29%  go.etcd.io/bbolt.(*Bucket).write
  364.41MB 10.33% 58.74%   364.41MB 10.33%  go.etcd.io/bbolt.Open.func1
  318.06MB  9.02% 67.76%   318.06MB  9.02%  go.etcd.io/bbolt.(*node).dereference
  311.17MB  8.82% 76.58%   356.18MB 10.10%  go.etcd.io/bbolt.(*Bucket).openBucket
  201.51MB  5.71% 82.30%   201.51MB  5.71%  go.etcd.io/bbolt.(*Cursor).search
  174.11MB  4.94% 87.23%   627.43MB 17.79%  go.etcd.io/bbolt.(*Bucket).node
  136.51MB  3.87% 91.10%   136.51MB  3.87%  decred.org/dcrdex/dex/encode.BuildyBytes.AddData

Copy link
Member

Choose a reason for hiding this comment

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

With the current changes:

top
Showing nodes accounting for 3515.76MB, 91.35% of 3848.73MB total
Dropped 16 nodes (cum <= 19.24MB)
Showing top 10 nodes out of 45
      flat  flat%   sum%        cum   cum%
  648.01MB 16.84% 16.84%   648.01MB 16.84%  go.etcd.io/bbolt.Open.func1
  463.85MB 12.05% 28.89%   463.85MB 12.05%  go.etcd.io/bbolt.(*node).read
  451.74MB 11.74% 40.63%   451.74MB 11.74%  go.etcd.io/bbolt.(*node).put
  444.22MB 11.54% 52.17%   444.22MB 11.54%  decred.org/dcrdex/dex/encode.ExtractPushes
  381.26MB  9.91% 62.07%   381.26MB  9.91%  go.etcd.io/bbolt.(*Bucket).write
  319.06MB  8.29% 70.36%   319.06MB  8.29%  go.etcd.io/bbolt.(*node).dereference
  273.66MB  7.11% 77.47%   330.16MB  8.58%  go.etcd.io/bbolt.(*Bucket).openBucket
  206.01MB  5.35% 82.83%   206.01MB  5.35%  go.etcd.io/bbolt.(*Cursor).search
  172.94MB  4.49% 87.32%   636.78MB 16.55%  go.etcd.io/bbolt.(*Bucket).node
  155.02MB  4.03% 91.35%   155.02MB  4.03%  decred.org/dcrdex/dex/encode.BuildyBytes.AddData

Your second top is missing go.etcd.io/bbolt.Open.func1, wonder why?

Copy link
Member Author

Choose a reason for hiding this comment

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

I wonder why too. That profile looks more like the profile with a single Update as it was before. 😕

Copy link
Member Author

Choose a reason for hiding this comment

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

With d977162, now I'm seeing:

$  go test -v -count 1 -run TestUpgradeDB -memprofile=mem.out
=== RUN   TestUpgradeDB
2021-04-28 11:58:11.281 [INF] db_TEST: Upgrading database from version 1 to 3
2021-04-28 11:58:11.513 [DBG] db_TEST: Upgrading to version 2...
2021-04-28 11:58:15.132 [DBG] db_TEST: Upgrading to version 3...
--- PASS: TestUpgradeDB (6.90s)
PASS
ok  	decred.org/dcrdex/client/db/bolt	7.221s
$  go tool pprof bolt.test mem.out
File: bolt.test
Type: alloc_space
Time: Apr 28, 2021 at 11:58am (CDT)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top15
Showing nodes accounting for 2627.65MB, 99.25% of 2647.48MB total
Dropped 14 nodes (cum <= 13.24MB)
Showing top 15 nodes out of 43
      flat  flat%   sum%        cum   cum%
  458.21MB 17.31% 17.31%   458.21MB 17.31%  go.etcd.io/bbolt.(*node).put
  364.92MB 13.78% 31.09%   364.92MB 13.78%  go.etcd.io/bbolt.Open.func1
  335.56MB 12.67% 43.77%   335.56MB 12.67%  go.etcd.io/bbolt.(*node).dereference
  298.68MB 11.28% 55.05%   361.68MB 13.66%  go.etcd.io/bbolt.(*Bucket).openBucket
  247.69MB  9.36% 64.40%   247.69MB  9.36%  go.etcd.io/bbolt.(*node).read
  216.66MB  8.18% 72.59%   216.66MB  8.18%  go.etcd.io/bbolt.(*Bucket).write
  163.01MB  6.16% 78.74%   163.01MB  6.16%  go.etcd.io/bbolt.(*Cursor).search
  154.58MB  5.84% 84.58%   154.58MB  5.84%  decred.org/dcrdex/dex/encode.ExtractPushes
  127.05MB  4.80% 89.38%   127.05MB  4.80%  decred.org/dcrdex/client/db.decodeMatchProof_v2
   92.26MB  3.49% 92.87%   339.96MB 12.84%  go.etcd.io/bbolt.(*Bucket).node
   81.67MB  3.08% 95.95%   537.36MB 20.30%  go.etcd.io/bbolt.(*Bucket).Bucket
      63MB  2.38% 98.33%       63MB  2.38%  go.etcd.io/bbolt.newBucket (inline)
      10MB  0.38% 98.71%  1049.60MB 39.65%  go.etcd.io/bbolt.(*Bucket).spill
    7.50MB  0.28% 98.99%   759.83MB 28.70%  go.etcd.io/bbolt.(*Bucket).Put
    6.86MB  0.26% 99.25%   709.17MB 26.79%  go.etcd.io/bbolt.(*Tx).allocate

@JoeGruffins
Copy link
Member

I left some suggestions here: chappjc#2

Am getting this by updating in batches.

(pprof) top
Showing nodes accounting for 2246.86MB, 98.90% of 2271.87MB total
Dropped 9 nodes (cum <= 11.36MB)
Showing top 10 nodes out of 36
      flat  flat%   sum%        cum   cum%
  450.66MB 19.84% 19.84%   450.66MB 19.84%  go.etcd.io/bbolt.(*node).put
  444.22MB 19.55% 39.39%   444.22MB 19.55%  decred.org/dcrdex/dex/encode.ExtractPushes
  405.27MB 17.84% 57.23%   405.27MB 17.84%  go.etcd.io/bbolt.(*node).read
  290.67MB 12.79% 70.02%   347.67MB 15.30%  go.etcd.io/bbolt.(*Bucket).openBucket
  148.02MB  6.52% 76.54%   148.02MB  6.52%  decred.org/dcrdex/dex/encode.BuildyBytes.AddData
  133.02MB  5.85% 82.39%   538.29MB 23.69%  go.etcd.io/bbolt.(*Bucket).node
  122.51MB  5.39% 87.78%   122.51MB  5.39%  go.etcd.io/bbolt.(*Cursor).search
  119.55MB  5.26% 93.05%   119.55MB  5.26%  decred.org/dcrdex/client/db.decodeMatchProof_v2
   75.95MB  3.34% 96.39%   518.63MB 22.83%  go.etcd.io/bbolt.(*Bucket).Bucket
      57MB  2.51% 98.90%       57MB  2.51%  go.etcd.io/bbolt.newBucket (inline)

@chappjc
Copy link
Member Author

chappjc commented Apr 28, 2021

The peak allocation is clearly reduced with doing match updates in chunks @JoeGruffins. My only comment on that approach was regarding rollback not necessarily leaving the DB in a state prior to starting the upgrade. chappjc#2 (review) I think this may be acceptable since the first Update in a chunk is likely to error if any of them error (although it could be a disk full error on the last chunk), and we have a backup db file created before starting...

Opinions welcome on the issue. It is clear that the larger the txn, the higher the peak memory utilization...

@chappjc
Copy link
Member Author

chappjc commented Apr 28, 2021

My suspicion now is that we've made sub-buckets with values that are simply too large, and should have been split into multiple sub-buckets. Namely the MatchProof being serialized and written into a single sub-bucket of a match bucket. If we had each field of MatchProof in a separate sub-bucket, we likely wouldn't have this memory issue just to update/add one field.

Also, another reason why splitting more could be good is if we want to check just one field in the db, such as RedeemSig, without loading and decoding the entire MatchProof. This is a current issue with checking for match completeness (long load times as we cycle through all matches to determine if they are active). This is the reason the proposed addition of an archived orders bucket in #1071

Making the above change is a challenge though. It's not just a big change, it still requires dealing with an upgrade that needs to load all the match proofs just to split into more buckets.

EDIT: smaller sub-buckets wouldn't explain the memory use from v2Upgrade though, because it just adds a key

@@ -3923,7 +3925,7 @@ func (c *Core) dbTrackers(dc *dexConnection) (map[order.OrderID]*trackedTrade, e
trackers[dbOrder.Order.ID()] = tracker

// Get matches.
dbMatches, err := c.db.MatchesForOrder(oid)
dbMatches, err := c.db.MatchesForOrder(oid, excludeCancelMatches)
Copy link
Member Author

@chappjc chappjc Apr 28, 2021

Choose a reason for hiding this comment

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

Note a few lines down how we skip cancel matches:

			// Only trade matches are added to the matches map. Detect and skip
			// cancel order matches, which have an empty Address field.
			if dbMatch.Address == "" {
				// tracker.cancel is set from LinkedOrder with cancelTrade.
				continue

Any cancel info comes from the order's data (tracker.metaData.LinkedOrder).

Comment on lines +43 to +50
reProof, ver, err := db.DecodeMatchProof(proofB)
if err != nil {
t.Fatalf("match decode error: %v", err)
}
MustCompareMatchProof(t, proof, reProof)
if ver != db.MatchProofVer {
t.Errorf("wanted match proof ver %d, got %d", db.MatchProofVer, ver)
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm actually not getting why either the v1 or v3 upgrades that just call reloadMatchProofs are needed at all given the MatchProofs will always load the same regardless of the serialization version in the stored data.

Comment on lines 2548 to +2552
func (c *Core) coreOrderFromMetaOrder(mOrd *db.MetaOrder) (*Order, error) {
corder := coreOrderFromTrade(mOrd.Order, mOrd.MetaData)
oid := mOrd.Order.ID()
matches, err := c.db.MatchesForOrder(oid)
excludeCancels := false // maybe don't include cancel order matches?
matches, err := c.db.MatchesForOrder(oid, excludeCancels)
Copy link
Member Author

@chappjc chappjc Apr 28, 2021

Choose a reason for hiding this comment

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

This is used by (*Core).Order and (*Core).Orders, and the consumers may be looking at cancel matches too, so I didn't change this result.

However apiOrders is very unlikely to need the cancel matches, and we have had reports of the order history page taking extremely long to load pull new orders... yeah apiOrders seem to need the cancel matches so it can display like this:

image

So coreOrderFromMetaOrder really does need to get a MetaOrder that includes even cancel order matches.

@chappjc
Copy link
Member Author

chappjc commented Apr 28, 2021

With 68a6cb3 just added, the v2 upgrade is faster and lighter since it no longer incorrectly sets maxFeeRate for cancel orders. It was incorrect before because cancel orders are normally stored with 0 maxFeeRate not ^uint8(0), but it wasn't an issue because maxFeeRate for cancel orders is rightly ignored in (*dexConnection).parseMatches.

timing and memprofile now:

$ go test -v -count 1 -run TestUpgradeDB -memprofile=mem.out
=== RUN   TestUpgradeDB
2021-04-28 13:52:52.829 [INF] db_TEST: Upgrading database from version 1 to 3
2021-04-28 13:52:53.069 [DBG] db_TEST: Upgrading to version 2...
2021-04-28 13:52:55.029 [DBG] db_TEST: Upgrading to version 3...
--- PASS: TestUpgradeDB (5.26s)
PASS
ok  	decred.org/dcrdex/client/db/bolt	5.511s

$  go tool pprof bolt.test mem.out
File: bolt.test
Type: alloc_space
Time: Apr 28, 2021 at 1:52pm (CDT)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 1623.40MB, 94.46% of 1718.61MB total
Dropped 11 nodes (cum <= 8.59MB)
Showing top 10 nodes out of 42
      flat  flat%   sum%        cum   cum%
  317.22MB 18.46% 18.46%   317.22MB 18.46%  go.etcd.io/bbolt.Open.func1
  287.66MB 16.74% 35.20%   342.66MB 19.94%  go.etcd.io/bbolt.(*Bucket).openBucket
  233.90MB 13.61% 48.81%   233.90MB 13.61%  go.etcd.io/bbolt.(*node).put
  151.58MB  8.82% 57.63%   151.58MB  8.82%  decred.org/dcrdex/dex/encode.ExtractPushes
  137.51MB  8.00% 65.63%   137.51MB  8.00%  go.etcd.io/bbolt.(*Cursor).search
  131.12MB  7.63% 73.26%   131.12MB  7.63%  go.etcd.io/bbolt.(*node).read
  121.05MB  7.04% 80.30%   121.05MB  7.04%  decred.org/dcrdex/client/db.decodeMatchProof_v2
  108.09MB  6.29% 86.59%   108.09MB  6.29%  go.etcd.io/bbolt.(*Bucket).write
   80.27MB  4.67% 91.26%   515.44MB 29.99%  go.etcd.io/bbolt.(*Bucket).Bucket
      55MB  3.20% 94.46%       55MB  3.20%  go.etcd.io/bbolt.newBucket (inline)

@chappjc chappjc changed the base branch from master to release-v0.2 April 28, 2021 19:46
@JoeGruffins
Copy link
Member

at 2ba2aeb

top
Showing nodes accounting for 1655.31MB, 95.29% of 1737.12MB total
Dropped 10 nodes (cum <= 8.69MB)
Showing top 10 nodes out of 42
      flat  flat%   sum%        cum   cum%
  326.77MB 18.81% 18.81%   326.77MB 18.81%  go.etcd.io/bbolt.Open.func1
  314.68MB 18.12% 36.93%   370.68MB 21.34%  go.etcd.io/bbolt.(*Bucket).openBucket
  222.87MB 12.83% 49.76%   222.87MB 12.83%  go.etcd.io/bbolt.(*node).put
  156.59MB  9.01% 58.77%   156.59MB  9.01%  decred.org/dcrdex/dex/encode.ExtractPushes
  147.62MB  8.50% 67.27%   147.62MB  8.50%  go.etcd.io/bbolt.(*node).read
  135.01MB  7.77% 75.04%   135.01MB  7.77%  go.etcd.io/bbolt.(*Cursor).search
  111.54MB  6.42% 81.46%   111.54MB  6.42%  decred.org/dcrdex/client/db.decodeMatchProof_v2
  107.08MB  6.16% 87.63%   107.08MB  6.16%  go.etcd.io/bbolt.(*Bucket).write
   77.14MB  4.44% 92.07%   543.33MB 31.28%  go.etcd.io/bbolt.(*Bucket).Bucket
      56MB  3.22% 95.29%       56MB  3.22%  go.etcd.io/bbolt.newBucket (inline)

Copy link
Member

@JoeGruffins JoeGruffins left a comment

Choose a reason for hiding this comment

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

Looks like this reduced the memory usage, that db must have a lot of cancel orders?

Comment on lines +227 to +230
// No need to rewrite this if it was loaded from the current version.
if ver == dexdb.MatchProofVer {
return nil
}
Copy link
Member

Choose a reason for hiding this comment

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

This logic would make resuming from failed batches easily doable, for this upgrade, if we did batches.

@chappjc
Copy link
Member Author

chappjc commented Apr 29, 2021

Thanks for the follow-up Joe. We've had a good amount of feedback and testing, so I think this is good to go.

@chappjc chappjc changed the base branch from release-v0.2 to master April 29, 2021 03:27
try each upgrade in its own tx

excludeCancels option for db.MatchesForOrder and reloadMatchProofs

Cancel matches can be the lion's share of matches in some DBs, and in
most cases it is not necessary to process these.
- In db upgrades, there is no reason to reencode the MatchProof.
  Although it's not clear there is a reason to do this for trade matches
  either since any match proof version decodes automatically to the
  current MatchProof.
- In (*Core).dbTrackers, cancel order matches are not used.
- (*Core).coreOrderFromMetaOrder might be able to exclude cancel order
  matches, but the consumers are exported Core methods, so no change.

This also include a prealloc optional arg to ExtractPushes and
DecodeBlob, which is mainly helpful for the MatchProof buckets
that have 22 pushes.

do not set maxFeeRate for cancels v2 upgrade
@chappjc chappjc merged commit 83377b0 into decred:master Apr 29, 2021
@chappjc chappjc deleted the db-nocopy branch April 29, 2021 03:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants