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
34 changes: 27 additions & 7 deletions Benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,35 @@ node run.js --filter=/string/i

## Identity Mode Benchmarks

Compare `identityMode: "pointer"` vs default (`"none"`) for SwiftHeapObject wrapper caching. Requires `--expose-gc` for memory benchmarks.
Compare `identityMode: "pointer"` vs default (`"none"`) for SwiftHeapObject wrapper caching. Both class variants are compiled into the **same build** via per-class `@JS(identityMode: true)` annotations, so no separate builds or config files are needed.

Requires `--expose-gc` for memory benchmarks.

### Build once

```bash
swift package --swift-sdk $SWIFT_SDK_ID js -c release
```

### Compare both modes in one run

```bash
# Run identity benchmarks comparing both modes
node --expose-gc run.js --identity-mode=both
node --expose-gc run.js --identity-mode=both --identity-iterations=1000000
```

### Run only one mode

# Pointer mode only
node --expose-gc run.js --identity-mode=pointer
```bash
# Only pointer (identity-cached) classes
node --expose-gc run.js --identity-mode=pointer --identity-iterations=1000000

# Only non-identity classes
node --expose-gc run.js --identity-mode=none --identity-iterations=1000000
```

### Additional options

```bash
# Control iteration count (default: 1000000)
node --expose-gc run.js --identity-mode=both --identity-iterations=500000

Expand All @@ -59,8 +79,8 @@ node --expose-gc run.js --identity-mode=both --identity-memory
# Combine with adaptive sampling
node --expose-gc run.js --identity-mode=both --adaptive

# Save identity results
node --expose-gc run.js --identity-mode=both --output=results/identity-mode/results.json
# Filter to specific identity benchmarks
node --expose-gc run.js --adaptive --filter=passBothWaysRoundtrip --identity-mode=both --identity-iterations=1000000
```

### Identity Mode Scenarios
Expand Down
55 changes: 55 additions & 0 deletions Benchmarks/Sources/Benchmarks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,61 @@ nonisolated(unsafe) var _cachedPool: [SimpleClass] = []
}
}

// MARK: - Identity Mode Benchmark Variants
// These classes use @JS(identityMode: true) so that identity cache benchmarks
// can run in the SAME build alongside the non-identity classes above.

@JS(identityMode: true)
class SimpleClassIdentity {
@JS var name: String
@JS var count: Int
@JS var flag: Bool
@JS var rate: Float
@JS var precise: Double

@JS init(name: String, count: Int, flag: Bool, rate: Float, precise: Double) {
self.name = name
self.count = count
self.flag = flag
self.rate = rate
self.precise = precise
}
}

@JS(identityMode: true)
class ClassRoundtripIdentity {
@JS init() {}

@JS func roundtripSimpleClassIdentity(_ obj: SimpleClassIdentity) -> SimpleClassIdentity {
return obj
}

@JS func makeSimpleClassIdentity() -> SimpleClassIdentity {
return SimpleClassIdentity(name: "Hello", count: 42, flag: true, rate: 0.5, precise: 3.14159)
}

@JS func takeSimpleClassIdentity(_ obj: SimpleClassIdentity) {
// consume without returning
}
}

nonisolated(unsafe) var _cachedPoolIdentity: [SimpleClassIdentity] = []

@JS(identityMode: true)
class IdentityCacheBenchmarkIdentity {
@JS init() {}

@JS func setupPool(_ count: Int) {
_cachedPoolIdentity = (0..<count).map {
SimpleClassIdentity(name: "Item \($0)", count: $0, flag: true, rate: 0.5, precise: 3.14)
}
}

@JS func getPoolRepeated() -> [SimpleClassIdentity] {
return _cachedPoolIdentity
}
}

// MARK: - Array Performance Tests

@JS struct Point {
Expand Down
Loading
Loading