besu icon indicating copy to clipboard operation
besu copied to clipboard

Excessive memory consumption on initial sync

Open tdiesler opened this issue 1 year ago • 3 comments

Description

After 23h of syncing, Besu starts the world state healing process - I see an excessive mem usage of 26G and a very busy CPU.

CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O        PIDS
8b3616a0c196   besu      241.31%   25.96GiB / 29.24GiB   88.79%    62.8GB / 6.84GB   455GB / 1.27TB   138

After several attempts, Besu has not yet managed to fully sync and crashed for memory issues, every time. It seems to be worse with versions > 22.7.4

Expected behavior: Mem usage within acceptable/documented bounds. A system crash after several days of syncing should be avoided, especially because the initial sync will have to restart all over again.

Frequency: Seems to occur every time

Versions (Add all that apply)

  • Besu-22.7.4-openjdk-11
  • CentOS Stream release 8
  • Linux vpsl01 4.18.0-365.el8.x86_64
  • Docker version 20.10.13

Additional Information (Add any of the following or anything else that may be relevant)

I'm using -XX:MaxRAMPercentage=80, so it should have 24G

docker run --detach \
  --name=besu \
  --user=0:0 \
  --restart=no \
  -p 8545:8545 \
  -p 8551:8551 \
  -p 30303:30303/tcp \
  -p 30303:30303/udp \
  -v besu-data:/var/besu/data \
  -v besu-config:/var/besu/config \
  -e BESU_OPTS=-XX:MaxRAMPercentage=80 \
  hyperledger/besu:${BESU_VERSION:-latest} \
    --network=mainnet \
    --data-path=/var/besu/data \
    --data-storage-format=bonsai \
    --sync-mode=x_checkpoint

https://discord.com/channels/697535391594446898/888098626264502302/1030171074052235325

tdiesler avatar Oct 14 '22 06:10 tdiesler

@tdiesler : The first thing we can check is either this is related to on-heap memory consumption or native memory consumption. For both cases have fixes and workarounds for both cases. For heap usage, could you share heap usage and GC pause time graph ? For native memory usage, have you already enabled Jemalloc lib ? it allows Besu to have less fragmentation when allocating objects in memory.

ahamlat avatar Oct 14 '22 07:10 ahamlat

@ahamlat AFAICS, there is no mention of jemalloc at startup ...

2022-10-13 06:36:40.972+00:00 | main | INFO  | Besu | Using LibEthPairings native alt bn128
2022-10-13 06:36:40.976+00:00 | main | INFO  | Besu | Using the native implementation of the signature algorithm
2022-10-13 06:36:40.997+00:00 | main | INFO  | Besu | Using the native implementation of the blake2bf algorithm
2022-10-13 06:36:41.004+00:00 | main | INFO  | Besu | Starting Besu version: besu/v22.7.4/linux-x86_64/openjdk-java-11
2022-10-13 06:36:41.495+00:00 | main | WARN  | Besu | --graphql-http-host has been ignored because --graphql-http-enabled was not defined on the command line.
2022-10-13 06:36:41.496+00:00 | main | WARN  | Besu | --rpc-ws-host has been ignored because --rpc-ws-enabled was not defined on the command line.
2022-10-13 06:36:41.498+00:00 | main | INFO  | Besu | Static Nodes file = /var/besu/data/static-nodes.json
2022-10-13 06:36:41.499+00:00 | main | INFO  | StaticNodesParser | StaticNodes file /var/besu/data/static-nodes.json does not exist, no static connections will be created.
2022-10-13 06:36:41.499+00:00 | main | INFO  | Besu | Connecting to 0 static nodes.
2022-10-13 06:36:41.502+00:00 | main | INFO  | Besu | Security Module: localfile
2022-10-13 06:36:41.526+00:00 | main | INFO  | DatabaseMetadata | Lookup database metadata file in data directory: /var/besu/data
2022-10-13 06:36:41.609+00:00 | main | INFO  | RocksDBKeyValueStorageFactory | Existing database detected at /var/besu/data. Version 2
2022-10-13 06:36:44.794+00:00 | main | WARN  | Besu | --tx-pool-future-max-by-account has been deprecated, use --tx-pool-limit-by-account-percentage instead.
2022-10-13 06:36:44.816+00:00 | main | INFO  | KeyPairUtil | Loaded public key 0x0ae8afc65f4eb662171fd5634e841e0ecff73d4e06f4f3de0222656176c1f75edc8c3bce90c6afd689c0de5ba9d6120832e21dbf783aefb7344c54a1cfde5918 from /var/besu/data/key
2022-10-13 06:36:45.035+00:00 | main | INFO  | ProtocolScheduleBuilder | Protocol schedule created with milestones: [Frontier: 0, Homestead: 1150000, DaoRecoveryInit: 1920000, DaoRecoveryTransition: 1920001, Homestead: 1920010, TangerineWhistle: 2463000, SpuriousDragon: 2675000, Byzantium: 4370000, Petersburg: 7280
000, Istanbul: 9069000, MuirGlacier: 9200000, Berlin: 12244000, London: 12965000, ArrowGlacier: 13773000, GrayGlacier: 15050000]
2022-10-13 06:36:45.066+00:00 | main | INFO  | ProtocolScheduleBuilder | Protocol schedule created with milestones: [Frontier: 0, Homestead: 1150000, DaoRecoveryInit: 1920000, DaoRecoveryTransition: 1920001, Homestead: 1920010, TangerineWhistle: 2463000, SpuriousDragon: 2675000, Byzantium: 4370000, Petersburg: 7280
000, Istanbul: 9069000, MuirGlacier: 9200000, Berlin: 12244000, London: 12965000, ArrowGlacier: 13773000, GrayGlacier: 15050000]
2022-10-13 06:36:45.704+00:00 | main | INFO  | EthPeers | Updating the default best peer comparator
2022-10-13 06:36:45.734+00:00 | main | INFO  | BesuControllerBuilder | TTD difficulty is present, creating initial sync phase with transition to PoS support
2022-10-13 06:36:45.766+00:00 | main | INFO  | CheckpointDownloaderFactory | Checkpoint sync start with block 11052984 and hash 0x44bca881b07a6a09f83b130798072441705d9a665c5ac8bdf2f39a3cdf3bee29
2022-10-13 06:36:46.087+00:00 | main | INFO  | TransitionBesuControllerBuilder | TTD present, creating DefaultSynchronizer that stops propagating after finalization
2022-10-13 06:36:46.115+00:00 | main | INFO  | RunnerBuilder | Detecting NAT service.
2022-10-13 06:36:46.401+00:00 | main | INFO  | Runner | Starting external services ... 
2022-10-13 06:36:46.402+00:00 | main | INFO  | JsonRpcHttpService | Starting JSON-RPC service on 0.0.0.0:8545
2022-10-13 06:36:46.515+00:00 | main | INFO  | JsonRpcService | Starting JSON-RPC service on 0.0.0.0:8551
2022-10-13 06:36:46.514+00:00 | vert.x-eventloop-thread-1 | INFO  | JsonRpcHttpService | JSON-RPC service started and listening on 0.0.0.0:8545
2022-10-13 06:36:46.525+00:00 | vert.x-eventloop-thread-1 | INFO  | JsonRpcService | JSON-RPC service started and listening on 0.0.0.0:8551
2022-10-13 06:36:46.530+00:00 | main | INFO  | AutoTransactionLogBloomCachingService | Starting auto transaction log bloom caching service.
2022-10-13 06:36:46.532+00:00 | main | INFO  | LogBloomCacheMetadata | Lookup cache metadata file in data directory: /var/besu/data/caches
2022-10-13 06:36:46.541+00:00 | main | INFO  | Runner | Starting Ethereum main loop ... 
2022-10-13 06:36:46.541+00:00 | main | INFO  | DockerNatManager | Starting docker NAT manager.
2022-10-13 06:36:46.548+00:00 | main | INFO  | NetworkRunner | Starting Network.
2022-10-13 06:36:46.552+00:00 | main | INFO  | DefaultP2PNetwork | Starting DNS discovery with URL enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net
2022-10-13 06:36:46.662+00:00 | nioEventLoopGroup-2-1 | INFO  | RlpxAgent | P2P RLPx agent started and listening on /0.0.0.0:30303.
2022-10-13 06:36:46.664+00:00 | main | INFO  | PeerDiscoveryAgent | Starting peer discovery agent on host=0.0.0.0, port=30303
2022-10-13 06:36:46.725+00:00 | vert.x-eventloop-thread-1 | INFO  | VertxPeerDiscoveryAgent | Started peer discovery agent successfully, on effective host=0.0.0.0 and port=30303
2022-10-13 06:36:46.727+00:00 | vert.x-eventloop-thread-1 | INFO  | PeerDiscoveryAgent | P2P peer discovery agent started and listening on /0.0.0.0:30303
2022-10-13 06:36:46.830+00:00 | vert.x-eventloop-thread-1 | INFO  | PeerDiscoveryAgent | Writing node record to disk. NodeRecord{seq=37, publicKey=0x020ae8afc65f4eb662171fd5634e841e0ecff73d4e06f4f3de0222656176c1f75e, udpAddress=Optional[/127.0.0.1:30303], tcpAddress=Optional[/127.0.0.1:30303], asBase64=-Je4QJB_CLhN
dRJpTxJItXvzw1qQiZ-cV3-yCoZdyxRj8xezZoc0d8baYJ4zZXRCuFmPRwOnNCDPtz2g_UyLpHIH2vglg2V0aMfGhPCv0OOAgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQIK6K_GX062Yhcf1WNOhB4Oz_c9Tgb0894CImVhdsH3XoN0Y3CCdl-DdWRwgnZf, nodeId=0x532470b557b8c4e3bc78de09812dcf4dfc82f8a88ac4dd59130fa765e3f1b048, customFields={tcp=30303, udp=30303, ip=0x7f0000
01, eth=[[0xf0afd0e3, 0x]], id=V4, secp256k1=0x020ae8afc65f4eb662171fd5634e841e0ecff73d4e06f4f3de0222656176c1f75e}}
2022-10-13 06:36:46.913+00:00 | main | INFO  | DefaultP2PNetwork | Enode URL enode://0ae8afc65f4eb662171fd5634e841e0ecff73d4e06f4f3de0222656176c1f75edc8c3bce90c6afd689c0de5ba9d6120832e21dbf783aefb7344c54a1cfde5918@127.0.0.1:30303
2022-10-13 06:36:46.914+00:00 | main | INFO  | DefaultP2PNetwork | Node address 0x812dcf4dfc82f8a88ac4dd59130fa765e3f1b048
2022-10-13 06:36:46.918+00:00 | main | INFO  | DefaultSynchronizer | Starting synchronizer.
2022-10-13 06:36:46.920+00:00 | main | INFO  | SnapSyncDownloader | Starting sync.
2022-10-13 06:36:46.923+00:00 | main | INFO  | WaitForPeersTask | Waiting for 1 total peers to connect. 0 peers currently connected.
2022-10-13 06:36:46.933+00:00 | main | INFO  | Runner | Ethereum main loop is up.

This suggests there should be a message about it. In any case, it would have to be enabled by the besu docker image, right? Here is a related post about a ruby image.

How would I get these mem stats from a running docker container?

tdiesler avatar Oct 14 '22 09:10 tdiesler

This suggests that jemalloc is getting installed in hyperledger/besu:22.7.4-openjdk-11, but BESU_USING_JEMALLOC is not getting set by the startup script

root@09f08bdfc84a:/opt/besu# set | grep BESU
BESU_GRAPHQL_HTTP_HOST=0.0.0.0
BESU_OPTS=-XX:MaxRAMPercentage=80
BESU_PID_PATH=/tmp/pid
BESU_RPC_HTTP_HOST=0.0.0.0
BESU_RPC_WS_HOST=0.0.0.0

I can load the library in container

$ docker exec -it besu bash
LD_PRELOAD=libjemalloc.so sh -c true

Now, is it using it or not?

tdiesler avatar Oct 14 '22 15:10 tdiesler

@ahamlat Could you please share your workarounds? What do other folks use in their docker BESU_OPTS?

tdiesler avatar Oct 17 '22 10:10 tdiesler

Now, is it using it or not?

You can use this command inside your docker container to be sure that Jemalloc is actually loaded : sudo lsof -n -p [PID] | fgrep jem

@ahamlat Could you please share your workarounds? What do other folks use in their docker BESU_OPTS?

For BESU_OPTS, you can replace the one you're using currently with this one : BESU_OPTS=-Xmx8g.

If you still have this excessive memory consumption, please share the result of this command : jcmd [PID] GC.class_histogram

ahamlat avatar Oct 17 '22 15:10 ahamlat

ok, it is using jemalloc

root@456e6c4d7f81:/opt/besu# lsof -n -p 1 | grep jem
java      1 root  mem       REG                8,2            1444124 /usr/lib/x86_64-linux-gnu/libjemalloc.so.2 (path dev=0,45)

jcmd is not available in the openjdk image by default. If needed, I'll try to get it from elsewhere

tdiesler avatar Oct 18 '22 10:10 tdiesler

In this case, you can just let it run and see if Jemalloc helps to reduce memory consumption.

ahamlat avatar Oct 18 '22 15:10 ahamlat

I manually installed jcmd in the running container and found that by running it mem drops by 1G - probably GC. Now that we verified that the process is indeed using jemalloc, I assume it was always there

tdiesler avatar Oct 18 '22 16:10 tdiesler

Could you share jcmd command results please ?

ahamlat avatar Oct 18 '22 16:10 ahamlat

Here you go ...

This is after 8h, currently @ Worldstate download in progress synced=30.36%

CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O        PIDS
aa78adccf96d   besu      255.21%   6.664GiB / 20GiB      33.32%    74.2GB / 2.48GB   305GB / 1.22TB   144

gc_hist.txt

With previous attempts, I could always get passed the worldstate download phase. Memory consumption shot up during healing and the furthest I got was 20m nodes

tdiesler avatar Oct 18 '22 17:10 tdiesler

From the histogram, we can see that we have a lot of Transaction's objects in memory. We already fixed this issue in Besu 22.7.6 and one other similar issue that happens during backward sync in 22.10.0-RC1.

ahamlat avatar Oct 18 '22 20:10 ahamlat

This is hyperledger/besu:22.7.6-openjdk-11. After 20h it got to Worldstate download in progress synced=49.02% - this seems (a lot) slower than on previous attempts (with -Xmx > 16g). Now, for 3h no worldstate download progress

tdiesler avatar Oct 19 '22 05:10 tdiesler

Do you have metrics to share to see why this is so slow ? (block time import, number of connected peers, GC activity, CPU usage, ...etc. If you don't have a Besu Dashboard, you can take a look to this one : https://grafana.com/grafana/dashboards/10273-besu-overview/

ahamlat avatar Oct 19 '22 12:10 ahamlat

The worldstate download stage completed after 42h with hyperledger/besu:22.7.6-openjdk-11.

  • memory usage at the time 15G (with -Xmx=16g)
  • 6.8TB written to disk
  • 2m core transaction kept in memory
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT    MEM %     NET I/O         BLOCK I/O         PIDS
e5e684197070   besu      148.87%   15.14GiB / 26GiB     58.23%    322GB / 15GB    2.73TB / 6.75TB   148
root@e5e684197070:/opt/besu# jcmd 1 GC.class_histogram | more
1:
 num     #instances         #bytes  class name (module)
-------------------------------------------------------
   1:       2269717     1054792440  [B ([email protected])
   2:      11913052      948593616  [I ([email protected])
   3:       6144888      245795520  java.math.BigInteger ([email protected])
   4:       2051226      180507888  org.hyperledger.besu.ethereum.core.Transaction
   5:       9450372      151205952  java.util.Optional ([email protected])
   6:       5758156      138195744  org.apache.tuweni.units.bigints.UInt256
   7:       5757807      138187368  org.hyperledger.besu.datatypes.Wei
   8:       3718265      118984480  org.apache.tuweni.bytes.ArrayWrappingBytes
   9:       2051231       65639392  org.hyperledger.besu.crypto.SECPSignature
  10:       2148159       51555816  org.hyperledger.besu.datatypes.Address
  11:       2077249       49853976  com.google.common.base.Suppliers$NonSerializableMemoizingSupplier
  12:       1748787       41970888  java.util.ArrayList ([email protected])
  13:       2051227       32819632  org.hyperledger.besu.crypto.SECPSignature$$Lambda$491/0x000000084043d840
  14:        565769       18104608  org.apache.tuweni.bytes.ArrayWrappingBytes32
  15:        120635       17225456  [Ljava.lang.Object; ([email protected])
  16:         97882        3915280  java.lang.ref.Finalizer ([email protected])
  17:         86573        2077752  org.hyperledger.besu.evm.AccessListEntry
  18:         77219        1853256  java.lang.String ([email protected])
  19:         69647        1671528  org.hyperledger.besu.datatypes.Hash
  20:        100059        1600944  java.util.concurrent.atomic.AtomicBoolean ([email protected])
  21:         48877        1564064  org.rocksdb.Transaction
  22:         47499        1519968  java.util.HashMap$Node ([email protected])
  23:         13000        1456000  org.hyperledger.besu.ethereum.core.BlockHeader
  24:         11355        1346784  java.lang.Class ([email protected])
  25:         48882        1173168  org.rocksdb.WriteOptions
  26:         36155        1156960  java.util.concurrent.ConcurrentHashMap$Node ([email protected])
  27:           387         909336  [C ([email protected])
  28:          3780         789648  [Ljava.util.HashMap$Node; ([email protected])
  29:         15822         759456  java.nio.HeapByteBuffer ([email protected])
  30:         17775         711000  java.util.LinkedHashMap$Entry ([email protected])
  31:           960         645120  io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueue
  32:         26811         643464  java.util.concurrent.CompletableFuture ([email protected])
  33:           642         608880  [Ljava.util.concurrent.ConcurrentHashMap$Node; ([email protected])
  34:          1956         603552  [J ([email protected])
  35:         12780         511200  java.util.concurrent.CompletableFuture$UniExceptionally ([email protected])

Now, onward to the node healing stage. Let's hope this time it completes before the process dies with OOME Currently nodes heal at a rate of 60k / min

tdiesler avatar Oct 21 '22 06:10 tdiesler

Ok, besu is done

2022-10-21 13:13:31.731+00:00 | EthScheduler-Services-28 (requestCompleteTask) | INFO  | SnapsyncMetricsManager | Finished worldstate snapsync with nodes 1390002633 (healed=8613992) duration 1:20:0,970.
2022-10-21 13:13:31.998+00:00 | EthScheduler-Services-666 (importBlock) | INFO  | PipelineChainDownloader | PipelineChain download complete
2022-10-21 13:13:32.043+00:00 | EthScheduler-Services-666 (importBlock) | INFO  | DefaultSynchronizer | Sync completed successfully with pivot block 15796599
2022-10-21 13:13:32.043+00:00 | EthScheduler-Services-666 (importBlock) | INFO  | BesuControllerBuilder | Initial sync done, unsubscribe finalized block hash supplier

Does this mean I can upgrade besu without having to do the initial sync again?

tdiesler avatar Oct 21 '22 13:10 tdiesler

Closing - Thanks for your help

tdiesler avatar Oct 21 '22 14:10 tdiesler