xc against Objective-C

The same programs in both languages, both with automatic reference counting, built at four optimisation levels.

versionv0.6
platformarm64
runs per point3
benchmarks19

Each figure is the fastest of the runs. Every program times its own measured region with clock_gettime(CLOCK_MONOTONIC), so process startup and data setup are outside the number. Both programs print a checksum and a run is rejected if they disagree.

The arm64 Objective-C column is Apple's runtime and Foundation; the x86-64 column is libobjc2 and gnustep-base. Comparing a ratio across the two platforms therefore also compares two different Objective-C implementations, which matters most for the benchmarks dominated by allocation and dispatch.

Time by benchmark and optimisation level

xc arm64ObjC arm64xc x86-64ObjC x86-64ratio below 1 means xc is faster
benchmarkO0O1O2O3
arm64x86-64arm64x86-64arm64x86-64arm64x86-64
arc_alloc1.52×4.37×1.60×6.02×1.54×5.96×1.51×5.17×
arc_array1.49×0.88×1.45×1.41×0.85×0.47×0.86×0.49×
array_map3.94×1.49×9.60×4.28×9.53×2.61×9.63×2.63×
array_sum0.98×2.42×2.26×3.61×1.04×1.39×1.03×1.40×
bit_ops3.59×3.15×5.61×6.13×4.60×2.75×4.33×2.82×
branch_mix3.31×3.08×5.72×4.82×4.25×1.64×4.39×1.56×
call_depth1.71×1.12×8.60×5.67×2.45×6.12×2.46×6.13×
float_math4.23×1.61×4.58×8.39×4.30×5.98×4.34×6.01×
hash_mix0.43×1.01×1.12×1.01×1.09×1.09×1.05×1.12×
int_accum1.14×1.97×1.56×2.37×3.71×1.12×3.75×1.15×
int_muldiv2.94×0.87×5.59×3.73×10.98×3.66×11.58×3.88×
matrix_mul3.02×2.51×7.91×7.67×11.63×4.75×12.58×4.75×
mem_copy6.01×2.02×13.03×3.97×9.39×4.16×9.97×4.10×
method_call0.40×0.70×0.45×1.07×0.54×0.81×0.47×0.81×
poly_dispatch1.31×0.88×2.16×1.10×1.42×0.89×1.44×0.88×
sieve1.23×2.48×2.73×5.50×1.73×3.19×1.81×3.15×
sort_small1.91×3.05×5.73×6.13×4.31×3.33×4.12×3.66×
string_scan2.35×2.82×6.42×5.80×23.65×11.18×23.72×11.14×
struct_copy1.43×1.09×10.46×14.39×9.46×15.74×10.17×15.52×

Per benchmark

arc_alloc

0.000s0.087s0.174s0.261s0.348sO0xc O0 0.0690sobjc O0 0.0454sxc_x86_64 O0 0.3329sobjc_x86_64 O0 0.0762sO1xc O1 0.0559sobjc O1 0.0349sxc_x86_64 O1 0.3483sobjc_x86_64 O1 0.0578sO2xc O2 0.0544sobjc O2 0.0353sxc_x86_64 O2 0.3237sobjc_x86_64 O2 0.0543sO3xc O3 0.0523sobjc O3 0.0346sxc_x86_64 O3 0.3262sobjc_x86_64 O3 0.0631s

arc_array

0.000s0.014s0.027s0.041s0.055sO0xc O0 0.0546sobjc O0 0.0368sxc_x86_64 O0 0.0354sobjc_x86_64 O0 0.0401sO1xc O1 0.0526sobjc O1 0.0363sxc_x86_64 O1 0.0358sobjc_x86_64 O1 0.0254sO2xc O2 0.0303sobjc O2 0.0357sxc_x86_64 O2 0.0120sobjc_x86_64 O2 0.0256sO3xc O3 0.0310sobjc O3 0.0359sxc_x86_64 O3 0.0122sobjc_x86_64 O3 0.0249s

array_map

0.000s0.066s0.131s0.197s0.262sO0xc O0 0.2621sobjc O0 0.0665sxc_x86_64 O0 0.0963sobjc_x86_64 O0 0.0647sO1xc O1 0.2617sobjc O1 0.0273sxc_x86_64 O1 0.0944sobjc_x86_64 O1 0.0220sO2xc O2 0.0384sobjc O2 0.0040sxc_x86_64 O2 0.0204sobjc_x86_64 O2 0.0078sO3xc O3 0.0385sobjc O3 0.0040sxc_x86_64 O3 0.0205sobjc_x86_64 O3 0.0078s

array_sum

0.000s0.019s0.037s0.056s0.074sO0xc O0 0.0436sobjc O0 0.0445sxc_x86_64 O0 0.0743sobjc_x86_64 O0 0.0308sO1xc O1 0.0448sobjc O1 0.0198sxc_x86_64 O1 0.0727sobjc_x86_64 O1 0.0202sO2xc O2 0.0029sobjc O2 0.0028sxc_x86_64 O2 0.0072sobjc_x86_64 O2 0.0052sO3xc O3 0.0028sobjc O3 0.0027sxc_x86_64 O3 0.0072sobjc_x86_64 O3 0.0052s

bit_ops

0.000s0.057s0.115s0.172s0.230sO0xc O0 0.2296sobjc O0 0.0640sxc_x86_64 O0 0.2042sobjc_x86_64 O0 0.0648sO1xc O1 0.2298sobjc O1 0.0410sxc_x86_64 O1 0.1987sobjc_x86_64 O1 0.0324sO2xc O2 0.1853sobjc O2 0.0403sxc_x86_64 O2 0.0891sobjc_x86_64 O2 0.0324sO3xc O3 0.1799sobjc O3 0.0416sxc_x86_64 O3 0.0913sobjc_x86_64 O3 0.0324s

branch_mix

0.000s0.059s0.119s0.178s0.238sO0xc O0 0.2372sobjc O0 0.0716sxc_x86_64 O0 0.1530sobjc_x86_64 O0 0.0496sO1xc O1 0.2377sobjc O1 0.0415sxc_x86_64 O1 0.1560sobjc_x86_64 O1 0.0324sO2xc O2 0.1789sobjc O2 0.0421sxc_x86_64 O2 0.0590sobjc_x86_64 O2 0.0359sO3xc O3 0.1900sobjc O3 0.0433sxc_x86_64 O3 0.0536sobjc_x86_64 O3 0.0344s

call_depth

0.000s0.008s0.015s0.023s0.031sO0xc O0 0.0270sobjc O0 0.0157sxc_x86_64 O0 0.0307sobjc_x86_64 O0 0.0274sO1xc O1 0.0268sobjc O1 0.0031sxc_x86_64 O1 0.0299sobjc_x86_64 O1 0.0053sO2xc O2 0.0037sobjc O2 0.0015sxc_x86_64 O2 0.0104sobjc_x86_64 O2 0.0017sO3xc O3 0.0037sobjc O3 0.0015sxc_x86_64 O3 0.0104sobjc_x86_64 O3 0.0017s

float_math

0.000s0.020s0.039s0.059s0.078sO0xc O0 0.0490sobjc O0 0.0116sxc_x86_64 O0 0.0782sobjc_x86_64 O0 0.0486sO1xc O1 0.0496sobjc O1 0.0108sxc_x86_64 O1 0.0778sobjc_x86_64 O1 0.0093sO2xc O2 0.0397sobjc O2 0.0092sxc_x86_64 O2 0.0564sobjc_x86_64 O2 0.0094sO3xc O3 0.0401sobjc O3 0.0092sxc_x86_64 O3 0.0562sobjc_x86_64 O3 0.0094s

hash_mix

0.000s0.010s0.020s0.030s0.041sO0xc O0 0.0173sobjc O0 0.0407sxc_x86_64 O0 0.0160sobjc_x86_64 O0 0.0159sO1xc O1 0.0175sobjc O1 0.0156sxc_x86_64 O1 0.0159sobjc_x86_64 O1 0.0158sO2xc O2 0.0171sobjc O2 0.0157sxc_x86_64 O2 0.0184sobjc_x86_64 O2 0.0169sO3xc O3 0.0169sobjc O3 0.0161sxc_x86_64 O3 0.0188sobjc_x86_64 O3 0.0169s

int_accum

0.000s0.040s0.079s0.119s0.158sO0xc O0 0.0597sobjc O0 0.0523sxc_x86_64 O0 0.0701sobjc_x86_64 O0 0.0356sO1xc O1 0.0609sobjc O1 0.0391sxc_x86_64 O1 0.0886sobjc_x86_64 O1 0.0373sO2xc O2 0.1490sobjc O2 0.0401sxc_x86_64 O2 0.0455sobjc_x86_64 O2 0.0406sO3xc O3 0.1584sobjc O3 0.0422sxc_x86_64 O3 0.0462sobjc_x86_64 O3 0.0402s

int_muldiv

0.000s0.031s0.061s0.092s0.122sO0xc O0 0.1222sobjc O0 0.0416sxc_x86_64 O0 0.0841sobjc_x86_64 O0 0.0972sO1xc O1 0.1174sobjc O1 0.0210sxc_x86_64 O1 0.0848sobjc_x86_64 O1 0.0227sO2xc O2 0.0664sobjc O2 0.0061sxc_x86_64 O2 0.0457sobjc_x86_64 O2 0.0125sO3xc O3 0.0683sobjc O3 0.0059sxc_x86_64 O3 0.0485sobjc_x86_64 O3 0.0125s

matrix_mul

0.000s0.004s0.009s0.013s0.018sO0xc O0 0.0160sobjc O0 0.0053sxc_x86_64 O0 0.0177sobjc_x86_64 O0 0.0071sO1xc O1 0.0161sobjc O1 0.0020sxc_x86_64 O1 0.0174sobjc_x86_64 O1 0.0023sO2xc O2 0.0136sobjc O2 0.0012sxc_x86_64 O2 0.0079sobjc_x86_64 O2 0.0017sO3xc O3 0.0139sobjc O3 0.0011sxc_x86_64 O3 0.0079sobjc_x86_64 O3 0.0017s

mem_copy

0.000s0.067s0.134s0.201s0.269sO0xc O0 0.2686sobjc O0 0.0447sxc_x86_64 O0 0.0737sobjc_x86_64 O0 0.0365sO1xc O1 0.2615sobjc O1 0.0201sxc_x86_64 O1 0.0752sobjc_x86_64 O1 0.0190sO2xc O2 0.0264sobjc O2 0.0028sxc_x86_64 O2 0.0162sobjc_x86_64 O2 0.0039sO3xc O3 0.0270sobjc O3 0.0027sxc_x86_64 O3 0.0159sobjc_x86_64 O3 0.0039s

method_call

0.000s0.005s0.010s0.014s0.019sO0xc O0 0.0065sobjc O0 0.0162sxc_x86_64 O0 0.0134sobjc_x86_64 O0 0.0190sO1xc O1 0.0061sobjc O1 0.0136sxc_x86_64 O1 0.0127sobjc_x86_64 O1 0.0119sO2xc O2 0.0075sobjc O2 0.0140sxc_x86_64 O2 0.0096sobjc_x86_64 O2 0.0119sO3xc O3 0.0067sobjc O3 0.0143sxc_x86_64 O3 0.0096sobjc_x86_64 O3 0.0119s

poly_dispatch

0.000s0.004s0.008s0.012s0.016sO0xc O0 0.0161sobjc O0 0.0122sxc_x86_64 O0 0.0113sobjc_x86_64 O0 0.0128sO1xc O1 0.0156sobjc O1 0.0072sxc_x86_64 O1 0.0113sobjc_x86_64 O1 0.0103sO2xc O2 0.0112sobjc O2 0.0079sxc_x86_64 O2 0.0091sobjc_x86_64 O2 0.0103sO3xc O3 0.0114sobjc O3 0.0080sxc_x86_64 O3 0.0091sobjc_x86_64 O3 0.0103s

sieve

0.000s0.019s0.037s0.056s0.075sO0xc O0 0.0543sobjc O0 0.0443sxc_x86_64 O0 0.0745sobjc_x86_64 O0 0.0301sO1xc O1 0.0550sobjc O1 0.0201sxc_x86_64 O1 0.0742sobjc_x86_64 O1 0.0135sO2xc O2 0.0346sobjc O2 0.0200sxc_x86_64 O2 0.0427sobjc_x86_64 O2 0.0134sO3xc O3 0.0364sobjc O3 0.0202sxc_x86_64 O3 0.0425sobjc_x86_64 O3 0.0135s

sort_small

0.000s0.031s0.062s0.094s0.125sO0xc O0 0.0792sobjc O0 0.0414sxc_x86_64 O0 0.1175sobjc_x86_64 O0 0.0385sO1xc O1 0.0787sobjc O1 0.0137sxc_x86_64 O1 0.1248sobjc_x86_64 O1 0.0204sO2xc O2 0.0513sobjc O2 0.0119sxc_x86_64 O2 0.0766sobjc_x86_64 O2 0.0230sO3xc O3 0.0526sobjc O3 0.0127sxc_x86_64 O3 0.0767sobjc_x86_64 O3 0.0210s

string_scan

0.000s0.082s0.163s0.245s0.327sO0xc O0 0.2578sobjc O0 0.1095sxc_x86_64 O0 0.2560sobjc_x86_64 O0 0.0908sO1xc O1 0.2549sobjc O1 0.0397sxc_x86_64 O1 0.2571sobjc_x86_64 O1 0.0443sO2xc O2 0.3151sobjc O2 0.0133sxc_x86_64 O2 0.1851sobjc_x86_64 O2 0.0166sO3xc O3 0.3266sobjc O3 0.0138sxc_x86_64 O3 0.1840sobjc_x86_64 O3 0.0165s

struct_copy

0.000s0.007s0.014s0.021s0.029sO0xc O0 0.0227sobjc O0 0.0159sxc_x86_64 O0 0.0285sobjc_x86_64 O0 0.0262sO1xc O1 0.0228sobjc O1 0.0022sxc_x86_64 O1 0.0285sobjc_x86_64 O1 0.0020sO2xc O2 0.0207sobjc O2 0.0022sxc_x86_64 O2 0.0281sobjc_x86_64 O2 0.0018sO3xc O3 0.0208sobjc O3 0.0020sxc_x86_64 O3 0.0277sobjc_x86_64 O3 0.0018s

Optimisations by target

Read from the compiler's target profiles when this page was rendered. A target that does not override a setting takes the base value.

optimisationbaseArm64X86_64Arm9Wasm32M68kXt6502
unroll allows multiple carried valuesnoyesyesyesyesyesno
unroll allows calls in bodynoyesnonononono
eliminates redundant init guardsnoyesyesyesyesyesyes
hoists init guards to entrynoyesyesyesyesyesno
folds pow squarenoyesyesyesyesnono
lowers sqrt to hardwarenoyesyesyesyesnono
uses native varargsnoyesnoyesnonono
hoists global addrnoyesyesyesnoyesyes
unrolls variable tripnoyesyesyesnonono
recognises memset idiomnoyesyesyesyesnono
hoists loop invariantsnoyesyesyesyesyesyes
converts tail recursionnoyesyesyesyesyesyes
converts accumulator recursionnononononoyesyes
if converts predicatesnoyesyesyesyesyesyes
rotates loopsnoyesyesyesyesyesno
vectorizes loopsnoyesyesyesyesnono
forms pointer induction varsnoyesyesyesnoyesno
collapses invariant reductionsnoyesyesnonoyesyes
narrows induction varsnononononoyesyes