Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
# `@bacons/xcode`

The fastest and most accurate parser for Xcode project files (`.pbxproj`). **11x faster** than the legacy `xcode` package with better error messages and full spec compliance.
The fastest and most accurate parser for Xcode project files (`.pbxproj`). **10-28x faster** than alternatives (xcode, XcodeProj, xcodeproj) with better error messages and full spec compliance.

```
bun add @bacons/xcode
```

## Performance

Run benchmarks with `bun run bench`.
Run benchmarks with `bun run bench` or `bun run bench:compare` for cross-language comparison.

```mermaid
xychart-beta horizontal
title "Parse Time (lower is better)"
x-axis ["@bacons/xcode", "legacy xcode"]
y-axis "Time (ms)" 0 --> 1.5
bar [0.12, 1.4]
title "Parse Time - 29KB file (lower is better)"
x-axis ["@bacons/xcode", "xcode (legacy)", "XcodeProj (Swift)", "xcodeproj (Ruby)"]
y-axis "Time (ms)" 0 --> 4
bar [0.15, 1.54, 2.00, 3.63]
```

| Parser | Time (29KB) | Time (263KB) | Throughput |
|--------|-------------|--------------|------------|
| **@bacons/xcode** | **120µs** | **800µs** | **315 MB/s** |
| legacy xcode | 1.4ms | crashes | ~20 MB/s |
| Parser | Language | Time (29KB) | Time (263KB) | Relative |
|--------|----------|-------------|--------------|----------|
| **@bacons/xcode** | TypeScript | **0.15ms** | **0.81ms** | **1x** |
| xcode (legacy) | JavaScript | 1.54ms | crashes | 10x slower |
| XcodeProj (Tuist) | Swift | 2.00ms | 11.2ms | 13x slower |
| xcodeproj (CocoaPods) | Ruby | 3.63ms | 22.5ms | 24x slower |

### Key Performance Features

- **11.7x faster** than the legacy `xcode` npm package
- **10-28x faster** than alternatives (xcode, XcodeProj, xcodeproj)
- Single-pass parsing with no intermediate representation
- Pre-computed lookup tables for character classification
- Handles files that crash the legacy parser
Expand Down
1 change: 1 addition & 0 deletions bench/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Gemfile.lock
6 changes: 6 additions & 0 deletions bench/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

source "https://rubygems.org"

# CocoaPods xcodeproj gem for parsing pbxproj files
gem "xcodeproj", "~> 1.24"
83 changes: 83 additions & 0 deletions bench/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Benchmarks

This directory contains benchmarks comparing `@bacons/xcode` against other pbxproj parsers.

## Parsers Compared

| Parser | Language | Library |
|--------|----------|---------|
| @bacons/xcode | TypeScript | Chevrotain |
| xcode (legacy) | JavaScript | PEG.js |
| xcodeproj | Ruby | CocoaPods gem |
| XcodeProj | Swift | Tuist |

## Quick Start

```bash
# Run TypeScript-only benchmarks
bun run bench

# Run cross-language comparison (requires setup below)
bun run bench:compare
```

## Setup

### Ruby (xcodeproj gem)

```bash
# Option 1: Install globally
gem install xcodeproj

# Option 2: Use bundler
cd bench
bundle install
```

### Swift (XcodeProj)

```bash
# Build the Swift benchmark tool
bun run bench:setup

# Or manually:
cd bench/swift-bench
swift build -c release
```

## Benchmarks

### `bun run bench`

Runs detailed benchmarks of `@bacons/xcode` using [mitata](https://github.com/evanwashere/mitata):
- Parse time across different fixture sizes
- XcodeProject.open() (full object graph)
- Round-trip (parse + build)
- Comparison with legacy xcode package

### `bun run bench:compare`

Runs cross-language comparison across all parsers:
- Tests multiple fixtures (small to large)
- Shows avg/min/max times
- Handles parser errors gracefully

## Results

Typical results on Apple Silicon (M1/M2):

| Parser | 29KB (RN) | 263KB (Protobuf) |
|--------|-----------|------------------|
| @bacons/xcode | ~0.1ms | ~1ms |
| xcode (legacy) | ~1.4ms | ❌ crashes |
| xcodeproj (Ruby) | ~2-3ms | ~15-20ms |
| XcodeProj (Swift) | ~0.5ms | ~3-4ms |

Note: Ruby and Swift times include some process/runtime overhead when called from the benchmark script.

## Adding Fixtures

Fixtures are located in `src/json/__tests__/fixtures/`. To add a new fixture:

1. Add the `.pbxproj` file to the fixtures directory
2. Update the `fixtures` array in `bench/parse.bench.ts` and/or `bench/compare.ts`
Loading