In this notebook I’ll show some techniques that I use to optimize my shiny apps to the point that I can upload them to a free 1GB RAM server (shinyapps.io)
#Find what is slow in your code:
Starting the process of optimization on an app can be quite rewarding if you start by the chunks of code that take more time to be processed. This is called collecting the low hanging fruits and can be easily achieved using the right tools.
I’m going to pick an app(https://github.com/raylandmagalhaes/Densidade_Gastos_Deputados) that I’m currently working on and needs improvement, but you can choose the one you want to optimize.
We are going to use the funcion profviz that will show how much memory and how much time each chunk of code takes to run.
library(profvis,quietly = T)
library(shiny,quietly = T)
#After your app pops up, play with it and make it work so that the function can capture how much time each task take to run.
Initial_Profile <- profvis(runApp(appDir="app.R"))
Initial_Profile
Looking at our Initial_Profile, we can see that our App takes 5930ms to initialize, 630ms to run the output$densidades for the first time and 2480ms for the second. What we can also see is that it took 2670.7MB of RAM to initialize, wich by itself would turn our dream to upload it on a free 1GB server into ashes.
Starting the optimization with the initialization seems to be our best choice in this situation, so lets get started.
Optimizing initialization
If we look at our app, we see that at the beginning we build the complete data set that we are going to use.
camara=bind_rows(list(camara2009,
camara2010,
camara2011,
camara2012,
camara2013,
camara2014,
camara2015,
camara2016,
camara2017,
camara2018,
camara2019)
) %>%
filter(total_net_value>0) %>%
data.frame(check.names = F) %>%
filter(!is.na(total_net_value)&!is.na(document_value))
So, why not doing this data processing outside the app?
save(camara,file="camara")
Now, all we have to do is load the pre processed data into our app with the command load("camara").
Lets check the performance of our app now:
Second_Profile <- profvis(runApp(appDir="app.R"))
Second_Profile
Looking at the Second_Profile, we can see that our app took 3560ms to start and 751.3MB of RAM to run and it can already be uploaded to a free server. Or can it?
I’m going to update this notebook very soon with more optimization techniques. Thanks for reading.
LS0tDQp0aXRsZTogIlNoaW55IE9wdGltaXphdGlvbiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCkluIHRoaXMgbm90ZWJvb2sgSSdsbCBzaG93IHNvbWUgdGVjaG5pcXVlcyB0aGF0IEkgdXNlIHRvIG9wdGltaXplIG15IHNoaW55IGFwcHMNCnRvIHRoZSBwb2ludCB0aGF0IEkgY2FuIHVwbG9hZCB0aGVtIHRvIGEgZnJlZSAxR0IgUkFNIHNlcnZlciAoc2hpbnlhcHBzLmlvKQ0KDQojRmluZCB3aGF0IGlzIHNsb3cgaW4geW91ciBjb2RlOg0KDQpTdGFydGluZyB0aGUgcHJvY2VzcyBvZiBvcHRpbWl6YXRpb24gb24gYW4gYXBwIGNhbiBiZSBxdWl0ZSByZXdhcmRpbmcgaWYgeW91IHN0YXJ0IGJ5IHRoZSBjaHVua3Mgb2YgY29kZSB0aGF0IHRha2UgbW9yZSB0aW1lIHRvIGJlIHByb2Nlc3NlZC4gVGhpcyBpcyBjYWxsZWQgY29sbGVjdGluZyB0aGUgbG93IGhhbmdpbmcgZnJ1aXRzIGFuZCBjYW4gYmUgZWFzaWx5IGFjaGlldmVkIHVzaW5nIHRoZSByaWdodCB0b29scy4NCg0KSSdtIGdvaW5nIHRvIHBpY2sgYW4gYXBwKGh0dHBzOi8vZ2l0aHViLmNvbS9yYXlsYW5kbWFnYWxoYWVzL0RlbnNpZGFkZV9HYXN0b3NfRGVwdXRhZG9zKSB0aGF0IEknbSBjdXJyZW50bHkgd29ya2luZyBvbiBhbmQgbmVlZHMgaW1wcm92ZW1lbnQsIGJ1dCB5b3UgY2FuIGNob29zZSB0aGUgb25lIHlvdSB3YW50IHRvIG9wdGltaXplLg0KDQpXZSBhcmUgZ29pbmcgdG8gdXNlIHRoZSBmdW5jaW9uIHByb2Z2aXogdGhhdCB3aWxsIHNob3cgaG93IG11Y2ggbWVtb3J5IGFuZCBob3cgbXVjaCB0aW1lIGVhY2ggY2h1bmsgb2YgY29kZSB0YWtlcyB0byBydW4uIA0KDQoNCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9VFJVRX0NCmxpYnJhcnkocHJvZnZpcyxxdWlldGx5ID0gVCkNCmxpYnJhcnkoc2hpbnkscXVpZXRseSA9IFQpDQoNCiNBZnRlciB5b3VyIGFwcCBwb3BzIHVwLCBwbGF5IHdpdGggaXQgYW5kIG1ha2UgaXQgd29yayBzbyB0aGF0IHRoZSBmdW5jdGlvbiBjYW4gY2FwdHVyZSBob3cgbXVjaCB0aW1lIGVhY2ggdGFzayB0YWtlIHRvIHJ1bi4NCg0KSW5pdGlhbF9Qcm9maWxlIDwtIHByb2Z2aXMocnVuQXBwKGFwcERpcj0iYXBwLlIiKSkNCkluaXRpYWxfUHJvZmlsZQ0KYGBgDQoNCkxvb2tpbmcgYXQgb3VyIFtJbml0aWFsX1Byb2ZpbGUsXShodHRwczovL3JwdWJzLmNvbS9SYXlsYW5kL0luaXRfUHJvZmlsZSkgd2UgY2FuIHNlZSB0aGF0IG91ciBBcHAgdGFrZXMgNTkzMG1zIHRvIGluaXRpYWxpemUsIDYzMG1zIHRvIHJ1biB0aGUgb3V0cHV0JGRlbnNpZGFkZXMgZm9yIHRoZSBmaXJzdCB0aW1lIGFuZCAyNDgwbXMgZm9yIHRoZSBzZWNvbmQuDQpXaGF0IHdlIGNhbiBhbHNvIHNlZSBpcyB0aGF0IGl0IHRvb2sgMjY3MC43TUIgb2YgUkFNIHRvIGluaXRpYWxpemUsIHdpY2ggYnkgaXRzZWxmIHdvdWxkIHR1cm4gb3VyIGRyZWFtIHRvIHVwbG9hZCBpdCBvbiBhIGZyZWUgMUdCIHNlcnZlciBpbnRvIGFzaGVzLg0KDQpTdGFydGluZyB0aGUgb3B0aW1pemF0aW9uIHdpdGggdGhlIGluaXRpYWxpemF0aW9uIHNlZW1zIHRvIGJlIG91ciBiZXN0IGNob2ljZSBpbiB0aGlzIHNpdHVhdGlvbiwgc28gbGV0cyBnZXQgc3RhcnRlZC4NCg0KIyMgT3B0aW1pemluZyBpbml0aWFsaXphdGlvbg0KDQpJZiB3ZSBsb29rIGF0IG91ciBhcHAsIHdlIHNlZSB0aGF0IGF0IHRoZSBiZWdpbm5pbmcgd2UgYnVpbGQgdGhlIGNvbXBsZXRlIGRhdGEgc2V0IHRoYXQgd2UgYXJlIGdvaW5nIHRvIHVzZS4NCg0KYGBge3J9DQoNCmNhbWFyYT1iaW5kX3Jvd3MobGlzdChjYW1hcmEyMDA5LA0KICAgICAgICAgICAgICAgICAgICBjYW1hcmEyMDEwLA0KICAgICAgICAgICAgICAgICAgICBjYW1hcmEyMDExLA0KICAgICAgICAgICAgICAgICAgICBjYW1hcmEyMDEyLA0KICAgICAgICAgICAgICAgICAgICBjYW1hcmEyMDEzLA0KICAgICAgICAgICAgICAgICAgICBjYW1hcmEyMDE0LA0KICAgICAgICAgICAgICAgICAgICBjYW1hcmEyMDE1LA0KICAgICAgICAgICAgICAgICAgICBjYW1hcmEyMDE2LA0KICAgICAgICAgICAgICAgICAgICBjYW1hcmEyMDE3LA0KICAgICAgICAgICAgICAgICAgICBjYW1hcmEyMDE4LA0KICAgICAgICAgICAgICAgICAgICBjYW1hcmEyMDE5KQ0KICAgICAgICAgICAgICAgICApICU+JQ0KICBmaWx0ZXIodG90YWxfbmV0X3ZhbHVlPjApICU+JQ0KICBkYXRhLmZyYW1lKGNoZWNrLm5hbWVzID0gRikgJT4lIA0KICBmaWx0ZXIoIWlzLm5hKHRvdGFsX25ldF92YWx1ZSkmIWlzLm5hKGRvY3VtZW50X3ZhbHVlKSkgDQoNCmBgYA0KDQpTbywgd2h5IG5vdCBkb2luZyB0aGlzIGRhdGEgcHJvY2Vzc2luZyBvdXRzaWRlIHRoZSBhcHA/IA0KDQpgYGB7cn0NCg0Kc2F2ZShjYW1hcmEsZmlsZT0iY2FtYXJhIikNCg0KYGBgDQoNCk5vdywgYWxsIHdlIGhhdmUgdG8gZG8gaXMgbG9hZCB0aGUgcHJlIHByb2Nlc3NlZCBkYXRhIGludG8gb3VyIGFwcCB3aXRoIHRoZSBjb21tYW5kIGBsb2FkKCJjYW1hcmEiKWAuDQoNCkxldHMgY2hlY2sgdGhlIHBlcmZvcm1hbmNlIG9mIG91ciBhcHAgbm93Og0KDQpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPVRSVUV9DQpTZWNvbmRfUHJvZmlsZSA8LSBwcm9mdmlzKHJ1bkFwcChhcHBEaXI9ImFwcC5SIikpDQpTZWNvbmRfUHJvZmlsZQ0KDQpgYGANCg0KTG9va2luZyBhdCB0aGUgW1NlY29uZF9Qcm9maWxlLF0oaHR0cHM6Ly9ycHVicy5jb20vUmF5bGFuZC9TZWNvbmRfUHJvZmlsZSkgd2UgY2FuIHNlZSB0aGF0IG91ciBhcHAgdG9vayAzNTYwbXMgdG8gc3RhcnQgYW5kIDc1MS4zTUIgb2YgUkFNIHRvIHJ1biBhbmQgaXQgY2FuIGFscmVhZHkgYmUgdXBsb2FkZWQgdG8gYSBmcmVlIHNlcnZlci4gT3IgY2FuIGl0Pw0KDQoNCkknbSBnb2luZyB0byB1cGRhdGUgdGhpcyBub3RlYm9vayB2ZXJ5IHNvb24gd2l0aCBtb3JlIG9wdGltaXphdGlvbiB0ZWNobmlxdWVzLg0KVGhhbmtzIGZvciByZWFkaW5nLg0K