XPerf
LanguagesObjective-C

Objective-C performance guide (v0)

Foundation collection, string, and logging checklists. Distinct from swiftperf.

Scope: Objective-C (ARC or MRC). Lint is a line-window scan of .m/.h. Speedup claims cite a local bench, an upstream source, or are marked provisional. Corpus residual counts are lint hit counts, not wall-time savings.

Profile first (Instruments Time Profiler / Allocations). Measure on device or macOS before escalating.

Contents

1. Collections

[[NSMutableArray alloc] init] then many addObject: calls can resize repeatedly. Prefer arrayWithCapacity: when n is known. No lint rule covers this: the capacity rules were removed after a jitter-controlled retest showed no reliable speedup.

2. Strings and hot I/O

stringByAppendingString: in a loop allocates many immutable strings. Prefer NSMutableString. Keep NSLog out of tight loops (gate or use os_log carefully).

Lint: oc-nsstring-append-hot, oc-nslog-hot (default off).

3. Formatters, JSON, and regular expressions

[[NSDateFormatter alloc] init], [NSDateFormatter new], NSJSONSerialization (JSONObjectWithData / dataWithJSONObject), and NSRegularExpression (regularExpressionWithPattern) inside a loop repeat that setup on every iteration. Create the formatter or expression once, and parse or encode a payload once when the data allows it. These lints are hint. Each has a JSONL microbench and stays hint. They are not part of the 2026-10-22 corpus-ready verdict. They do not revive the removed array-capacity rules.

stringWithContentsOfFile: of one path was about 450× versus reading once. A path that changes every iteration cannot be hoisted.

[NSDate date] every iteration was about 769× versus one sample. A loop that needs a fresh timestamp has nothing to hoist. NSDateFormatter stays its own rule.

valueForKey: every iteration was about 124× versus reading the field. A name that is not a fixed field cannot be rewritten as a direct read. This is the same family as Go FieldByName.

Lint: oc-dateformatter-hot, oc-json-hot, oc-regex-hot, oc-file-read-hot, oc-clock-hot, oc-value-for-key-hot (default hint).

Lint map

IDSmellDefault
oc-nsstring-append-hotstringByAppendingString in loopoff
oc-nslog-hotNSLog in loopoff
oc-dateformatter-hotdate formatter alloc/init or new in a loophint (JSONL present; not corpus-triaged)
oc-json-hotJSON parse or encode in a loophint (JSONL present; not corpus-triaged)
oc-regex-hotregular expression compiled in a loophint (JSONL present; not corpus-triaged)

Escalate only with evidence/oc-*.jsonl — see evidence-policy.md. The two array-capacity rules (OC001, OC004) were removed; see rule-ids.md. oc-dateformatter-hot, oc-json-hot, and oc-regex-hot have a JSONL microbench and stay hint. They are not part of the 2026-10-22 corpus-ready verdict.

References