Experimenting with Corda Attachments
By: Jonathan Scialpi
Tags: Distributed Ledgers, Kotlin, Blockchain, Corda, Spring Boot

Analysis

Spring vs Braid:

To compare server performance, I conducted four tests that measured the total elapsed time for 100 attachment transactions to complete. Each test used the same source node (Issuer node-US East), an attachment size of 1MB or 10MB, and a domestic (RecipientB-US East) or international (RecipientA-CA Central) target node. To initiate a transaction, I concurrently called the respective server’s TriggerAttachmentDownload flow which would cause the source node to load the (non-cached) attachment from disk so that the target flow can then read and write the data to its disk.

Being that Braid doesn’t currently have a parameter to adjust the threadPoolSize, my tests were limited to the eight concurrent threads that Braid’s underlying framework (Vert.x) uses by default . This also meant that I had to run Spring at an eight thread maximum as well if I wanted to actually measure which performed faster under the same constraints.

Figure 1: Four test runs comparing the total elapsed time to send 100 domestic/international Txs with different sized attachments.

Spring Pros:

Consistently faster than Braid in regard to attachment size and latency due to node proximity.

Number of threads that can be processed are only limited to your node’s available memory.

Spring Cons:

Requires some research to understand how to use Spring annotations.

Requires development time to create and test your REST endpoints.

Braid Pros:

Great for quick POCs since it doesn’t require any setup time or prerequisite knowledge besides downloading the jar file.

Using Open API, Braid will inspect your CorDapps folder and your flow parameters to automatically create REST endpoints for any application to call your flows so you can focus on CorDapp development.

Braid Cons:

Although Braid’s underlying framework can handle a lot of concurrency using a small number of kernel threads, Vert.x’s golden rule says “Don’t block the event loop”. Because each of our requests requires a blocking thread to write our attachment to the target node’s disk, that means all my tests were limited to only eight threads.

Cached vs Non-Cached Attachments

Now that I had decisive winner in regard to server performance, it was finally time to take off the governor and test for throughput with no threading restrictions on my Spring server. Going back to our original example use case of data sharing, most of the transactions that would take place involve reusable attachments albeit the occasional update to the data set. Therefore a cached approach where said attachments are pre-loaded is optimal as the source node sending the transaction isn’t required to re-request the attachment from the database.

To cache my attachments prior to the test, I sent a transaction with each of the attachments to a node I wasn’t going to be testing with. For example, if I was measuring RecipientB, I would send the transactions first to RecipientA.

Figure 2: Four test runs that compare the results of Cached vs Non-Cached attachments from a Spring server with 100 concurrent/multi-threaded transactions.

Figure 2 above shows the dramatic effect that pre-caching your attachments can achieve. Not only was throughput 50 times faster than non-cached transactions, but the comparison of the results from the US-1MB test to that of the US-10MB shows only a 7% drop in performance while transacting with attachments that are ten times larger in size.