on 2018 Oct 05 4:36 PM
Is there any performance impact of calling modelservice.save multiple times inside a loop
Request clarification before answering.
Basically yes, that's not the more optimized way, so yes it has impact. Now this impact may be ignored depending on your needs in term of performance.
I would say, as any performance questions, that you have to try it to know if it's perfomant enough for you.
You shouldn't worry about that kind of optimization, as you can see with Andrew's tests we are speaking of micro-optimisation.
If you need really low response time, then using Transaction to limit the connections to DB will be the answer.
You can check the hybris ref : https://help.hybris.com/1808/hcd/8c7387f186691014922080f2e053216a.html
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
My understanding is that each time you call save (and the model has been modified) there is a database update, unless you've got enableDelayedStore set to true for the transaction. So depending on how much you are updating you might want to save outside of the loop or set the transaction to not store in the database until the end. If your loop is very large then you're going to have other issues with memory so you'd want to consider batching your saves and commits.
Some really rudimentary Groovy to test this theory (bear in mind I've only averaged this over 5 runs)
Saving in the loop
start = System.currentTimeMillis()
(1..500).each {
ex = modelService.create('Product')
ex.code = "test${it}"
ex.catalogVersion = catalogVersionService.getCatalogVersion('Default', 'Staged')
try {
p = flexibleSearchService.getModelByExample ex
} catch (e) {
p = ex
}
p.name += '!'
modelService.save(p)
}
println "took ${System.currentTimeMillis() - start}ms"
times
609
619
575
650
557
===
avg = 602 ms
Saving outside the loop
start = System.currentTimeMillis()
items = []
(1..500).each {
ex = modelService.create('Product')
ex.code = "test${it}"
ex.catalogVersion = catalogVersionService.getCatalogVersion('Default', 'Staged')
try {
p = flexibleSearchService.getModelByExample ex
} catch (de.hybris.platform.servicelayer.exceptions.ModelNotFoundException e) {
p = ex
}
p.name += '!'
items << p
}
modelService.saveAll(items)
println "took ${System.currentTimeMillis() - start}ms"
times
480
502
482
465
464
===
avg = 479 ms
Delaying store
start = System.currentTimeMillis()
de.hybris.platform.tx.Transaction.current().enableDelayedStore(true)
(1..500).each {
ex = modelService.create('Product')
ex.code = "test${it}"
ex.catalogVersion = catalogVersionService.getCatalogVersion('Default', 'Staged')
try {
p = flexibleSearchService.getModelByExample ex
} catch (e) {
p = ex
}
p.name += '!'
modelService.save(p)
}
println "took ${System.currentTimeMillis() - start}ms"
times
519
530
531
522
494
===
avg = 519 ms
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yeah, I was a bit surprised that there was a difference. The next step would be to enable the jdbc log whilst this was running and see what queries are being issued. I'm also not totally sure about the validity of this test when run from the hac because presumably it is only committing the transaction after the script has finished, which is actually after our timing finishes.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.