Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

Quite a few years ago (probably when Perl 5.6 was the current version) I read some documentation regarding this; unfortunately, I can't readily locate it now - I don't even remember if it was a manpage or a Perl book. Anyway, the gist of it was that join was a single operation whereas concatentation was a mult-stepped operation (i.e. $string = $x . $y . $z; was effectively $temp = $x . $y; $string = $temp . $z;) - the recommendation was to choose join over concatenation as a general rule-of-thumb.

So, other than for very simple cases (such as $string = $x . $y; and $string .= $x;), I've pretty much kept to that rule.

As we've moved through a number of Perl versions since then, and prompted by this thread, I decided to do some benchmarking. The results are mostly the reverse of the advice above. In general:

  • For relatively small numbers of strings that aren't exceptionally long (such as shown in qazwart's examples above), concatenation with the dot operator is typically faster.
  • For large numbers of strings, or when the strings are large, then join comes into its own.

On this basis, I'm changing my general rule-of-thumb to use concatenation over join.

Unless these operations are occurring in loops, recursive calls or similar situations where the net effect stacks noticeably, it probably doesn't matter that much which is used: spending hours trying to micro-optimise code to save a few nanoseconds just isn't worth it.

The code and results are below (click on Read more ...).

Just to head off the inevitable "Why did you ...?" question: the code contains an array (@counts) with one element which is used to iterate through the outer loop once. While testing, this contained a variety of values and I've left it that way in case others want to do the same.

Code:

#!perl use 5.12.0; use warnings; use Benchmark qw{:hireswallclock cmpthese}; my ($x, $y, $z); my $x_base = 'x'; my $y_base = 'y'; my $z_base = 'z'; my @counts = (-10); my @lengths = (1, 4, 8, 16, 32, 64, 128); for my $count (@counts) { say '*' x 60; say 'Count: ', $count; for my $length (@lengths) { $x = $x_base x $length; $y = $y_base x $length; $z = $z_base x $length; say '-' x 60; say 'length $x = ', length $x; say 'length $y = ', length $y; say 'length $z = ', length $z; say '-' x 60; cmpthese $count => { join_2 => \&join_code_2, cat_2 => \&concat_code_2, join_3 => \&join_code_3, cat_3 => \&concat_code_3, join_6 => \&join_code_6, cat_6 => \&concat_code_6, join_12 => \&join_code_12, cat_12 => \&concat_code_12, join_24 => \&join_code_24, cat_24 => \&concat_code_24, join_48 => \&join_code_48, cat_48 => \&concat_code_48, }; } } sub join_code_2 { join '', $x, $y; } sub concat_code_2 { $x . $y; } sub join_code_3 { join '', $x, $y, $z; } sub concat_code_3 { $x . $y . $z; } sub join_code_6 { join '', $x, $y, $z, $x, $y, $z; } sub concat_code_6 { $x . $y . $z . $x . $y . $z; } sub join_code_12 { join '', $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z; } sub concat_code_12 { $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z; } sub join_code_24 { join '', $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z; } sub concat_code_24 { $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z; } sub join_code_48 { join '', $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z, $x, $y, $z; } sub concat_code_48 { $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z . $x . $y . $z; }

Results:

$ bench_join_concat.pl ************************************************************ Count: -10 ------------------------------------------------------------ length $x = 1 length $y = 1 length $z = 1 ------------------------------------------------------------ Rate cat_48 join_48 cat_24 join_24 cat_12 join_12 join_6 + cat_6 join_3 join_2 cat_3 cat_2 cat_48 505547/s -- -15% -49% -56% -75% -77% -87% + -87% -92% -94% -95% -96% join_48 592907/s 17% -- -40% -49% -70% -73% -84% + -85% -91% -93% -94% -96% cat_24 991279/s 96% 67% -- -14% -50% -54% -74% + -74% -84% -88% -89% -93% join_24 1157579/s 129% 95% 17% -- -42% -47% -69% + -70% -82% -86% -88% -92% cat_12 1999519/s 296% 237% 102% 73% -- -8% -47% + -48% -68% -77% -79% -86% join_12 2166166/s 328% 265% 119% 87% 8% -- -43% + -44% -66% -75% -77% -85% join_6 3791349/s 650% 539% 282% 228% 90% 75% -- + -1% -40% -56% -60% -73% cat_6 3836950/s 659% 547% 287% 231% 92% 77% 1% + -- -39% -55% -59% -73% join_3 6298801/s 1146% 962% 535% 444% 215% 191% 66% + 64% -- -26% -33% -55% join_2 8550747/s 1591% 1342% 763% 639% 328% 295% 126% + 123% 36% -- -9% -39% cat_3 9398428/s 1759% 1485% 848% 712% 370% 334% 148% + 145% 49% 10% -- -33% cat_2 13995173/s 2668% 2260% 1312% 1109% 600% 546% 269% + 265% 122% 64% 49% -- ------------------------------------------------------------ length $x = 4 length $y = 4 length $z = 4 ------------------------------------------------------------ Rate cat_48 join_48 cat_24 join_24 join_12 cat_12 join_6 +cat_6 join_3 cat_3 join_2 cat_2 cat_48 299462/s -- -7% -52% -52% -74% -76% -85% + -88% -93% -94% -94% -96% join_48 321590/s 7% -- -48% -48% -73% -74% -84% + -87% -92% -94% -94% -96% cat_24 621193/s 107% 93% -- -0% -47% -50% -69% + -74% -85% -88% -88% -92% join_24 623208/s 108% 94% 0% -- -47% -50% -69% + -74% -85% -88% -88% -92% join_12 1173746/s 292% 265% 89% 88% -- -5% -41% + -51% -72% -77% -77% -85% cat_12 1235600/s 313% 284% 99% 98% 5% -- -38% + -49% -70% -76% -76% -85% join_6 1985139/s 563% 517% 220% 219% 69% 61% -- + -18% -52% -61% -61% -75% cat_6 2417374/s 707% 652% 289% 288% 106% 96% 22% + -- -42% -52% -52% -70% join_3 4145282/s 1284% 1189% 567% 565% 253% 235% 109% + 71% -- -18% -18% -49% cat_3 5049298/s 1586% 1470% 713% 710% 330% 309% 154% + 109% 22% -- -0% -38% join_2 5069139/s 1593% 1476% 716% 713% 332% 310% 155% + 110% 22% 0% -- -37% cat_2 8084458/s 2600% 2414% 1201% 1197% 589% 554% 307% + 234% 95% 60% 59% -- ------------------------------------------------------------ length $x = 8 length $y = 8 length $z = 8 ------------------------------------------------------------ Rate join_48 cat_48 join_24 cat_24 join_12 cat_12 join_6 +cat_6 join_3 cat_3 join_2 cat_2 join_48 318490/s -- -1% -40% -50% -73% -75% -84% + -87% -92% -94% -94% -96% cat_48 322321/s 1% -- -39% -49% -73% -75% -84% + -87% -92% -93% -94% -96% join_24 527508/s 66% 64% -- -17% -55% -58% -74% + -79% -86% -89% -90% -93% cat_24 633179/s 99% 96% 20% -- -46% -50% -68% + -74% -84% -87% -88% -92% join_12 1173542/s 268% 264% 122% 85% -- -7% -42% + -52% -70% -76% -77% -85% cat_12 1266359/s 298% 293% 140% 100% 8% -- -37% + -49% -67% -74% -75% -84% join_6 2010089/s 531% 524% 281% 217% 71% 59% -- + -18% -48% -59% -61% -74% cat_6 2463112/s 673% 664% 367% 289% 110% 95% 23% + -- -36% -50% -52% -68% join_3 3853091/s 1110% 1095% 630% 509% 228% 204% 92% + 56% -- -22% -25% -51% cat_3 4937508/s 1450% 1432% 836% 680% 321% 290% 146% + 100% 28% -- -4% -37% join_2 5165243/s 1522% 1503% 879% 716% 340% 308% 157% + 110% 34% 5% -- -34% cat_2 7793951/s 2347% 2318% 1378% 1131% 564% 515% 288% + 216% 102% 58% 51% -- ------------------------------------------------------------ length $x = 16 length $y = 16 length $z = 16 ------------------------------------------------------------ Rate cat_48 join_48 cat_24 join_24 cat_12 join_12 join_6 + cat_6 join_3 cat_3 join_2 cat_2 cat_48 394763/s -- -15% -50% -57% -74% -76% -86% + -87% -93% -94% -94% -96% join_48 462890/s 17% -- -41% -49% -70% -72% -84% + -85% -91% -93% -93% -96% cat_24 786847/s 99% 70% -- -13% -49% -52% -72% + -74% -85% -89% -89% -93% join_24 908319/s 130% 96% 15% -- -41% -45% -68% + -71% -83% -87% -87% -92% cat_12 1540454/s 290% 233% 96% 70% -- -7% -45% + -50% -71% -78% -78% -86% join_12 1652148/s 319% 257% 110% 82% 7% -- -41% + -46% -69% -76% -76% -85% join_6 2811157/s 612% 507% 257% 209% 82% 70% -- + -9% -47% -59% -60% -75% cat_6 3079963/s 680% 565% 291% 239% 100% 86% 10% + -- -42% -56% -56% -72% join_3 5343956/s 1254% 1054% 579% 488% 247% 223% 90% + 74% -- -23% -24% -52% cat_3 6922205/s 1654% 1395% 780% 662% 349% 319% 146% + 125% 30% -- -1% -38% join_2 6999736/s 1673% 1412% 790% 671% 354% 324% 149% + 127% 31% 1% -- -37% cat_2 11144965/s 2723% 2308% 1316% 1127% 623% 575% 296% + 262% 109% 61% 59% -- ------------------------------------------------------------ length $x = 32 length $y = 32 length $z = 32 ------------------------------------------------------------ Rate cat_48 join_48 cat_24 join_24 cat_12 join_12 join_6 + cat_6 join_3 cat_3 join_2 cat_2 cat_48 386670/s -- -15% -50% -57% -75% -76% -87% + -88% -93% -94% -94% -97% join_48 456381/s 18% -- -41% -49% -71% -72% -84% + -85% -91% -93% -93% -96% cat_24 779579/s 102% 71% -- -13% -50% -52% -73% + -75% -85% -89% -89% -93% join_24 893078/s 131% 96% 15% -- -43% -46% -70% + -71% -83% -87% -87% -92% cat_12 1568382/s 306% 244% 101% 76% -- -4% -47% + -49% -71% -77% -77% -86% join_12 1638868/s 324% 259% 110% 84% 4% -- -44% + -47% -69% -76% -76% -86% join_6 2932281/s 658% 543% 276% 228% 87% 79% -- + -5% -45% -57% -58% -74% cat_6 3099420/s 702% 579% 298% 247% 98% 89% 6% + -- -42% -55% -55% -73% join_3 5347004/s 1283% 1072% 586% 499% 241% 226% 82% + 73% -- -22% -23% -53% cat_3 6850770/s 1672% 1401% 779% 667% 337% 318% 134% + 121% 28% -- -2% -40% join_2 6957298/s 1699% 1424% 792% 679% 344% 325% 137% + 124% 30% 2% -- -39% cat_2 11457076/s 2863% 2410% 1370% 1183% 631% 599% 291% + 270% 114% 67% 65% -- ------------------------------------------------------------ length $x = 64 length $y = 64 length $z = 64 ------------------------------------------------------------ Rate cat_48 join_48 cat_24 join_24 cat_12 join_12 join_6 + cat_6 join_3 cat_3 join_2 cat_2 cat_48 376774/s -- -4% -50% -55% -75% -77% -87% + -87% -93% -94% -95% -96% join_48 392263/s 4% -- -48% -53% -74% -76% -86% + -87% -92% -94% -94% -96% cat_24 758578/s 101% 93% -- -9% -50% -54% -73% + -74% -85% -89% -89% -92% join_24 837790/s 122% 114% 10% -- -44% -49% -71% + -72% -84% -88% -88% -92% cat_12 1503652/s 299% 283% 98% 79% -- -8% -47% + -49% -71% -78% -78% -85% join_12 1642902/s 336% 319% 117% 96% 9% -- -42% + -44% -68% -76% -76% -84% join_6 2842350/s 654% 625% 275% 239% 89% 73% -- + -4% -45% -58% -59% -72% cat_6 2956899/s 685% 654% 290% 253% 97% 80% 4% + -- -42% -57% -57% -71% join_3 5130361/s 1262% 1208% 576% 512% 241% 212% 80% + 74% -- -25% -25% -49% cat_3 6798035/s 1704% 1633% 796% 711% 352% 314% 139% + 130% 33% -- -1% -32% join_2 6885745/s 1728% 1655% 808% 722% 358% 319% 142% + 133% 34% 1% -- -31% cat_2 10024409/s 2561% 2456% 1221% 1097% 567% 510% 253% + 239% 95% 47% 46% -- ------------------------------------------------------------ length $x = 128 length $y = 128 length $z = 128 ------------------------------------------------------------ Rate cat_48 join_48 cat_24 join_24 cat_12 join_12 join_6 +cat_6 join_3 cat_3 join_2 cat_2 cat_48 345863/s -- -5% -50% -56% -75% -77% -87% + -87% -93% -94% -95% -96% join_48 365729/s 6% -- -47% -53% -73% -75% -86% + -86% -92% -94% -94% -96% cat_24 686457/s 98% 88% -- -12% -50% -54% -74% + -74% -85% -89% -89% -93% join_24 782276/s 126% 114% 14% -- -43% -48% -71% + -71% -83% -87% -88% -92% cat_12 1373400/s 297% 276% 100% 76% -- -8% -48% + -49% -71% -77% -79% -86% join_12 1490923/s 331% 308% 117% 91% 9% -- -44% + -44% -68% -75% -77% -84% join_6 2658864/s 669% 627% 287% 240% 94% 78% -- + -1% -43% -56% -58% -72% cat_6 2676821/s 674% 632% 290% 242% 95% 80% 1% + -- -43% -56% -58% -72% join_3 4684392/s 1254% 1181% 582% 499% 241% 214% 76% + 75% -- -22% -27% -51% cat_3 6032896/s 1644% 1550% 779% 671% 339% 305% 127% + 125% 29% -- -6% -37% join_2 6390454/s 1748% 1647% 831% 717% 365% 329% 140% + 139% 36% 6% -- -33% cat_2 9572936/s 2668% 2517% 1295% 1124% 597% 542% 260% + 258% 104% 59% 50% --

-- Ken


In reply to Re: Is there a reason to use "join" instead of just using the period? (Benchmark results.) by kcott
in thread Is there a reason to use "join" instead of just using the period? by qazwart

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (7)
As of 2024-03-28 12:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found