Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How Do Heroku Dynos Affect Performance?

DZone's Guide to

How Do Heroku Dynos Affect Performance?

This is useful in capacity planning — we can estimate how many dynos are required for our application based on the TPS needs of the application being built.

· Performance Zone ·
Free Resource

Sensu is an open source monitoring event pipeline. Try it today.

As many of you know, Heroku is a cloud-based platform (PaaS) that encourages developers to focus on application development and not worry much about infrastructure. One of its advantages is that it's easy to start. Additionally, many Heroku add-ons are available for developers to choose from, and it's easy to scale and to do app monitoring. There are also some disadvantages in Heroku as well, like price, less control, and not being able to get the IP address of a single dyno instance.

Have you ever wondered how adding Heroku dynos affects performance? Does adding more Heroku dynos scale stateless apps? Let’s try to get some insight to this.

To validate this understanding, I have run a performance test with a sample stateless application using various Heroku dyno combinations. I will not go into the details of the application nor will I discuss the sample application code. Also, I will not discuss how to identify performance bottlenecks or how to tune performance.

To give an overview of the system under test:

System Under Test

  • Browser: Client or user.

  • Proxy: A node-based application deployed on Heroku. It passes through the system with no processing other than routing/forwarding the request to the web application.

  • Web application: A web-based application deployed on Heroku that serves HTML pages (i.e server-side page rendering). We use an embedded undertow container that makes use of backend restful APIs (services) to get relevant data. Also, we enable the local cache (Infinispan is used for that purpose) in this performance test setup.

Web Application Config Setup:

Undertow THREAD_COUNT_IO=16 , Undertow THREAD_COUNT_WORKER=64 , infinispan local cache is enabled

Blazemeter Test Configuration (Load Generator Machine)

  • Engines = 0

  • Threads per engine = 50

  • Iterations = ∞

  • Ramp up (seconds) = 0

  • Test duration (minutes) = 5

  • Delay (milliseconds) = 0

Test warm-up: This is done for all the test runs before load testing.

Test run

Heroku dyno app setup info

Perf test results

1

1 PM dyno for node proxy with 1 PM dyno for Java web application

TPS: 61.01; Response: 821.97 ms

2

2 PM dynos for node Proxy with 2 PM dynos for Java web application

TPS:  124; Response: 399.88 ms

3

1 PM dyno for node Proxy with 3 PM dynos for Java web application

TPS:  98.83; Response: 505.35 ms

4

1 PL dyno for node proxy with 1 PL dyno for Java web application

TPS: 203; Response: 246 ms

The first three test runs demonstrate Heroku horizontal scaling. The fourth test run demonstrates Heroku vertical scaling.

Note: Performance-M dynos are a single tenant on c3.large EC2 instances (Intel Xeon [Ivy Bridge] 2xCPU). Performance-L dynos are a single tenant on c3.2xlarge EC2 instances (Intel Xeon [Ivy Bridge] 8xCPU).

Increasing from 1PM dynos to 2PM dynos each for the proxy and web application resulted in an approximate 2x performance increase.

Switching to the Performance-L dyno resulted in a more than 3x performance increase over the Performance-M dyno.

From the above performance test results, we observe that Heroku scales out well for stateless applications. We can approximately predict the TPS (transaction per second; also known as hits per second) of the system when we add more similar dynos. This is useful in capacity planning — we can estimate how many dynos are required for our application based on the TPS needs of the application being built.

Sensu: workflow automation for monitoring. Learn more—download the whitepaper.

Topics:
heroku ,performance ,load testing ,scaling ,dyno ,app performance

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}