out of curiosity, would anyone happen to know if c...
# cfml-general
r
out of curiosity, would anyone happen to know if cfml run-time is any faster between cfscript vs tagged based code, even by the smallest margins? Is there any extra processing between one or the other?
b
@ryan I would expect the bytecode generated to be nearly identical
šŸ‘šŸ¼ 1
I've certainly never seen a difference between the two
šŸ‘šŸ¼ 1
a
cfscript is much much faster † † this is based entirely on the fact cfscript is much nicer to work with and not based on any actual performance metrics
āœ… 3
b
lol, yes it's certainly faster to code in and read and debug for me šŸ™‚
It's easily 25% less code I have to type
āœ… 3
šŸ’Æ 1
r
me neither, but I have always wondered if either code base takes less processing vs the other in any way, even if it is miniscule.
I do prefer script wherever possible to code over tag 100%, but just a curiosity I wanted to throw out to see if there was any sort of answer.
a
even if it is miniscule
Why though? If one was dealing with a performance issue (which is when one ought to start thinking about this sort of thing... and not before then), one would want to find things that have a decent amount of gain. Not immeasurable ones. I cannot give you any tangible metrics, but as Brad alludes to... it's not the CFML code - tags or script - that is executed, so it's not really a consideration. One or the other might have a slightly higher compilation time, but that is negligible to the point of not being apparent, and is a one-time (-ish) cost anyhow, really. The code that the CFML dev writes is gonna be where optimisation opportunities will lie. Not in this sort of stuff. At the same time, one can have real tangible gains for the humans every day if one maintains well-written, clean, easy to reason code. And I'd say that is more readily achieved with less effort in script-based code than tag-based code. Use tags in yer views (and a very limited subset of tags at that). Use script everywhere else. When a performance issue comes along, start by looking at what the code is doing. Not which syntax variant it's written in.
r
Good thoughts, Adam. Like I mentioned, this is just a curiosity. I'm not having issues of any kind and I would not be switching to tag based coding even if it were slightly faster for the mere reasons you explained. There is more benefit on the side of coding in script than coding in tag, imo, but attempting to avoid that dead-horse debate for this question.
āœ… 1
m
The run-time is 100% identical. They compile to the same bytecode. There is no speed difference between the two that I am aware of (and if there is please let me know as it is likely a bug). I code in both, depending on my mood and what I'm trying to output. Sometimes I'll write something in tags first as I'M slightly faster on some stuff there, and then I'll refactor over to script (optimizing as I go as well). Or just have ChatGPT do it lmao.
šŸ˜‚ 3
r
Good to know, thanks Mark! ChatGPT is helpful. I did try to convert some tags to script recently as well but it didn't do it quite right, but it is still completely useful in getting it close enough and then I adjust the remaining things that are erroring because of bad or misinterpreted translating on GPT's part.
m
If it screws up, tell it and it will fix the issue šŸ™‚
I had it write my code for my talk in DC on AI integration
because I'm HELLA META
lol
r
i do tell it šŸ™‚
m
oh! I guess it likes me better lol šŸ˜‰
3.5 or 4?
r
4
m
huh. weird.
your code is probably more complex than mine
b
If you want help converting CF tags to script, don't forget about @foundeo’s https://cfscript.me/ site.
šŸ‘šŸ¼ 1
āž• 3
šŸ‘ 1
m
What's the fun in that Brad?
šŸ˜‚ 1
b
IKR
m
I want to have our new robot overlords do my dirty work hehe
b
Who, I for one, welcome
🤣 1
b
That is the best thing I'm going to see and learn about today
<http://cfscript.me|cfscript.me>
. I should call it a day.
šŸ˜Ž 1
r
Not related to converting tag to script, I have gone in circles in some cases with GPT where I will tell it the coding mistakes, and then it fixes it, but introduces another mistake. So, I would continue to repeat these fixing steps in an effort to complete all of the mistakes, but it would still reintroduce a previous mistake. Lol That is the point I would just take the code and fix it, but it's fun to see it's limitations and still a reason for me to exist as a developer LOL
z
cfscript was faster with cf 4.5 or something
a
That was when cfscript was first added I think and it was very limited. CF MX 6 was when it switched over to running on Java.
f
yes, and we usually made those performance rules by running code like this: https://trycf.com/gist/539dc745f143adfcd59e6cf6d01a58d0/acf2021?theme=monokai
🤯 1
a
blimey, that's interesting.
I think for a like-for-like, the tag-based version ought to be :
Copy code
<cfset i=1>
<cfloop condition="i le 100000">
    <cfset i++>
But no difference making that change.
šŸ‘ 1
b
@foundeo If you change the script loop to actually be a to/from loop the tag version is about the same
Also, cfslient around the tags should help
You can see the for loop is actually faster then the to/from loop in Adobe so it's not fair to compare them
a
Brad if you write
cfloop
in CFScript I'm gonna have to break your arms. Off.
šŸ˜‚ 1
b
lol
f
try it on lucee closer to the same times, and sometimes tag is faster than script
šŸ‘ 1
b
In Lucee, there's nearly no difference across them
āœ… 1
šŸ‘ 1
f
I was going to take out one of the zeros in the cfscript loop to see if anyone noticed
šŸ˜† 3
z
brb decompiling bytcode
b
Occasionally, I do like the semantics of the to/from or times loop in script. But if I'm coding for Lucee I would use
Copy code
loop from=1 to=5 {}
and not
Copy code
cfloop( from=1, to=5 ) {}
f
I’m going to post my findings to cf-talk
šŸ‘šŸ¼ 1
šŸ‘ 1
z
locally lucee is always faster in script, you don't know who's hitting try cf at the same time
šŸ‘šŸ¼ 1
Copy code
public final Object call(PageContext paramPageContext) throws Throwable {
    <http://paramPageContext.us|paramPageContext.us>().set(this.keys[0], Caster.toRef(GetTickCount.call(paramPageContext)));
    paramPageContext
      .write("\r\n");
    double d1 = 1.0D, d2 = 100000.0D, d3 = 1.0D;
    boolean bool = (d3 > 0.0D) ? true : false;
    if ((d3 != 0.0D)) {
      VariableReference variableReference = VariableInterpreter.getVariableReference(paramPageContext, "i");
      variableReference.set(d1);
      double d = d1;
      while (true) {
        if (bool ? ((d <= d2)) : ((d >= d2))) {
          paramPageContext
            .write("\r\n    ");
          <http://paramPageContext.us|paramPageContext.us>().set(KeyConstants._X, Operator.plusRef(<http://paramPageContext.us|paramPageContext.us>().get(KeyConstants._I), ConstantsDouble._1));
          paramPageContext
            .write("\r\n");
          variableReference.set(d += d3);
          continue;
        } 
        break;
      } 
    } 
    paramPageContext
      .write("\r\n");
    paramPageContext.outputStart();
    try {
      paramPageContext.write(Caster.toString(Caster.toDoubleValue(Operator.minusRef(Caster.toRef(GetTickCount.call(paramPageContext)), <http://paramPageContext.us|paramPageContext.us>().get(this.keys[0])))));
      paramPageContext.write("ms");
    } finally {
      paramPageContext.outputEnd();
    } 
    paramPageContext
      .write("\r\n<hr>\r\n");
    if (true) {
      <http://paramPageContext.us|paramPageContext.us>().set(this.keys[0], Caster.toRef(GetTickCount.call(paramPageContext)));
      <http://paramPageContext.us|paramPageContext.us>().set(KeyConstants._I, ConstantsDouble._1);
      for (; !(Operator.compare(<http://paramPageContext.us|paramPageContext.us>().get(KeyConstants._I), 100000.0D) > 0); Operator.unaryPoPl(paramPageContext, KeyConstants._I, 1.0D))
        <http://paramPageContext.us|paramPageContext.us>().set(KeyConstants._X, Operator.plusRef(<http://paramPageContext.us|paramPageContext.us>().get(KeyConstants._I), ConstantsDouble._1)); 
      WriteOutput.call(paramPageContext, Caster.toString(Caster.toDoubleValue(Operator.minusRef(Caster.toRef(GetTickCount.call(paramPageContext)), <http://paramPageContext.us|paramPageContext.us>().get(this.keys[0])))));
    } 
    return null;
  }
f
so the whitespace is really probably accounting for any of the extra time tags take
z
it's faster with tabs then :)))))))
f
which in this case is exaggerated due to looping 100,000 times
b
Lucee does a better job of optimizing whitespace. In Adobe, even when outpout=false, the whitespace is still collected and then discarded at the end. As of Lucee 5.3, when
bufferOutput
is set to false, the whitespace isn't even collected in the first place
šŸ‘ 1
a
Bloody hell... imagine how much faster @ben could make his code if he removed even 50% of his whitespace. Like just down to 5-lines per CFML statement or something.
🤣 5
Also now hoping for a cfCbMinifyBox lib to appear on ForgeBox.
z
that was an 800kb file
view source hangs my chrome lol
p
interesting, with 10000000 interactions CF2021 is slower than CF2018 on CFTRY, instead on CFFIDDLE it is the same https://trycf.com/gist/8bdad9f1f6db1011630e02eae16d6eed/acf2021?theme=monokai
a
Note for anyone reading this lot and going "šŸ¤”" and wondering if they should change how they do things. No. As soon as one needs to do <drEvil>ONE MILLION</drEvil> iterations to amplify the difference so it stands out over the background noise, it demonstrates it doesn't matter. Just write good clear code. There will "never" be a situation where changing code syntax like this is where perf improvements will be made in your projects. It's interesting to know. It's not something to act on though. Code is for the humans, not for the machines. Remember that.
z
hmm, for loops are much slower in lucee https://luceeserver.atlassian.net/browse/LDEV-4473
a
The loops aren't the same. It's comparing apples to oranges. Re-test with the tag-based one as:
Copy code
<cfset i=1>
<cfloop condition="i LE iteration">
    <!---...--->
    <cfset i++>
</cfloop>
Might not make a diff, but at least use comparable code.
šŸ‘ 1
But, yeah, the exception to what I said above is that the language dev teams should pay attn to this stuff šŸ˜‰ Esp if the results raise an eyebrow... and "hang on, that shouldn't happen..?!"
Equally, no-one would write tag-based code like that, I realise this. However there will be performance considerations around these constructs where one does slightly more/different work than another.
(but inconsequential ones)
z
no one- famous last words šŸ˜‰
😜 1
a
Hey just let me live in my fantasy world where ppl can write three lines of CFML code without me going "you did what, FFS??"
z
perl programmers like, hold my beer, i'll do it in one line
šŸ˜‚ 1
a
Copy code
arrayNew(1).set(1,1000000, "").each(()=>{return})
#mePicksUpBeer (oh and for shits and giggles time that one. EEEEEEEEEK)
(would be really nice if CFML had a Range type. or even a range function refs: https://kotlinlang.org/docs/ranges.html / https://www.php.net/manual/en/function.range.php)
z
in lucee, cfloop is highly optimized
Copy code
double d = d4;
        while (true) {
          if (bool1 ? ((d <= d5)) : ((d >= d5))) {
            <http://paramPageContext.us|paramPageContext.us>().set(KeyConstants._X, Operator.plusRef(<http://paramPageContext.us|paramPageContext.us>().get(KeyConstants._I), ConstantsDouble._1));
            variableReference.set(d += d6);
            continue;
          } 
          break;
        }
while for loop is doing more gymnastics
Copy code
for (; !(Operator.compare(<http://paramPageContext.us|paramPageContext.us>().get(KeyConstants._I), <http://paramPageContext.us|paramPageContext.us>().get(this.keys[0])) > 0); Operator.unaryPoPl(paramPageContext, KeyConstants._I, 1.0D))
        <http://paramPageContext.us|paramPageContext.us>().set(KeyConstants._X, Operator.plusRef(<http://paramPageContext.us|paramPageContext.us>().get(KeyConstants._I), ConstantsDouble._1));
a
Yeah needs to be because the second and third parameter of a
for
can be any expression that evaluates to a boolean (second one), or anything at all (third one). It's a far more flexible construct.
In fact the first param can be anything as well, I guess
Copy code
i=1    
for (;true;){
    writeOutput(i)
    if (++i > 10) break;
}
Works fine.