I have an in-memory data accesor function, in a giant report, which gets
called 20k times, and I’d like it to be faster. It is simple struct key
access. I hadn’t realised accessing in-memory data via a struct took this
much time. Anyone have a suggestion how I could implement this code
directly in Java to decrease the access time for this specific case?
( And yes, I realise the glaring solution is to reduce the 20k calls, which
were looking into… but may not be possible. )
(As a caveat, given a low percentage of misses, a try/catch block is 2x
faster than structKeyExists at 0.113ms per call, but around 0.300ms if each
call is a catch.)
This method call takes an average of 0.208ms * ( x 20k = 4160ms ) *running
in Lucee 5.0.x
Where: “this.data” is a struct with 183 elements. each element has 5 keys,
each containing an single integer
public any function getAnswerById(numeric id){
if (structKeyExists(this.data,id)){
return this.data[id].answer;
}
else {
return 0;
}
}
If there aren’t to many calls of the function getAnswerById() try replacing them with the following:
Say your call was:
Id = getAnswerById(yourId);
Replace it with:
Id = this.data[id] ?: 0;
In your case i presume the function calls are killing the performance.
GertSent from somewhere on the road
Am 17.08.2016 um 20:47 schrieb Jonathan Smith <@Jonathan_Smith>:
Hi,
I have an in-memory data accesor function, in a giant report, which gets called 20k times, and I’d like it to be faster. It is simple struct key access. I hadn’t realised accessing in-memory data via a struct took this much time. Anyone have a suggestion how I could implement this code directly in Java to decrease the access time for this specific case?
( And yes, I realise the glaring solution is to reduce the 20k calls, which were looking into… but may not be possible. )
(As a caveat, given a low percentage of misses, a try/catch block is 2x faster than structKeyExists at 0.113ms per call, but around 0.300ms if each call is a catch.)
This method call takes an average of 0.208ms ( x 20k = 4160ms ) running in Lucee 5.0.x
Where: “this.data” is a struct with 183 elements. each element has 5 keys, each containing an single integer
public any function getAnswerById(numeric id){
if (structKeyExists(this.data,id)){
return this.data[id].answer;
}
else {
return 0;
}
}
–
Get 10% off of the regular price for this years CFCamp in Munich, Germany (Oct. 20th & 21st) with the Lucee discount code Lucee@cfcamp. 189€ instead of 210€. Visit CFCamp 2016
I’ll try both options. For starters, I just changed the code to measure the
function call overhead of 20k calls:
public any function getAnswerById(numeric id){
return 1;
}
Any my debug output shows 20ms for 20970 calls, or 0.00095 ms per call ),
which leads me to believe the function call overhead is almost nothing
compared to the structKeyExists and fetch statements?On Wednesday, 17 August 2016 15:13:14 UTC-4, Gert Franz wrote:
Actually there is a small typo…
I the line is slightly wrong. It should be:
Id = this.data[id].answer ?: 0;
Gert
Sent from somewhere on the road
Am 17.08.2016 um 20:47 schrieb Jonathan Smith <jonatha...@gmail.com
<javascript:>>:
Hi,
I have an in-memory data accesor function, in a giant report, which gets
called 20k times, and I’d like it to be faster. It is simple struct key
access. I hadn’t realised accessing in-memory data via a struct took this
much time. Anyone have a suggestion how I could implement this code
directly in Java to decrease the access time for this specific case?
( And yes, I realise the glaring solution is to reduce the 20k calls,
which were looking into… but may not be possible. )
(As a caveat, given a low percentage of misses, a try/catch block is 2x
faster than structKeyExists at 0.113ms per call, but around 0.300ms if each
call is a catch.)
This method call takes an average of 0.208ms * ( x 20k = 4160ms ) *running
in Lucee 5.0.x
Where: “this.data” is a struct with 183 elements. each element has 5 keys,
each containing an single integer
public any function getAnswerById(numeric id){
if (structKeyExists(this.data,id)){
return this.data[id].answer;
}
else {
return 0;
}
}
–
Get 10% off of the regular price for this years CFCamp in Munich, Germany
(Oct. 20th & 21st) with the Lucee discount code Lucee@cfcamp. 189€ instead
of 210€. Visit CFCamp 2016
Sent by typing with my thumbs.> On 17 Aug 2016, at 21:27, Jonathan Smith <@Jonathan_Smith> wrote:
Hi Mark,
Thanks for the reply! I tried cacheGet/cachePut using Lucee’s ramCache and the function call dropped to 0.109 ms from 0.208ms, so 2x improvement… but still seems like a long time for an in-memory operation… ? ( I appreciate that the timing is subject to my workstation, but… I was hoping it would be negligible time to read a tiny data set from memory )
On Wednesday, 17 August 2016 15:11:50 UTC-4, Mark Drew wrote:
Have you tried using a cacheget() instead of structs?
I have an in-memory data accesor function, in a giant report, which gets called 20k times, and I’d like it to be faster. It is simple struct key access. I hadn’t realised accessing in-memory data via a struct took this much time. Anyone have a suggestion how I could implement this code directly in Java to decrease the access time for this specific case?
( And yes, I realise the glaring solution is to reduce the 20k calls, which were looking into… but may not be possible. )
(As a caveat, given a low percentage of misses, a try/catch block is 2x faster than structKeyExists at 0.113ms per call, but around 0.300ms if each call is a catch.)
This method call takes an average of 0.208ms ( x 20k = 4160ms ) running in Lucee 5.0.x
Where: “this.data” is a struct with 183 elements. each element has 5 keys, each containing an single integer
public any function getAnswerById(numeric id){
if (structKeyExists(this.data,id)){
return this.data[id].answer;
}
else {
return 0;
}
}
–
Get 10% off of the regular price for this years CFCamp in Munich, Germany (Oct. 20th & 21st) with the Lucee discount code Lucee@cfcamp. 189€ instead of 210€. Visit CFCamp 2016
–
Get 10% off of the regular price for this years CFCamp in Munich, Germany (Oct. 20th & 21st) with the Lucee discount code Lucee@cfcamp. 189€ instead of 210€. Visit CFCamp 2016
Thanks for the reply! I tried cacheGet/cachePut using Lucee’s ramCache and
the function call dropped to 0.109 ms from 0.208ms, so 2x improvement…
but still seems like a long time for an in-memory operation… ? ( I
appreciate that the timing is subject to my workstation, but… I was
hoping it would be negligible time to read a tiny data set from memory )On Wednesday, 17 August 2016 15:11:50 UTC-4, Mark Drew wrote:
Have you tried using a cacheget() instead of structs?
Mark Drew
Sent by typing with my thumbs.
On 17 Aug 2016, at 19:47, Jonathan Smith <jonatha...@gmail.com <javascript:>> wrote:
Hi,
I have an in-memory data accesor function, in a giant report, which gets
called 20k times, and I’d like it to be faster. It is simple struct key
access. I hadn’t realised accessing in-memory data via a struct took this
much time. Anyone have a suggestion how I could implement this code
directly in Java to decrease the access time for this specific case?
( And yes, I realise the glaring solution is to reduce the 20k calls,
which were looking into… but may not be possible. )
(As a caveat, given a low percentage of misses, a try/catch block is 2x
faster than structKeyExists at 0.113ms per call, but around 0.300ms if each
call is a catch.)
This method call takes an average of 0.208ms * ( x 20k = 4160ms ) *running
in Lucee 5.0.x
Where: “this.data” is a struct with 183 elements. each element has 5 keys,
each containing an single integer
public any function getAnswerById(numeric id){
if (structKeyExists(this.data,id)){
return this.data[id].answer;
}
else {
return 0;
}
}
–
Get 10% off of the regular price for this years CFCamp in Munich, Germany
(Oct. 20th & 21st) with the Lucee discount code Lucee@cfcamp. 189€ instead
of 210€. Visit CFCamp 2016
id = structKeyExists(this.data, key) ? this.data[key] : 0;
Is that if the key exists – we do a hash lookup twice, which simply
means that the operation, albeit fast, takes twice as long as it should.
I recommend trying this construct instead:
id = structFind(this.data, key, 0); // see
Which will return 0 if the key does not exist, but will return the key
with a single lookup if it does exist.
As an aside, structFind() is a horrible name for that function. It
should have been structGet(), but some genius decided that structGet()
should return something completely different.
Id = structKeyExists(this.data, id) ? this.data[id].answer : 0;
I’ll check myself for a different solution…
Gert
Sent from somewhere on the road
Am 17.08.2016 um 22:38 schrieb Jonathan Smith
<@Jonathan_Smith mailto:Jonathan_Smith>:
Hi Gert,
When I use the inline elvis operator ?: I still get an error when I
ask for a non-existent struct key, instead of a Zero.
ie.
integer-key-that-does-not-exist = 999;
this.data[integer-key-that-does-not-exist].answer ?: 0; // Throws:
The key [999] does not exist , but there is a similar key with name
[300] available.
On Wednesday, 17 August 2016 15:13:14 UTC-4, Gert Franz wrote:
Actually there is a small typo...
I the line is slightly wrong. It should be:
Id = this.data[id].answer ?: 0;
Gert
Sent from somewhere on the road
Am 17.08.2016 um 20:47 schrieb Jonathan Smith
<jonatha...@gmail.com <javascript:>>:
Hi,
I have an in-memory data accesor function, in a giant report,
which gets called 20k times, and I'd like it to be faster. It is
simple struct key access. I hadn't realised accessing in-memory
data via a struct took this much time. Anyone have a suggestion
how I could implement this code directly in Java to decrease the
access time for this specific case?
( And yes, I realise the glaring solution is to reduce the 20k
calls, which were looking into.. but may not be possible. )
(As a caveat, given a low percentage of misses, a try/catch
block is 2x faster than structKeyExists at 0.113ms per call, but
around 0.300ms if each call is a catch.)
This method call takes an average of 0.208ms * ( x 20k = 4160ms
) *running in Lucee 5.0.x
Where: "this.data" is a struct with 183 elements. each element
has 5 keys, each containing an single integer
*
*
public any function getAnswerById(numeric id){
if (structKeyExists(this.data,id)){
return this.data[id].answer;
}
else {
return 0;
}
}
--
Get 10% off of the regular price for this years CFCamp in
Munich, Germany (Oct. 20th & 21st) with the Lucee discount code
Lucee@cfcamp. 189€ instead of 210€. Visit
https://ti.to/cfcamp/cfcamp-2016/discount/Lucee@cfcamp
<https://ti.to/cfcamp/cfcamp-2016/discount/Lucee@cfcamp>
---
You received this message because you are subscribed to the
Google Groups "Lucee" group.
To unsubscribe from this group and stop receiving emails from
it, send an email to lucee+un...@googlegroups.com <javascript:>.
To post to this group, send email to lu...@googlegroups.com
<javascript:>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/lucee/b99e5590-63bf-41ef-986c-e86e74c93368%40googlegroups.com
<https://groups.google.com/d/msgid/lucee/b99e5590-63bf-41ef-986c-e86e74c93368%40googlegroups.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout
<https://groups.google.com/d/optout>.
–
Get 10% off of the regular price for this years CFCamp in Munich,
Germany (Oct. 20th & 21st) with the Lucee discount code Lucee@cfcamp.
189€ instead of 210€. Visit CFCamp 2016
population: creates a struct with 20000 elements
index: creates an array with 30000 items which are numbered 1-30000 randomly (so we get cache misses)
And you can see I loop over the index array (to go get items from the struct)
Regards
Mark Drew> On 18 Aug 2016, at 06:21, Igal @ Lucee.org <@Igal> wrote:
My biggest issue with this construct:
id = structKeyExists(this.data, key) ? this.data[key] : 0;
Is that if the key exists – we do a hash lookup twice, which simply means that the operation, albeit fast, takes twice as long as it should.
I recommend trying this construct instead:
id = structFind(this.data, key, 0); // see http://docs.lucee.org/reference/functions/structfind.html <http://docs.lucee.org/reference/functions/structfind.html>
Which will return 0 if the key does not exist, but will return the key with a single lookup if it does exist.
As an aside, structFind() is a horrible name for that function. It should have been structGet(), but some genius decided that structGet() should return something completely different.
Id = structKeyExists(this.data, id) ? this.data[id].answer : 0;
I’ll check myself for a different solution…
Gert
Sent from somewhere on the road
Am 17.08.2016 um 22:38 schrieb Jonathan Smith <@Jonathan_Smith mailto:Jonathan_Smith>:
Hi Gert,
When I use the inline elvis operator ?: I still get an error when I ask for a non-existent struct key, instead of a Zero.
ie.
integer-key-that-does-not-exist = 999;
this.data[integer-key-that-does-not-exist].answer ?: 0; // Throws: The key [999] does not exist , but there is a similar key with name [300] available.
On Wednesday, 17 August 2016 15:13:14 UTC-4, Gert Franz wrote:
Actually there is a small typo…
I the line is slightly wrong. It should be:
Id = this.data[id].answer ?: 0;
Gert
Sent from somewhere on the road
Am 17.08.2016 um 20:47 schrieb Jonathan Smith <jonatha...@gmail.com <javascript:>>:
Hi,
I have an in-memory data accesor function, in a giant report, which gets called 20k times, and I’d like it to be faster. It is simple struct key access. I hadn’t realised accessing in-memory data via a struct took this much time. Anyone have a suggestion how I could implement this code directly in Java to decrease the access time for this specific case?
( And yes, I realise the glaring solution is to reduce the 20k calls, which were looking into… but may not be possible. )
(As a caveat, given a low percentage of misses, a try/catch block is 2x faster than structKeyExists at 0.113ms per call, but around 0.300ms if each call is a catch.)
This method call takes an average of 0.208ms ( x 20k = 4160ms ) running in Lucee 5.0.x
Where: “this.data” is a struct with 183 elements. each element has 5 keys, each containing an single integer
public any function getAnswerById(numeric id){
if (structKeyExists(this.data,id)){
return this.data[id].answer;
}
else {
return 0;
}
}
Looks like I’ve figured out where the discrepancy is. I had Lucee’s
debugging template enabled. Turns out, by looking too closely at code
performance, I inadvertently made it slow. So embarrassing, but it really
points out how fast Lucee is in the end!
With Debug Template: ( Specifically, what caused the change was
having “Implicit variable Access” enabled. Only having Timers enabled does
not cause such a meaningful slow down, and it only applies to struct
reads. )
population: 38msindex: 27msgetWithStructFind: 2980msgetWithElvis:
2907msgetWithStructKeyExists: 4855msgetWithTryCatch: 11764msOn Thursday, 18 August 2016 08:53:04 UTC-4, Andrew Penhorwood wrote:
In my test using trycf.com I found about the same as Mark. Though ACF
2016 was generally faster than Lucee 5 on inline-ternary operations
Lucee 4.5
inline-ternary 65 ms
structKeyExists 87 ms ( function based )
Lucee 5
inline-ternary 96 ms
structKeyExists 130 ms ( function based )
ACF 2016
inline-ternary 53 ms
structKeyExists 174 ms ( function based )