GoChain’s primary goal is to be the fastest Ethereum compatible public blockchain and we accomplished that goal by supporting 100x the transactions per second on day one, with even more performance upgrades to come. Now we’ve been asked several times by people that want to run a private GoChain network, how we compare to just running Ethereum in a private network. You can obviously get more speed in a private network that you can have full control over right?

So we set out to see for ourselves what the differences would be in a private network and here are the results.

GoChain vs Geth

We are doing the comparison using Go-Ethereum (geth) because 1) it’s the most widely used ethereum client by a factor of two and 2) it’s what GoChain is based off.

This is an analysis comparing a private GoChain network with a similarly configured private clique Geth network. The GoChain codebase originated as a fork of Geth, but uses a modified version of the clique consensus protocol and contains various other enhancements and optimizations to improve performance and throughput. By generating similar loads on both networks, we can measure the effects of these changes.

Configuration

Both networks consisted of identically configured Digital Ocean droplets (standard/16GB/6vCPU) — each with five signing nodes and two proxy nodes, distributed between San Fransisco and New York data centers. The Geth configuratrion was adjusted to be on par with GoChain’s defaults (5s blocks, same txpool limits, etc.).

Load

Identical load was generated on both networks by our custom chainload tool. Chainload generates a steady stream of transactions sent from many different accounts at once (hundreds or even thousands as necessary). Signed transactions are sent over JSON RPC to the proxy nodes which broadcast them to the rest of the network.

Results

Transaction Throughput

It is difficult to maintain consistent throughput on the geth network. For example, with a steady load of 100 tps, generally only 50–80 tps end up being processed, even though 100% of the transactions are accepted into the pool. Transactions become stuck pending on the proxy nodes and they are sometimes eventually rebroadcast to the network (but other times not at all!).

The two bottom nodes are the proxy nodes where the transactions are getting stuck.

The transactions are being distributed much faster and evenly on GoChain.

The throughput rate generally decreases over time — when a transaction fails to broadcast, any subsequent transactions from that account become queued (chainload eventually rotates accounts out). This effect worsens as the load increases. GoChain does not suffer from this problem — the transaction broadcast system has been enhanced both for performance and specifically to prevent ‘stuck’ transcations, which allows GoChain to maintain steady throughput of 100% of ingested transactions.

System Performance

All of the GoChain nodes (signers and proxies) maintained similar CPU usage under load — for example, 10–15% CPU at 100tps. Under the same 100tps load, the geth signer nodes show similar usage, but the proxy nodes use 40–50% CPU. This is likely due to managing the pool and broadcasting transactions — both of which have been heavily optimized in GoChain.

Limits

When pushed beyond it’s limit, geth often clogs up due to the aformentioned ‘stuck’ transactions problems. For example, with a 200tps load, after an initial burst the geth network quickly settles to processing only 8tps, at which point the backlog of transactions just keeps increasing.

On the other hand, when pushing 200tps to GoChain, performance degrades gradually and gracefully, for instance block propagation times increase but 100% transaction throughput is maintained.

Downtime

The geth clique protocol operates with a set of authorized signer nodes. The signer nodes take turns signing blocks, and after signing a block they must wait for at least half of the other nodes to sign before they are eligible to sign again. This ensures that the network cannot be manipulated by one or a few nodes, and requires half+1 of the signer nodes to be operational to keep the network running. For any given block, there is one ‘in-turn’ node that is expected to sign, but other nodes are able to fill in if necessary. The chain with the greatest total difficulty is chosen so the signer priorities are determined by the block difficulty.

The geth clique consensus protocol uses two fixed difficulty values, 2 for the ‘in-turn’ signer, and 1 for ‘out-of-turn’ signers. This prioritizes in-turn signing over out-of-turn. However, it does not distinguish between ‘out-of-turn’ signers as they all have equal weighting and ‘in-turn’ is based only on the block number with no consideration of recent history. This leads to a few problems:

When two or more nodes try to sign ‘out-of-turn’, there is no clear priority since they all have the same difficulty of 2. This ambiguity can lead to a kind of split-decision logical deadlock, where two different branches in the chain have the same total difficulty and the eligible signers for each are on the other branch. This prevents both from moving forward. When less than all n nodes are signing ( x are down), a smooth n-x round-robin signing pattern is likely not possible, because when a node fills in out-of-turn it may make itself ineligible (too recent) for it's own next in-turn block, requiring another out-of-turn signature. This effect can cascade or repeat depending both on chance and the least common multiple of n and n-x . When a signer is added, the period of the ‘in-turn’ schedule changes, making it possible for nodes to be ‘in-turn’ for two consecutive blocks (or for two blocks too near each other).

GoChain’s protocol avoids these problems by using distinct, dynamic, and scaled difficulties — based on when each node signed last. With n signers, the difficulty of each block ranges from n/2+1 to n , with the least recent signer having the highest priority. This has several benefits which solve or reduce the aforementioned problems:

Each signer always has a distinct difficulty — there is never a split-decision about which block or branch to accept. Because the ‘in-turn’ signer is the node which signed least recently, when less than all n nodes are signing, a graceful n-x round-robin schedule will still be prioritized, with random out-of-turn signatures only shifting or reordering the schedule.

This makes GoChain much more resilient to nodes going offline, and produces a fair ordering for signers nodes so that rewards are distributed evenly.

Conclusion

As we had hoped, all of the performance optimizations we’ve built into GoChain are proving themselves in a private, controlled environment too. What this means for you is that if you want an Ethereum private network, GoChain will give you a much better and more reliable experience. It’s also easier to setup and configure too!

For more information on running your own private GoChain network, see our documentation here.