SlideShare a Scribd company logo
Salenda
Nitro for your Grails App: 

how to improve performance!
Greach ‘18
Alberto De Ávila Hernández
Alberto Barón Cuevas
A B O U T @ A L B E R T O B A R O N 1
@alberto_deavila
@albertoBaron1
✴ Software Engineer
✴ Senior Dev at Salenda
✴ Groovy & Grails dev
A B O U T @ A L B E R T O _ D E AV I L A
✴ Software Engineer
✴ Team Lead at Salenda
✴ Groovy & Grails dev
@alberto_deavila
@albertoBaron1
S A L E N D A
S O F T WA R E D E V E L O P M E N T
Turnkey
development
Atlassian
Solution
Partner
Consulting and
support in
software
architecture and
analysis
Application
integration
Evolutionary support
of our own
developments or
inherited ones
@alberto_deavila
@albertoBaron1
G O A L S
Goals
G O A L S
✴ Different ways to improve performance
✴ Good practices
✴ Common mistakes
✴ Tricks and tips
✴ Tools to measure performance
@alberto_deavila
@albertoBaron1
✴ Improvements outside Grails App
✴ Improvements inside Grails App
✴ Config
✴ Code
✴ Tools
I N D E X
@alberto_deavila
@albertoBaron1
I M P R O V E M E N T S O U T S I D E
Improvements outside
✴ Hardware
✴ Software
✴ Architectural
✴ JVM
✴ Database
I M P R O V E M E N T S I N S I D E
@alberto_deavila
@albertoBaron1
H A R D WA R E I M P R O V E M E N T S
Hardware improvements
@alberto_deavila
@albertoBaron1
H A R D WA R E I M P R O V E M E N T S
✴ Better hard disc: SSD
✴ Increase RAM memory
✴ Better microprocessor
✴ More velocity
✴ More cores
✴ Improve network
@alberto_deavila
@albertoBaron1
H A R D WA R E I M P R O V E M E N T S
@alberto_deavila
@albertoBaron1
A R C H I T E C T U R A L I M P R O V E M E N T S
Arquitectural improvements
@alberto_deavila
@albertoBaron1
A R C H I T E C T U R A L I M P R O V E M E N T S
✴ Multiple web server instances
✴ Load balancers
✴ Proxies
✴ Message quering
✴ Multiple databases
✴ Microservices
@alberto_deavila
@albertoBaron1
A R Q U I T E C T U R A L I M P R O V E M E N T S
@alberto_deavila
@albertoBaron1
J V M I M P R O V E M E N T S
JVM improvements
@alberto_deavila
@albertoBaron1
PA R A M E T E R S
✴VM options:
✴ MaxMetaspaceSize
@alberto_deavila
@albertoBaron1
J AVA 8 PA R A M E T E R S
@alberto_deavila
@albertoBaron1
D ATA B A S E I M P R O V E M E N T S
Database improvements
@alberto_deavila
@albertoBaron1
D ATA B A S E I M P R O V E M E N T S
✴ Monitoring your database performance
✴ Fix slow queries
✴ Use views to execute complex queries
✴ Create indexes in the mains tables
✴ Create a good data model
✴ Do you (only) need relational databases?
@alberto_deavila
@albertoBaron1
D ATA B A S E I M P R O V E M E N T S
@alberto_deavila
@albertoBaron1
I M P R O V E M E N T S I N S I D E
Improvements inside
I M P R O V E M E N T S I N S I D E
Configuration improvements
@alberto_deavila
@albertoBaron1
C O N F I G U R AT I O N I M P R O V E M E N T S
Bootstrap
@alberto_deavila
@albertoBaron1
B O O T S T R A P
✴ Include the minimum code
✴ Configure it by environments
✴ Don’t insert data in Bootstrap: use migrations
✴ Use Promises
@alberto_deavila
@albertoBaron1
B O O T S T R A P
✴ Configure it by environments
@alberto_deavila
@albertoBaron1
import grails.util.Environment
Environment.executeForCurrentEnvironment{
production{
// do something in prod
}
development{
// do something in dev
}
staging{
// do something in custom env
}
}
B O O T S T R A P
✴ Don´t insert data. Use migrations plugin
✴ Manage database changes
✴ Avoid inconsistences
✴ Changelog.groovy file to group changes
@alberto_deavila
@albertoBaron1
databaseChangeLog = {
include file: ‘20180105_BUG-1.groovy’
include file: '20180212_FEATURE-6.groovy'
}
B O O T S T R A P
✴ Promises
@alberto_deavila
@albertoBaron1
def testingPerformance() {
redirect action: 'assistAnotherPresentation', controller: 'greach',
params: [
speak: 'GRAILS 3 TESTING OPTIMIZATION',
speaker: 'Evelina & Tomás',
day: '17th March',
time: '8:30 AM'
]
}
C O N F I G U R AT I O N I M P R O V E M E N T S
Hibernate cache
@alberto_deavila
@albertoBaron1
H I B E R N AT E C A C H E
✴ Second level cache:
✴ Read
✴ Read-Write
✴ Nonstrict-Read-Write
✴ Transactional
@alberto_deavila
@albertoBaron1
H I B E R N AT E C A C H E
✴ Add dependencies to your project
✴ Config:


@alberto_deavila
@albertoBaron1
hibernate:
cache:
use_second_level_cache: true
provider_class: net.sf.ehcache.hibernate.EhCacheProvider
region:
factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory
H I B E R N AT E C A C H E
✴ Cache use:
@alberto_deavila
@albertoBaron1
class Car {
static mapping = {
cache usage: 'read-only'
// 'read-write' || ‘transactional' || ‘nonstrict-read-write’
}
}
class Car {
static hasMany = [wheels: Wheel]
static mapping = {
wheels cache: true
}
}
H I B E R N AT E C A C H E
✴ Cache use:
@alberto_deavila
@albertoBaron1
Car.findByBrand("Tesla", [cache: true])
Car.withCriteria {
like('model', 'Model%')
cache true
}
H I B E R N AT E C A C H E
@alberto_deavila
@albertoBaron1
But be careful with Caches
I M P R O V E M E N T S I N S I D E
Code improvements
@alberto_deavila
@albertoBaron1
C O D E I M P R O V E M E N T S
@CompileStatic
@alberto_deavila
@albertoBaron1
C O D E I M P R O V E M E N T S
Querying
@alberto_deavila
@albertoBaron1
Q U E RY I N G
✴ GORM querying options
@alberto_deavila
@albertoBaron1 http://tatiyants.com/how-and-when-to-use-various-gorm-querying-options/
Q U E RY I N G
✴ Don’t abuse of dynamic finders
✴ Don’t filter / sort a query result, use queries
✴ You can use left join and projections with
criterias
✴ Flush the session in little batches
✴ Give hibernate´ s Stateless session a try
@alberto_deavila
@albertoBaron1
C O D E I M P R O V E M E N T S
Domain classes
@alberto_deavila
@albertoBaron1
D O M A I N C L A S S E S
Autowiring
@alberto_deavila
@albertoBaron1
A U T O R I W I N G
✴ Autowiring services are injected:
✴ Every GORM query result
✴ New domain classes instances
✴ Grails > 3.3.0 autowiring disabled by default
@alberto_deavila
@albertoBaron1
A U T O R I W I N G
✴ Alternatives:
✴ Anemic domain model + logic in services
✴ Taglibs to get logic in view layer
✴ Lazy load services
✴ GORM Event Listeners
@alberto_deavila
@albertoBaron1
lazy load services?
A U T O R I W I N G
@alberto_deavila
@albertoBaron1
D O M A I N C L A S S E S
HasMany
@alberto_deavila
@albertoBaron1
H A S M A N Y
✴ HasMany instances are lazy-loaded by default
✴ All instances are loaded when add new one
✴ Bad performance with entities too big
✴ How to stop using it in:
✴ One to Many
✴ Many to Many
@alberto_deavila
@albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring
H A S M A N Y
One to many
@alberto_deavila
@albertoBaron1
O N E T O M A N Y
✴ Delete the hasMany
✴ Relate the “many” side with the owner:
@alberto_deavila
@albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring
class Person{
String name
}
class Car{
String register
Person owner
}
class Person{
String name
static hasMany = [cars: Car]
}
class Car{
String register
}
H A S M A N Y
Many to many
@alberto_deavila
@albertoBaron1
M A N Y T O M A N Y
✴ Like Spring Security with User - Role relation
✴ Let instances orphans
✴ Map the join relation
✴ Create helpers to use the new relation
✴ Create / remove instances
✴ Finders
@alberto_deavila
@albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring
M A N Y T O M A N Y
@alberto_deavila
@albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring
class Person{
String name
Set<Car> getCars(){
PersonCar.findAllByPerson(this)
.collect { it.car } as Set
}
}
class PersonCar{
Car car
Person person
static PersonCar create(Person person, Car car){
new PersonCar(person: person, car: car).save()
}
static boolean remove (Person person, Car car){
PersonCar personCar = PersonCar.findByPersonAndCar(person, car)
personCar ? personCar?.delete() : false
}
}
class Car{
String register
}
O N E T O M A N Y
✴ You will lose automatic cascade:
✴ You have to delete it manually
✴ Evict cascade problems
✴ Can’t use addTo and removeFrom methods
✴ Implement getter to findAllCarsByUser
@alberto_deavila
@albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring
M A N Y T O M A N Y
✴ Not all models are applicable to this solution
✴ Study your model
✴ Take performance measures
✴ Then decide if use this approach
@alberto_deavila
@albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring
H A S M A N Y
@alberto_deavila
@albertoBaron1
C O D E I M P R O V E M E N T S
Logs
@alberto_deavila
@albertoBaron1
A S Y N C H R O N O U S A P P E N D E R S
Asynchronous Appenders
@alberto_deavila
@albertoBaron1
A S Y N C H R O N O U S A P P E N D E R S
✴ Appender:
✴ Delivering LogEvents to their destination
✴ AsyncAppender
✴ Lets users log events asynchronously
✴ How work is passed between threads?
✴Use ArrayBlockingQueue implementation
@alberto_deavila
@albertoBaron1
A S Y N C H R O N O U S L O G G E R S
Asynchronous Loggers
@alberto_deavila
@albertoBaron1
A S Y N C H R O N O U S L O G G E R S
✴ Concepts related with performance:
✴ Latency: required time to perform an action
✴ Throughput: nº of executed actions / time
@alberto_deavila
@albertoBaron1
To increase logging performance, we want
lower latency and higher throughput
A S Y N C H R O N O U S L O G G E R S
✴ How work is passed between threads?
✴ LMAX Disruptor technology
@alberto_deavila
@albertoBaron1
“A lock-free inter-thread communication library,
instead of queues, resulting in higher throughput
and lower latency.”
https://logging.apache.org/log4j/2.x/manual/async.html#UnderTheHood
A S Y N C H R O N O U S L O G G E R S
@alberto_deavila
@albertoBaron1 https://logging.apache.org/log4j/2.x/manual/async.html
A S Y N C H R O N O U S L O G G E R S
@alberto_deavila
@albertoBaron1
C O D E I M P R O V E M E N T S
Data processing
@alberto_deavila
@albertoBaron1
D ATA P R O C E S S I N G
✴ Grails promises
✴ Use the cache plugin
✴ Avoid repetitive querying
✴ Async processing
✴ GPars
@alberto_deavila
@albertoBaron1
D ATA P R O C E S S I N G
Cache plugin
@alberto_deavila
@albertoBaron1
C A C H E P L U G I N
✴ Plugin for Grails 2 & 3 (under development)
✴ Cache methods responses and tags
✴ Easy to use and configure
✴ Possibility to create any differents caches
✴ Cached items have no timeout
@alberto_deavila
@albertoBaron1
✴ To store values in the cache:
✴ To get the cached values:
C A C H E P L U G I N
@alberto_deavila
@albertoBaron1
@Cacheable(value = 'message', key = { title.toUpperCase() } )
Message getMessage(String title) {
log.debug 'Fetching message'
Message.findByTitle(title)
}
}
@CachePut(value='message', key = { message.title.toUpperCase() })
void save(Message message) {
log.debug "Saving message $message"
message.save()
}
✴ To delete values from cache:
✴ Trick: you can combine annotations
C A C H E P L U G I N
@alberto_deavila
@albertoBaron1
@CacheEvict(value = 'message', key = { message.title })
void delete(Message message) {
log.debug "Deleting message $message"
message.delete()
}
C A C H E P L U G I N
@alberto_deavila
@albertoBaron1
D ATA P R O C E S S I N G
Avoid repetitive querying
@alberto_deavila
@albertoBaron1
AV O I D R E P E T I T I V E Q U E RY I N G
✴ We have the following code:
@alberto_deavila
@albertoBaron1
def myMethod(){
List<String> names = ['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie']
//up to 100 Simpsons names
names.each{ String name ->
Character character = Character.findByName(name)
// some actions
character.save()
}
}
AV O I D R E P E T I T I V E Q U E RY I N G
✴ We can refactor it to:
@alberto_deavila
@albertoBaron1
def myRefactoredMethod(){
List<String> names = ['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie']
//up to 100 Simpsons names
List<Character> characters = Character.findByNameInList(names)
characters.each{ Character character ->
// some actions
}
characters*.save()
}
AV O I D R E P E T I T I V E Q U E RY I N G
✴ We have the following code:
@alberto_deavila
@albertoBaron1
def myServiceMethod(){
List<Long> ids = [1, 2, 3, 4, 5] //up to 100 ids
ids.each{ Long id ->
Character character = Character.get(id)
// some actions
character.save()
}
}
AV O I D R E P E T I T I V E Q U E RY I N G
✴ We can refactor it to:
@alberto_deavila
@albertoBaron1
def myRefactoredAction2(){
List<Long> ids = [1, 2, 3, 4, 5] //up to 100 ids
List<Character> characters = Character.getAll(ids)
characters.each{ Character character ->
// some actions
}
characters*.save()
}
AV O I D R E P E T I T I V E Q U E RY I N G
@alberto_deavila
@albertoBaron1
D ATA P R O C E S S I N G
Async data processing
@alberto_deavila
@albertoBaron1
A S Y N C D ATA P R O C E S S I N G
✴ 100 factorial with threads & shared memory:
@alberto_deavila
@albertoBaron1
Long result = 1g
List threads = []
(1..100).each { number ->
threads << Thread.start {
synchronized(this) {
result = result * number
}
}
}
threads*.join()
log.debug result
A S Y N C D ATA P R O C E S S I N G
✴ Process a request asynchronously
@alberto_deavila
@albertoBaron1
def myAction(){
Thread.start {
// do slow work in background
// Send an email or some kind of notification
}
render "We are working on it!"
}
A S Y N C D ATA P R O C E S S I N G
@alberto_deavila
@albertoBaron1
D ATA P R O C E S S I N G
GPars
@alberto_deavila
@albertoBaron1
G PA R S
✴ GPars is a framework to do concurrent tasks
✴ Works with Java and Groovy
✴ Make concurrent programming easy
✴ Provide us multiple solutions for parallelism
@alberto_deavila
@albertoBaron1
G PA R S
✴ An example with parallel collections:
@alberto_deavila
@albertoBaron1
//summarize numbers concurrently
GParsPool.withPool {
final AtomicInteger amount = new AtomicInteger(0)
[1, 2, 3, 4, 5].eachParallel {amount.addAndGet(it)}
assert 15 == result
}
G PA R S
✴ An example with async call:
@alberto_deavila
@albertoBaron1
GParsPool.withPool() {
assert 6 == {it * 2}.callAsync(3).get()
}
G PA R S
✴ But there are more GPars features:
✴ Actors
✴ Agents
✴ Dataflow
✴ Fork-join
@alberto_deavila
@albertoBaron1
G PA R S
@alberto_deavila
@albertoBaron1
C O D E I M P R O V E M E N T S
Views
@alberto_deavila
@albertoBaron1
V I E W S
✴ Compress resources:
✴ Group resources in Manifest
@alberto_deavila
@albertoBaron1
assets {
minifyJs=true
minifyCss=true
excludes=[“**/*.html”]
}
/*
* =require file1.css
* =require file2.css
*/
<asset:javascript src=“manifest.js” />
assets/javascript/manifest.js
V I E W S
✴ Avoid ask for resources external
✴ Download JS or CSS files in local
@alberto_deavila
@albertoBaron1
V I E W S
Content Delivery Network
@alberto_deavila
@albertoBaron1
V I E W S
✴ Use CDN for static files
✴Network of servers spread over the world
✴Shows statically the content of websites
✴Static content cached and stored on servers
✴Delivery determined by location of visitors
✴Static files include html, css, JS or images
@alberto_deavila
@albertoBaron1
V I E W S
@alberto_deavila
@albertoBaron1
V I E W S
✴ Set up CDN in a Grails App
✴Install two plugins in BuildConfig
✴SetUp a CloudFront
✴Put CDN details in Config
✴Push local assets to cloud: assets-cdn-push
@alberto_deavila
@albertoBaron1
compile “:cdn-asset-pipeline:0.4.1”
compile “:karman:0.6.1”
C O D E I M P R O V E M E N T S
Regex
@alberto_deavila
@albertoBaron1
R E G E X
@alberto_deavila
@albertoBaron1
R E G E X
✴ Main Tools
✴ JRegExAnalyser
✴ RegexBuddy
✴ Debuggex
✴ Rubular
✴ RegexPal
@alberto_deavila
@albertoBaron1
R E G E X
✴ RegExp against bad backtracking:
http://www.regular-expressions.info/catastrophic.html
@alberto_deavila
@albertoBaron1
“When nesting repetition operators, make
sure that there is only one way to match the
same match”
C O D E I M P R O V E M E N T S
Testing
@alberto_deavila
@albertoBaron1
T E S T I N G
def testingPerformance() {
redirect action: 'assistAnotherPresentation', controller: 'greach',
params: [
speak: 'GRAILS 3 TESTING OPTIMIZATION',
speaker: 'Evelina & Tomás',
day: '17th March',
time: '8:30 AM'
]
}
@alberto_deavila
@albertoBaron1
T O O L S
Tools
T O O L S
✴ Many tools to measure performance
✴ JavaMelody
✴ App dynamics
✴ New relic
✴ Dynatrace
@alberto_deavila
@albertoBaron1
J AVA M E L O D Y
@alberto_deavila
@albertoBaron1
def javaMelodyTool() {
redirect action: 'assistAnotherPresentation', controller: 'greach',
params: [
speak: 'JavaMelody to measure Grails app performance',
speaker: 'Miguel Angel García',
day: '17th March',
time: '11:45 AM'
]
}
T O O L S
@alberto_deavila
@albertoBaron1
T O O L S
✴ Real time application
✴ Application performance monitoring
✴ Available to multiple technologies
✴ Database monitoring
✴ Server topology auto discovered
@alberto_deavila
@albertoBaron1
T O O L S
@alberto_deavila
@albertoBaron1
T O O L S
@alberto_deavila
@albertoBaron1
T O O L S
@alberto_deavila
@albertoBaron1
T O O L S
@alberto_deavila
@albertoBaron1
T O O L S
@alberto_deavila
@albertoBaron1
T O O L S
@alberto_deavila
@albertoBaron1
C O N C L U S I O N S
Conclusions
C O N C L U S I O N S
✴ Performance doesn't only depend on Grails
✴ Improve Grails performance in many ways
✴ Performance is a culture
✴ Performance has costs, but less than fix it later
✴ Easy to improve performance little by little
✴ Use tools to help you measure indicators
@alberto_deavila
@albertoBaron1
Q U E S T I O N S
Questions
SalendaThank you!
@alberto_deavila
@albertoBaron1

More Related Content

What's hot

How to Make WordPress Your Friend
How to Make WordPress Your FriendHow to Make WordPress Your Friend
How to Make WordPress Your Friendkerchmcc
 
SEO Before Yoast: WordCamp Rhode Island
SEO Before Yoast: WordCamp Rhode IslandSEO Before Yoast: WordCamp Rhode Island
SEO Before Yoast: WordCamp Rhode IslandKerch McConlogue
 
Solving Complex JavaScript Issues and Leveraging Semantic HTML5
Solving Complex JavaScript Issues and Leveraging Semantic HTML5Solving Complex JavaScript Issues and Leveraging Semantic HTML5
Solving Complex JavaScript Issues and Leveraging Semantic HTML5Hamlet Batista
 
Agular in a microservices world
Agular in a microservices worldAgular in a microservices world
Agular in a microservices worldBrecht Billiet
 
How To Tackle Enterprise Sites - Rachel Costello, Technical SEO, DeepCrawl
How To Tackle Enterprise Sites - Rachel Costello, Technical SEO, DeepCrawlHow To Tackle Enterprise Sites - Rachel Costello, Technical SEO, DeepCrawl
How To Tackle Enterprise Sites - Rachel Costello, Technical SEO, DeepCrawlDeepCrawl
 
Philadelphiaworkerscompensationbodypartsdm83
Philadelphiaworkerscompensationbodypartsdm83Philadelphiaworkerscompensationbodypartsdm83
Philadelphiaworkerscompensationbodypartsdm83Michael Murray
 
Page Experience Update TMC June 2021 Patrick Stox
Page Experience Update TMC June 2021 Patrick StoxPage Experience Update TMC June 2021 Patrick Stox
Page Experience Update TMC June 2021 Patrick Stoxpatrickstox
 
Building Gutenberg Applications & WebOPS Case Study
Building Gutenberg Applications & WebOPS Case StudyBuilding Gutenberg Applications & WebOPS Case Study
Building Gutenberg Applications & WebOPS Case StudyRoy Sivan
 
VP R&D Open Seminar: Caching
VP R&D Open Seminar: CachingVP R&D Open Seminar: Caching
VP R&D Open Seminar: CachingMoshe Kaplan
 
Dumb and smart components + redux (1)
Dumb and smart components + redux (1)Dumb and smart components + redux (1)
Dumb and smart components + redux (1)Brecht Billiet
 
Jacob Hagberg - Real World SEO Examples Every Digital Marketer Can Learn From
Jacob Hagberg - Real World SEO Examples Every Digital Marketer Can Learn FromJacob Hagberg - Real World SEO Examples Every Digital Marketer Can Learn From
Jacob Hagberg - Real World SEO Examples Every Digital Marketer Can Learn FromJulia Grosman
 
Compose all the things
Compose all the thingsCompose all the things
Compose all the thingsThomas Sojka
 
Facebook Social Plugins
Facebook Social PluginsFacebook Social Plugins
Facebook Social PluginsAizat Faiz
 
Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...
Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...
Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...Philip Tellis
 
Creating Book Trailers
Creating Book TrailersCreating Book Trailers
Creating Book TrailersNaomi Bates
 
rel canonical audit BrightonSEO September 2018
rel canonical audit BrightonSEO September 2018rel canonical audit BrightonSEO September 2018
rel canonical audit BrightonSEO September 2018Mark Thomas
 

What's hot (19)

10 Smart & Easy LinkedIn Background Images
10 Smart & Easy LinkedIn Background Images10 Smart & Easy LinkedIn Background Images
10 Smart & Easy LinkedIn Background Images
 
How to Make WordPress Your Friend
How to Make WordPress Your FriendHow to Make WordPress Your Friend
How to Make WordPress Your Friend
 
SEO Before Yoast: WordCamp Rhode Island
SEO Before Yoast: WordCamp Rhode IslandSEO Before Yoast: WordCamp Rhode Island
SEO Before Yoast: WordCamp Rhode Island
 
Rebuilding our Foundation
Rebuilding our FoundationRebuilding our Foundation
Rebuilding our Foundation
 
Solving Complex JavaScript Issues and Leveraging Semantic HTML5
Solving Complex JavaScript Issues and Leveraging Semantic HTML5Solving Complex JavaScript Issues and Leveraging Semantic HTML5
Solving Complex JavaScript Issues and Leveraging Semantic HTML5
 
Agular in a microservices world
Agular in a microservices worldAgular in a microservices world
Agular in a microservices world
 
How To Tackle Enterprise Sites - Rachel Costello, Technical SEO, DeepCrawl
How To Tackle Enterprise Sites - Rachel Costello, Technical SEO, DeepCrawlHow To Tackle Enterprise Sites - Rachel Costello, Technical SEO, DeepCrawl
How To Tackle Enterprise Sites - Rachel Costello, Technical SEO, DeepCrawl
 
Philadelphiaworkerscompensationbodypartsdm83
Philadelphiaworkerscompensationbodypartsdm83Philadelphiaworkerscompensationbodypartsdm83
Philadelphiaworkerscompensationbodypartsdm83
 
Page Experience Update TMC June 2021 Patrick Stox
Page Experience Update TMC June 2021 Patrick StoxPage Experience Update TMC June 2021 Patrick Stox
Page Experience Update TMC June 2021 Patrick Stox
 
Building Gutenberg Applications & WebOPS Case Study
Building Gutenberg Applications & WebOPS Case StudyBuilding Gutenberg Applications & WebOPS Case Study
Building Gutenberg Applications & WebOPS Case Study
 
VP R&D Open Seminar: Caching
VP R&D Open Seminar: CachingVP R&D Open Seminar: Caching
VP R&D Open Seminar: Caching
 
Dumb and smart components + redux (1)
Dumb and smart components + redux (1)Dumb and smart components + redux (1)
Dumb and smart components + redux (1)
 
Jacob Hagberg - Real World SEO Examples Every Digital Marketer Can Learn From
Jacob Hagberg - Real World SEO Examples Every Digital Marketer Can Learn FromJacob Hagberg - Real World SEO Examples Every Digital Marketer Can Learn From
Jacob Hagberg - Real World SEO Examples Every Digital Marketer Can Learn From
 
Compose all the things
Compose all the thingsCompose all the things
Compose all the things
 
Facebook Social Plugins
Facebook Social PluginsFacebook Social Plugins
Facebook Social Plugins
 
Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...
Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...
Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...
 
Jabber Bot
Jabber BotJabber Bot
Jabber Bot
 
Creating Book Trailers
Creating Book TrailersCreating Book Trailers
Creating Book Trailers
 
rel canonical audit BrightonSEO September 2018
rel canonical audit BrightonSEO September 2018rel canonical audit BrightonSEO September 2018
rel canonical audit BrightonSEO September 2018
 

Similar to Nitro for your Grails App: How to improve performance!! Greach' 18

Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...Alberto De Ávila Hernández
 
What Does Your Smart Car Know About You? Strata London 2016
What Does Your Smart Car Know About You?  Strata London 2016What Does Your Smart Car Know About You?  Strata London 2016
What Does Your Smart Car Know About You? Strata London 2016Charles Givre
 
Build a production ready PWA with Angular and Firebase
Build a production ready PWA with Angular and FirebaseBuild a production ready PWA with Angular and Firebase
Build a production ready PWA with Angular and FirebaseÖnder Ceylan
 
Feedback en continu grâce au TDD et au AsCode
Feedback en continu grâce au TDD et au AsCodeFeedback en continu grâce au TDD et au AsCode
Feedback en continu grâce au TDD et au AsCodeHaja R
 
JoomlaDay Conference_September 2023 PDF.pdf
JoomlaDay Conference_September 2023 PDF.pdfJoomlaDay Conference_September 2023 PDF.pdf
JoomlaDay Conference_September 2023 PDF.pdfOliver Brett
 
Building Next Generation Applications With BuddyPress
Building Next Generation Applications With BuddyPressBuilding Next Generation Applications With BuddyPress
Building Next Generation Applications With BuddyPressDavid Bisset
 
There's More Than 1 Way To Skin A Theme
There's More Than 1 Way To Skin A ThemeThere's More Than 1 Way To Skin A Theme
There's More Than 1 Way To Skin A ThemeSennza Design
 
Diff and Merge with Ease: EMF Compare
Diff and Merge with Ease: EMF CompareDiff and Merge with Ease: EMF Compare
Diff and Merge with Ease: EMF Comparemikaelbarbero
 
DevOps 101 for data professionals
DevOps 101 for data professionalsDevOps 101 for data professionals
DevOps 101 for data professionalsAlex Yates
 
Build social network in 4 weeks
Build social network in 4 weeksBuild social network in 4 weeks
Build social network in 4 weeksYan Cui
 
Build a production ready PWA - LINKIT & KLM Digital Studio Meetup
Build a production ready PWA - LINKIT & KLM Digital Studio MeetupBuild a production ready PWA - LINKIT & KLM Digital Studio Meetup
Build a production ready PWA - LINKIT & KLM Digital Studio MeetupÖnder Ceylan
 
Legacy: A Retrospective - Open West 2016
Legacy: A Retrospective - Open West 2016Legacy: A Retrospective - Open West 2016
Legacy: A Retrospective - Open West 2016Jessica Mauerhan
 
Manage custom options pages in Wordpress
Manage custom options pages in WordpressManage custom options pages in Wordpress
Manage custom options pages in WordpressSimone D'Amico
 
Docker Docker - Docker Security - Docker
Docker Docker - Docker Security - DockerDocker Docker - Docker Security - Docker
Docker Docker - Docker Security - DockerBoyd Hemphill
 
Container Days NYC Keynote
Container Days NYC KeynoteContainer Days NYC Keynote
Container Days NYC KeynoteBoyd Hemphill
 
Introducing Backblaze B2, the lowest cost cloud storage on the planet.
Introducing Backblaze B2, the lowest cost cloud storage on the planet.Introducing Backblaze B2, the lowest cost cloud storage on the planet.
Introducing Backblaze B2, the lowest cost cloud storage on the planet.Backblaze
 

Similar to Nitro for your Grails App: How to improve performance!! Greach' 18 (20)

Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
Testing Grails 3, the goob (unit), the bad (integration) and the ugly (functi...
 
Graalvm with Groovy and Kotlin - Madrid GUG 2019
Graalvm with Groovy and Kotlin - Madrid GUG 2019Graalvm with Groovy and Kotlin - Madrid GUG 2019
Graalvm with Groovy and Kotlin - Madrid GUG 2019
 
Graalvm with Groovy and Kotlin - Greach 2019
Graalvm with Groovy and Kotlin - Greach 2019Graalvm with Groovy and Kotlin - Greach 2019
Graalvm with Groovy and Kotlin - Greach 2019
 
What Does Your Smart Car Know About You? Strata London 2016
What Does Your Smart Car Know About You?  Strata London 2016What Does Your Smart Car Know About You?  Strata London 2016
What Does Your Smart Car Know About You? Strata London 2016
 
Build a production ready PWA with Angular and Firebase
Build a production ready PWA with Angular and FirebaseBuild a production ready PWA with Angular and Firebase
Build a production ready PWA with Angular and Firebase
 
Feedback en continu grâce au TDD et au AsCode
Feedback en continu grâce au TDD et au AsCodeFeedback en continu grâce au TDD et au AsCode
Feedback en continu grâce au TDD et au AsCode
 
Greach'19 SonarLint
Greach'19 SonarLintGreach'19 SonarLint
Greach'19 SonarLint
 
JoomlaDay Conference_September 2023 PDF.pdf
JoomlaDay Conference_September 2023 PDF.pdfJoomlaDay Conference_September 2023 PDF.pdf
JoomlaDay Conference_September 2023 PDF.pdf
 
Building Next Generation Applications With BuddyPress
Building Next Generation Applications With BuddyPressBuilding Next Generation Applications With BuddyPress
Building Next Generation Applications With BuddyPress
 
There's More Than 1 Way To Skin A Theme
There's More Than 1 Way To Skin A ThemeThere's More Than 1 Way To Skin A Theme
There's More Than 1 Way To Skin A Theme
 
BuddyPress v4
BuddyPress v4BuddyPress v4
BuddyPress v4
 
Diff and Merge with Ease: EMF Compare
Diff and Merge with Ease: EMF CompareDiff and Merge with Ease: EMF Compare
Diff and Merge with Ease: EMF Compare
 
DevOps 101 for data professionals
DevOps 101 for data professionalsDevOps 101 for data professionals
DevOps 101 for data professionals
 
Build social network in 4 weeks
Build social network in 4 weeksBuild social network in 4 weeks
Build social network in 4 weeks
 
Build a production ready PWA - LINKIT & KLM Digital Studio Meetup
Build a production ready PWA - LINKIT & KLM Digital Studio MeetupBuild a production ready PWA - LINKIT & KLM Digital Studio Meetup
Build a production ready PWA - LINKIT & KLM Digital Studio Meetup
 
Legacy: A Retrospective - Open West 2016
Legacy: A Retrospective - Open West 2016Legacy: A Retrospective - Open West 2016
Legacy: A Retrospective - Open West 2016
 
Manage custom options pages in Wordpress
Manage custom options pages in WordpressManage custom options pages in Wordpress
Manage custom options pages in Wordpress
 
Docker Docker - Docker Security - Docker
Docker Docker - Docker Security - DockerDocker Docker - Docker Security - Docker
Docker Docker - Docker Security - Docker
 
Container Days NYC Keynote
Container Days NYC KeynoteContainer Days NYC Keynote
Container Days NYC Keynote
 
Introducing Backblaze B2, the lowest cost cloud storage on the planet.
Introducing Backblaze B2, the lowest cost cloud storage on the planet.Introducing Backblaze B2, the lowest cost cloud storage on the planet.
Introducing Backblaze B2, the lowest cost cloud storage on the planet.
 

Recently uploaded

AI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekAI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekCzechDreamin
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersSafe Software
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...Product School
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...Product School
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonDianaGray10
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxAbida Shariff
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor TurskyiFwdays
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...Elena Simperl
 
UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2DianaGray10
 
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptxUnpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptxDavid Michel
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...UiPathCommunity
 
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlPeter Udo Diehl
 
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...CzechDreamin
 
In-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT ProfessionalsIn-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT ProfessionalsExpeed Software
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualityInflectra
 
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀DianaGray10
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...Product School
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaRTTS
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesBhaskar Mitra
 
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya HalderCustom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya HalderCzechDreamin
 

Recently uploaded (20)

AI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří KarpíšekAI revolution and Salesforce, Jiří Karpíšek
AI revolution and Salesforce, Jiří Karpíšek
 
Essentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with ParametersEssentials of Automations: Optimizing FME Workflows with Parameters
Essentials of Automations: Optimizing FME Workflows with Parameters
 
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
From Siloed Products to Connected Ecosystem: Building a Sustainable and Scala...
 
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
De-mystifying Zero to One: Design Informed Techniques for Greenfield Innovati...
 
Connector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a buttonConnector Corner: Automate dynamic content and events by pushing a button
Connector Corner: Automate dynamic content and events by pushing a button
 
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptxIOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
IOS-PENTESTING-BEGINNERS-PRACTICAL-GUIDE-.pptx
 
"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi"Impact of front-end architecture on development cost", Viktor Turskyi
"Impact of front-end architecture on development cost", Viktor Turskyi
 
When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...When stars align: studies in data quality, knowledge graphs, and machine lear...
When stars align: studies in data quality, knowledge graphs, and machine lear...
 
UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2UiPath Test Automation using UiPath Test Suite series, part 2
UiPath Test Automation using UiPath Test Suite series, part 2
 
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptxUnpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
Unpacking Value Delivery - Agile Oxford Meetup - May 2024.pptx
 
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
Dev Dives: Train smarter, not harder – active learning and UiPath LLMs for do...
 
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo DiehlFuture Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
Future Visions: Predictions to Guide and Time Tech Innovation, Peter Udo Diehl
 
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
Behind the Scenes From the Manager's Chair: Decoding the Secrets of Successfu...
 
In-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT ProfessionalsIn-Depth Performance Testing Guide for IT Professionals
In-Depth Performance Testing Guide for IT Professionals
 
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered QualitySoftware Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
Software Delivery At the Speed of AI: Inflectra Invests In AI-Powered Quality
 
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
Exploring UiPath Orchestrator API: updates and limits in 2024 🚀
 
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
AI for Every Business: Unlocking Your Product's Universal Potential by VP of ...
 
JMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and GrafanaJMeter webinar - integration with InfluxDB and Grafana
JMeter webinar - integration with InfluxDB and Grafana
 
Search and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical FuturesSearch and Society: Reimagining Information Access for Radical Futures
Search and Society: Reimagining Information Access for Radical Futures
 
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya HalderCustom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
 

Nitro for your Grails App: How to improve performance!! Greach' 18

  • 1. Salenda Nitro for your Grails App: 
 how to improve performance! Greach ‘18 Alberto De Ávila Hernández Alberto Barón Cuevas
  • 2. A B O U T @ A L B E R T O B A R O N 1 @alberto_deavila @albertoBaron1 ✴ Software Engineer ✴ Senior Dev at Salenda ✴ Groovy & Grails dev
  • 3. A B O U T @ A L B E R T O _ D E AV I L A ✴ Software Engineer ✴ Team Lead at Salenda ✴ Groovy & Grails dev @alberto_deavila @albertoBaron1
  • 4. S A L E N D A
  • 5. S O F T WA R E D E V E L O P M E N T Turnkey development Atlassian Solution Partner Consulting and support in software architecture and analysis Application integration Evolutionary support of our own developments or inherited ones @alberto_deavila @albertoBaron1
  • 6. G O A L S Goals
  • 7. G O A L S ✴ Different ways to improve performance ✴ Good practices ✴ Common mistakes ✴ Tricks and tips ✴ Tools to measure performance @alberto_deavila @albertoBaron1
  • 8. ✴ Improvements outside Grails App ✴ Improvements inside Grails App ✴ Config ✴ Code ✴ Tools I N D E X @alberto_deavila @albertoBaron1
  • 9. I M P R O V E M E N T S O U T S I D E Improvements outside
  • 10. ✴ Hardware ✴ Software ✴ Architectural ✴ JVM ✴ Database I M P R O V E M E N T S I N S I D E @alberto_deavila @albertoBaron1
  • 11. H A R D WA R E I M P R O V E M E N T S Hardware improvements @alberto_deavila @albertoBaron1
  • 12. H A R D WA R E I M P R O V E M E N T S ✴ Better hard disc: SSD ✴ Increase RAM memory ✴ Better microprocessor ✴ More velocity ✴ More cores ✴ Improve network @alberto_deavila @albertoBaron1
  • 13. H A R D WA R E I M P R O V E M E N T S @alberto_deavila @albertoBaron1
  • 14. A R C H I T E C T U R A L I M P R O V E M E N T S Arquitectural improvements @alberto_deavila @albertoBaron1
  • 15. A R C H I T E C T U R A L I M P R O V E M E N T S ✴ Multiple web server instances ✴ Load balancers ✴ Proxies ✴ Message quering ✴ Multiple databases ✴ Microservices @alberto_deavila @albertoBaron1
  • 16. A R Q U I T E C T U R A L I M P R O V E M E N T S @alberto_deavila @albertoBaron1
  • 17. J V M I M P R O V E M E N T S JVM improvements @alberto_deavila @albertoBaron1
  • 18. PA R A M E T E R S ✴VM options: ✴ MaxMetaspaceSize @alberto_deavila @albertoBaron1
  • 19. J AVA 8 PA R A M E T E R S @alberto_deavila @albertoBaron1
  • 20. D ATA B A S E I M P R O V E M E N T S Database improvements @alberto_deavila @albertoBaron1
  • 21. D ATA B A S E I M P R O V E M E N T S ✴ Monitoring your database performance ✴ Fix slow queries ✴ Use views to execute complex queries ✴ Create indexes in the mains tables ✴ Create a good data model ✴ Do you (only) need relational databases? @alberto_deavila @albertoBaron1
  • 22. D ATA B A S E I M P R O V E M E N T S @alberto_deavila @albertoBaron1
  • 23. I M P R O V E M E N T S I N S I D E Improvements inside
  • 24. I M P R O V E M E N T S I N S I D E Configuration improvements @alberto_deavila @albertoBaron1
  • 25. C O N F I G U R AT I O N I M P R O V E M E N T S Bootstrap @alberto_deavila @albertoBaron1
  • 26. B O O T S T R A P ✴ Include the minimum code ✴ Configure it by environments ✴ Don’t insert data in Bootstrap: use migrations ✴ Use Promises @alberto_deavila @albertoBaron1
  • 27. B O O T S T R A P ✴ Configure it by environments @alberto_deavila @albertoBaron1 import grails.util.Environment Environment.executeForCurrentEnvironment{ production{ // do something in prod } development{ // do something in dev } staging{ // do something in custom env } }
  • 28. B O O T S T R A P ✴ Don´t insert data. Use migrations plugin ✴ Manage database changes ✴ Avoid inconsistences ✴ Changelog.groovy file to group changes @alberto_deavila @albertoBaron1 databaseChangeLog = { include file: ‘20180105_BUG-1.groovy’ include file: '20180212_FEATURE-6.groovy' }
  • 29. B O O T S T R A P ✴ Promises @alberto_deavila @albertoBaron1 def testingPerformance() { redirect action: 'assistAnotherPresentation', controller: 'greach', params: [ speak: 'GRAILS 3 TESTING OPTIMIZATION', speaker: 'Evelina & Tomás', day: '17th March', time: '8:30 AM' ] }
  • 30. C O N F I G U R AT I O N I M P R O V E M E N T S Hibernate cache @alberto_deavila @albertoBaron1
  • 31. H I B E R N AT E C A C H E ✴ Second level cache: ✴ Read ✴ Read-Write ✴ Nonstrict-Read-Write ✴ Transactional @alberto_deavila @albertoBaron1
  • 32. H I B E R N AT E C A C H E ✴ Add dependencies to your project ✴ Config: 
 @alberto_deavila @albertoBaron1 hibernate: cache: use_second_level_cache: true provider_class: net.sf.ehcache.hibernate.EhCacheProvider region: factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory
  • 33. H I B E R N AT E C A C H E ✴ Cache use: @alberto_deavila @albertoBaron1 class Car { static mapping = { cache usage: 'read-only' // 'read-write' || ‘transactional' || ‘nonstrict-read-write’ } } class Car { static hasMany = [wheels: Wheel] static mapping = { wheels cache: true } }
  • 34. H I B E R N AT E C A C H E ✴ Cache use: @alberto_deavila @albertoBaron1 Car.findByBrand("Tesla", [cache: true]) Car.withCriteria { like('model', 'Model%') cache true }
  • 35. H I B E R N AT E C A C H E @alberto_deavila @albertoBaron1 But be careful with Caches
  • 36. I M P R O V E M E N T S I N S I D E Code improvements @alberto_deavila @albertoBaron1
  • 37. C O D E I M P R O V E M E N T S @CompileStatic @alberto_deavila @albertoBaron1
  • 38. C O D E I M P R O V E M E N T S Querying @alberto_deavila @albertoBaron1
  • 39. Q U E RY I N G ✴ GORM querying options @alberto_deavila @albertoBaron1 http://tatiyants.com/how-and-when-to-use-various-gorm-querying-options/
  • 40. Q U E RY I N G ✴ Don’t abuse of dynamic finders ✴ Don’t filter / sort a query result, use queries ✴ You can use left join and projections with criterias ✴ Flush the session in little batches ✴ Give hibernate´ s Stateless session a try @alberto_deavila @albertoBaron1
  • 41. C O D E I M P R O V E M E N T S Domain classes @alberto_deavila @albertoBaron1
  • 42. D O M A I N C L A S S E S Autowiring @alberto_deavila @albertoBaron1
  • 43. A U T O R I W I N G ✴ Autowiring services are injected: ✴ Every GORM query result ✴ New domain classes instances ✴ Grails > 3.3.0 autowiring disabled by default @alberto_deavila @albertoBaron1
  • 44. A U T O R I W I N G ✴ Alternatives: ✴ Anemic domain model + logic in services ✴ Taglibs to get logic in view layer ✴ Lazy load services ✴ GORM Event Listeners @alberto_deavila @albertoBaron1 lazy load services?
  • 45. A U T O R I W I N G @alberto_deavila @albertoBaron1
  • 46. D O M A I N C L A S S E S HasMany @alberto_deavila @albertoBaron1
  • 47. H A S M A N Y ✴ HasMany instances are lazy-loaded by default ✴ All instances are loaded when add new one ✴ Bad performance with entities too big ✴ How to stop using it in: ✴ One to Many ✴ Many to Many @alberto_deavila @albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring
  • 48. H A S M A N Y One to many @alberto_deavila @albertoBaron1
  • 49. O N E T O M A N Y ✴ Delete the hasMany ✴ Relate the “many” side with the owner: @alberto_deavila @albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring class Person{ String name } class Car{ String register Person owner } class Person{ String name static hasMany = [cars: Car] } class Car{ String register }
  • 50. H A S M A N Y Many to many @alberto_deavila @albertoBaron1
  • 51. M A N Y T O M A N Y ✴ Like Spring Security with User - Role relation ✴ Let instances orphans ✴ Map the join relation ✴ Create helpers to use the new relation ✴ Create / remove instances ✴ Finders @alberto_deavila @albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring
  • 52. M A N Y T O M A N Y @alberto_deavila @albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring class Person{ String name Set<Car> getCars(){ PersonCar.findAllByPerson(this) .collect { it.car } as Set } } class PersonCar{ Car car Person person static PersonCar create(Person person, Car car){ new PersonCar(person: person, car: car).save() } static boolean remove (Person person, Car car){ PersonCar personCar = PersonCar.findByPersonAndCar(person, car) personCar ? personCar?.delete() : false } } class Car{ String register }
  • 53. O N E T O M A N Y ✴ You will lose automatic cascade: ✴ You have to delete it manually ✴ Evict cascade problems ✴ Can’t use addTo and removeFrom methods ✴ Implement getter to findAllCarsByUser @alberto_deavila @albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring
  • 54. M A N Y T O M A N Y ✴ Not all models are applicable to this solution ✴ Study your model ✴ Take performance measures ✴ Then decide if use this approach @alberto_deavila @albertoBaron1 From Burt Beckwith talk in 2009: https://es.slideshare.net/burtbeckwith/advanced-gorm-performance-customization-and-monitoring
  • 55. H A S M A N Y @alberto_deavila @albertoBaron1
  • 56. C O D E I M P R O V E M E N T S Logs @alberto_deavila @albertoBaron1
  • 57. A S Y N C H R O N O U S A P P E N D E R S Asynchronous Appenders @alberto_deavila @albertoBaron1
  • 58. A S Y N C H R O N O U S A P P E N D E R S ✴ Appender: ✴ Delivering LogEvents to their destination ✴ AsyncAppender ✴ Lets users log events asynchronously ✴ How work is passed between threads? ✴Use ArrayBlockingQueue implementation @alberto_deavila @albertoBaron1
  • 59. A S Y N C H R O N O U S L O G G E R S Asynchronous Loggers @alberto_deavila @albertoBaron1
  • 60. A S Y N C H R O N O U S L O G G E R S ✴ Concepts related with performance: ✴ Latency: required time to perform an action ✴ Throughput: nº of executed actions / time @alberto_deavila @albertoBaron1 To increase logging performance, we want lower latency and higher throughput
  • 61. A S Y N C H R O N O U S L O G G E R S ✴ How work is passed between threads? ✴ LMAX Disruptor technology @alberto_deavila @albertoBaron1 “A lock-free inter-thread communication library, instead of queues, resulting in higher throughput and lower latency.” https://logging.apache.org/log4j/2.x/manual/async.html#UnderTheHood
  • 62. A S Y N C H R O N O U S L O G G E R S @alberto_deavila @albertoBaron1 https://logging.apache.org/log4j/2.x/manual/async.html
  • 63. A S Y N C H R O N O U S L O G G E R S @alberto_deavila @albertoBaron1
  • 64. C O D E I M P R O V E M E N T S Data processing @alberto_deavila @albertoBaron1
  • 65. D ATA P R O C E S S I N G ✴ Grails promises ✴ Use the cache plugin ✴ Avoid repetitive querying ✴ Async processing ✴ GPars @alberto_deavila @albertoBaron1
  • 66. D ATA P R O C E S S I N G Cache plugin @alberto_deavila @albertoBaron1
  • 67. C A C H E P L U G I N ✴ Plugin for Grails 2 & 3 (under development) ✴ Cache methods responses and tags ✴ Easy to use and configure ✴ Possibility to create any differents caches ✴ Cached items have no timeout @alberto_deavila @albertoBaron1
  • 68. ✴ To store values in the cache: ✴ To get the cached values: C A C H E P L U G I N @alberto_deavila @albertoBaron1 @Cacheable(value = 'message', key = { title.toUpperCase() } ) Message getMessage(String title) { log.debug 'Fetching message' Message.findByTitle(title) } } @CachePut(value='message', key = { message.title.toUpperCase() }) void save(Message message) { log.debug "Saving message $message" message.save() }
  • 69. ✴ To delete values from cache: ✴ Trick: you can combine annotations C A C H E P L U G I N @alberto_deavila @albertoBaron1 @CacheEvict(value = 'message', key = { message.title }) void delete(Message message) { log.debug "Deleting message $message" message.delete() }
  • 70. C A C H E P L U G I N @alberto_deavila @albertoBaron1
  • 71. D ATA P R O C E S S I N G Avoid repetitive querying @alberto_deavila @albertoBaron1
  • 72. AV O I D R E P E T I T I V E Q U E RY I N G ✴ We have the following code: @alberto_deavila @albertoBaron1 def myMethod(){ List<String> names = ['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie'] //up to 100 Simpsons names names.each{ String name -> Character character = Character.findByName(name) // some actions character.save() } }
  • 73. AV O I D R E P E T I T I V E Q U E RY I N G ✴ We can refactor it to: @alberto_deavila @albertoBaron1 def myRefactoredMethod(){ List<String> names = ['Homer', 'Marge', 'Bart', 'Lisa', 'Maggie'] //up to 100 Simpsons names List<Character> characters = Character.findByNameInList(names) characters.each{ Character character -> // some actions } characters*.save() }
  • 74. AV O I D R E P E T I T I V E Q U E RY I N G ✴ We have the following code: @alberto_deavila @albertoBaron1 def myServiceMethod(){ List<Long> ids = [1, 2, 3, 4, 5] //up to 100 ids ids.each{ Long id -> Character character = Character.get(id) // some actions character.save() } }
  • 75. AV O I D R E P E T I T I V E Q U E RY I N G ✴ We can refactor it to: @alberto_deavila @albertoBaron1 def myRefactoredAction2(){ List<Long> ids = [1, 2, 3, 4, 5] //up to 100 ids List<Character> characters = Character.getAll(ids) characters.each{ Character character -> // some actions } characters*.save() }
  • 76. AV O I D R E P E T I T I V E Q U E RY I N G @alberto_deavila @albertoBaron1
  • 77. D ATA P R O C E S S I N G Async data processing @alberto_deavila @albertoBaron1
  • 78. A S Y N C D ATA P R O C E S S I N G ✴ 100 factorial with threads & shared memory: @alberto_deavila @albertoBaron1 Long result = 1g List threads = [] (1..100).each { number -> threads << Thread.start { synchronized(this) { result = result * number } } } threads*.join() log.debug result
  • 79. A S Y N C D ATA P R O C E S S I N G ✴ Process a request asynchronously @alberto_deavila @albertoBaron1 def myAction(){ Thread.start { // do slow work in background // Send an email or some kind of notification } render "We are working on it!" }
  • 80. A S Y N C D ATA P R O C E S S I N G @alberto_deavila @albertoBaron1
  • 81. D ATA P R O C E S S I N G GPars @alberto_deavila @albertoBaron1
  • 82. G PA R S ✴ GPars is a framework to do concurrent tasks ✴ Works with Java and Groovy ✴ Make concurrent programming easy ✴ Provide us multiple solutions for parallelism @alberto_deavila @albertoBaron1
  • 83. G PA R S ✴ An example with parallel collections: @alberto_deavila @albertoBaron1 //summarize numbers concurrently GParsPool.withPool { final AtomicInteger amount = new AtomicInteger(0) [1, 2, 3, 4, 5].eachParallel {amount.addAndGet(it)} assert 15 == result }
  • 84. G PA R S ✴ An example with async call: @alberto_deavila @albertoBaron1 GParsPool.withPool() { assert 6 == {it * 2}.callAsync(3).get() }
  • 85. G PA R S ✴ But there are more GPars features: ✴ Actors ✴ Agents ✴ Dataflow ✴ Fork-join @alberto_deavila @albertoBaron1
  • 86. G PA R S @alberto_deavila @albertoBaron1
  • 87. C O D E I M P R O V E M E N T S Views @alberto_deavila @albertoBaron1
  • 88. V I E W S ✴ Compress resources: ✴ Group resources in Manifest @alberto_deavila @albertoBaron1 assets { minifyJs=true minifyCss=true excludes=[“**/*.html”] } /* * =require file1.css * =require file2.css */ <asset:javascript src=“manifest.js” /> assets/javascript/manifest.js
  • 89. V I E W S ✴ Avoid ask for resources external ✴ Download JS or CSS files in local @alberto_deavila @albertoBaron1
  • 90. V I E W S Content Delivery Network @alberto_deavila @albertoBaron1
  • 91. V I E W S ✴ Use CDN for static files ✴Network of servers spread over the world ✴Shows statically the content of websites ✴Static content cached and stored on servers ✴Delivery determined by location of visitors ✴Static files include html, css, JS or images @alberto_deavila @albertoBaron1
  • 92. V I E W S @alberto_deavila @albertoBaron1
  • 93. V I E W S ✴ Set up CDN in a Grails App ✴Install two plugins in BuildConfig ✴SetUp a CloudFront ✴Put CDN details in Config ✴Push local assets to cloud: assets-cdn-push @alberto_deavila @albertoBaron1 compile “:cdn-asset-pipeline:0.4.1” compile “:karman:0.6.1”
  • 94. C O D E I M P R O V E M E N T S Regex @alberto_deavila @albertoBaron1
  • 95. R E G E X @alberto_deavila @albertoBaron1
  • 96. R E G E X ✴ Main Tools ✴ JRegExAnalyser ✴ RegexBuddy ✴ Debuggex ✴ Rubular ✴ RegexPal @alberto_deavila @albertoBaron1
  • 97. R E G E X ✴ RegExp against bad backtracking: http://www.regular-expressions.info/catastrophic.html @alberto_deavila @albertoBaron1 “When nesting repetition operators, make sure that there is only one way to match the same match”
  • 98. C O D E I M P R O V E M E N T S Testing @alberto_deavila @albertoBaron1
  • 99. T E S T I N G def testingPerformance() { redirect action: 'assistAnotherPresentation', controller: 'greach', params: [ speak: 'GRAILS 3 TESTING OPTIMIZATION', speaker: 'Evelina & Tomás', day: '17th March', time: '8:30 AM' ] } @alberto_deavila @albertoBaron1
  • 100. T O O L S Tools
  • 101. T O O L S ✴ Many tools to measure performance ✴ JavaMelody ✴ App dynamics ✴ New relic ✴ Dynatrace @alberto_deavila @albertoBaron1
  • 102. J AVA M E L O D Y @alberto_deavila @albertoBaron1 def javaMelodyTool() { redirect action: 'assistAnotherPresentation', controller: 'greach', params: [ speak: 'JavaMelody to measure Grails app performance', speaker: 'Miguel Angel García', day: '17th March', time: '11:45 AM' ] }
  • 103. T O O L S @alberto_deavila @albertoBaron1
  • 104. T O O L S ✴ Real time application ✴ Application performance monitoring ✴ Available to multiple technologies ✴ Database monitoring ✴ Server topology auto discovered @alberto_deavila @albertoBaron1
  • 105. T O O L S @alberto_deavila @albertoBaron1
  • 106. T O O L S @alberto_deavila @albertoBaron1
  • 107. T O O L S @alberto_deavila @albertoBaron1
  • 108. T O O L S @alberto_deavila @albertoBaron1
  • 109. T O O L S @alberto_deavila @albertoBaron1
  • 110. T O O L S @alberto_deavila @albertoBaron1
  • 111. C O N C L U S I O N S Conclusions
  • 112. C O N C L U S I O N S ✴ Performance doesn't only depend on Grails ✴ Improve Grails performance in many ways ✴ Performance is a culture ✴ Performance has costs, but less than fix it later ✴ Easy to improve performance little by little ✴ Use tools to help you measure indicators @alberto_deavila @albertoBaron1
  • 113. Q U E S T I O N S Questions