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.
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:
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.
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% --