https://en.wikipedia.org/wiki/If_a_tree_falls_in_a_forest
This app is slow.
Perception burn!
May or may not report the issue (probably not)
User X loaded the results page in 1870ms today at 4:30pm
475 records were pulled from the DB
if (user.cares()) {
if(user.canLocateSupport() && user.hasTime()) {
reportSlowness()
}
}
How your users feel is the reality that you are working with
- https://blog.marvelapp.com/a-designers-guide-to-perceived-performance/
- https://www.fastcompany.com/1825005/how-one-second-could-cost-amazon-16-billion-sales
http://plugins.grails.org/plugin/grails/asset-pipeline
Quantify results
Human memory is 'lossy'
Removal of opinion
What happened surrounding
grails-app/conf/logback.groovy
or...
grails-app/conf/logback.xml
(can also be configured externally)
https://en.wikipedia.org/wiki/Observer_effect_(physics)
One place to rule them all!
Metrics
Visual representation
Proxy/Load Balancer timing Logs are a great place to start
monitor traffic, analyze outliars
MDC.put("user", user.name)
Easy to search and filter
CorrelationID from the entry point
(also works if included in reactive flows)
Did the performance change over time?
Growing? at what rate?
class MyInterceptor {
int order = HIGHEST_PRECEDENCE
boolean before() { true }
boolean after() { true }
void afterView() {
// no-op
}
}
class MyInterceptor {
int order = HIGHEST_PRECEDENCE
boolean before() { true }
boolean after() { true }
void afterView() {
// no-op
}
}
* warning this can be chatty!
logger("org.hibernate.SQL", DEBUG, ["STDOUT"], false)
logger("org.hibernate.type.descriptor.sql.BasicBinder", TRACE, ["STDOUT"], false)
environments:
local:
dataSource:
logSql: true
formatSql: true
grails-app/conf/logback.groovy
Application configuration
grails-app/conf/application.yml
One expensive query
Usually a Complex query
1 * (Query Time + network overhead)
Many smaller less expensive queries
Overhead becomes important
n * (Query Time + network overhead)
- https://www.slideshare.net/JonasWitt1/understanding-database-transactions-and-hibernate-sessions-in-grails
- https://www.slideshare.net/JonasWitt1/understanding-database-transactions-and-hibernate-sessions-in-grails
(@See Burt's talk!)
class Author {
String name
static hasMany = [books: Book]
}
new Book(title:"The Stand")
.save()
.subscribe { Book it ->
println "Title = ${it.title}"
}
Book.get(id)
.subscribe { Book it ->
println "Title = ${it.title}"
}
import static grails.async.Promises.*
def p1 = task { 2 * 2 }
def p2 = task { 4 * 4 }
def p3 = task { 8 * 8 }
assert [4,16,64] == waitAll(p1, p2, p3)
import static java.util.concurrent.TimeUnit.*
import static grails.async.Promises.*
Promise p = task {
// Long running task
}
p.onError { Throwable err ->
println "An error occured ${err.message}"
}
p.onComplete { result ->
println "Promise returned $result"
}
// block until result is called
def result = p.get()
// block for the specified time
def result = p.get(1,MINUTES)
class BookService {
List<Book> findBooks(String title) {
// implementation
}
}
import grails.async.*
class AsyncBookService {
@DelegateAsync BookService bookService
}
Please visit our table for giveaways
and to meet the team!
ociweb.com/grails
info@ociweb.com