Skip to content

Commit

Permalink
feat(minor): Make it possible to build and run without jemalloc avail…
Browse files Browse the repository at this point in the history
…able (#127)

To run benchmarks without jemalloc installed:

BENCHMARK_DISABLE_JEMALLOC=1 swift package benchmark
  • Loading branch information
hassila authored Mar 22, 2023
1 parent 3023ab1 commit 93b8ae9
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 21 deletions.
56 changes: 39 additions & 17 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
// swift-tools-version: 5.7

import PackageDescription
import class Foundation.ProcessInfo

// If the environment variable BENCHMARK_DISABLE_JEMALLOC is set, we'll build the package without Jemalloc support

let disableJemalloc = ProcessInfo.processInfo.environment["BENCHMARK_DISABLE_JEMALLOC"]

let package = Package(
name: "Benchmark",
Expand All @@ -19,7 +24,6 @@ let package = Package(
.package(url: "https://github.com/swift-extras/swift-extras-json", .upToNextMajor(from: "0.6.0")),
// .package(url: "https://github.com/SwiftPackageIndex/SPIManifest", from: "0.12.0"),
.package(url: "https://github.com/ordo-one/TextTable", .upToNextMajor(from: "0.0.1")),
.package(url: "https://github.com/ordo-one/package-jemalloc", .upToNextMajor(from: "1.0.0")),
.package(url: "https://github.com/ordo-one/package-datetime", .upToNextMajor(from: "0.0.0")),
.package(url: "https://github.com/ordo-one/package-histogram", .upToNextMajor(from: "0.0.1")),
.package(url: "https://github.com/ordo-one/Progress.swift", .upToNextMajor(from: "1.0.0")),
Expand Down Expand Up @@ -85,22 +89,6 @@ let package = Package(
path: "Plugins/BenchmarkHelpGenerator"
),

// Benchmark package
.target(
name: "Benchmark",
dependencies: [
.product(name: "Histogram", package: "package-histogram"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "ExtrasJSON", package: "swift-extras-json"),
.product(name: "SystemPackage", package: "swift-system"),
.product(name: "jemalloc", package: "package-jemalloc"),
.product(name: "DateTime", package: "package-datetime"),
.product(name: "Progress", package: "Progress.swift"),
.byNameItem(name: "CDarwinOperatingSystemStats", condition: .when(platforms: [.macOS])),
.byNameItem(name: "CLinuxOperatingSystemStats", condition: .when(platforms: [.linux])),
]
),

// Getting OS specific information
.target(
name: "CDarwinOperatingSystemStats",
Expand Down Expand Up @@ -154,3 +142,37 @@ let package = Package(
),
]
)

if let disableJemalloc, disableJemalloc != "false", disableJemalloc != "0" {
package.targets += [
.target(
name: "Benchmark",
dependencies: [
.product(name: "Histogram", package: "package-histogram"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "ExtrasJSON", package: "swift-extras-json"),
.product(name: "SystemPackage", package: "swift-system"),
.product(name: "DateTime", package: "package-datetime"),
.product(name: "Progress", package: "Progress.swift"),
.byNameItem(name: "CDarwinOperatingSystemStats", condition: .when(platforms: [.macOS])),
.byNameItem(name: "CLinuxOperatingSystemStats", condition: .when(platforms: [.linux])),
]
)]
} else {
package.dependencies += [.package(url: "https://github.com/ordo-one/package-jemalloc", .upToNextMajor(from: "1.0.0"))]
package.targets += [
.target(
name: "Benchmark",
dependencies: [
.product(name: "Histogram", package: "package-histogram"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "ExtrasJSON", package: "swift-extras-json"),
.product(name: "SystemPackage", package: "swift-system"),
.product(name: "jemalloc", package: "package-jemalloc"),
.product(name: "DateTime", package: "package-datetime"),
.product(name: "Progress", package: "Progress.swift"),
.byNameItem(name: "CDarwinOperatingSystemStats", condition: .when(platforms: [.macOS])),
.byNameItem(name: "CLinuxOperatingSystemStats", condition: .when(platforms: [.linux])),
]
)]
}
14 changes: 11 additions & 3 deletions Sources/Benchmark/Documentation.docc/GettingStarted.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,19 @@ After having done those, running your benchmarks are as simple as running `swift

Benchmark requires Swift 5.7 support as it uses Regex and Duration types introduced with the `macOS 13` runtime, most versions of Linux will work as long as Swift 5.7+ is used.

Benchmark also depends and needs the [jemalloc](https://jemalloc.net) memory allocation library, which is used by the Benchmark infrastructure to capture memory allocation statistics, as `jemalloc` provides a rich programmatic API for extracting memory allocation statistics at runtime.
Benchmark also by default depends on and uses the [jemalloc](https://jemalloc.net) memory allocation library, which is used by the Benchmark infrastructure to capture memory allocation statistics.

The Benchmark package requires you to install jemalloc on any machine used for benchmarking.
For platforms where `jemalloc` isn't available it's possible to build the Benchmark package without a `jemalloc` dependency by setting the environment variable BENCHMARK_DISABLE_JEMALLOC to any value except `false` or `0`.

If you want to avoid adding the `jemalloc` dependency to your project, the recommended approach is to embed a separate Swift project in a subdirectory that uses your project, then the dependency on `jemalloc` is contained to that subproject only.
E.g. to run the benchmark on the command line without memory allocation stats could look like:

```bash
BENCHMARK_DISABLE_JEMALLOC=true swift package benchmark
```

The Benchmark package requires you to install jemalloc on any machine used for benchmarking if you want malloc statistics.

If you want to avoid adding the `jemalloc` dependency to your main project while still getting malloc statistics when benchmarking, the recommended approach is to embed a separate Swift project in a subdirectory that uses your project, then the dependency on `jemalloc` is contained to that subproject only.

#### Installing `jemalloc` on macOS

Expand Down
16 changes: 16 additions & 0 deletions Sources/Benchmark/MallocStats/MallocStatsProducer+jemalloc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
//

import ExtrasJSON

#if canImport(jemalloc)
import jemalloc

// We currently register a number of MIB:s that aren't in use that
Expand Down Expand Up @@ -165,3 +167,17 @@ class MallocStatsProducer {
return carrier.data
}
}

#else

// stub if no jemalloc available
class MallocStatsProducer {
func makeMallocStats() -> MallocStats {
return MallocStats(mallocCountTotal: 0,
mallocCountSmall: 0,
mallocCountLarge: 0,
allocatedResidentMemory: 0)
}
}

#endif
3 changes: 2 additions & 1 deletion Tests/BenchmarkTests/OperatingSystemAndMallocTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ final class OperatingSystemAndMallocTests: XCTestCase {
blackHole(operatingSystemStatsProducer.metricSupported(.writeBytesPhysical))
blackHole(operatingSystemStatsProducer.metricSupported(.throughput))
}

#if canImport(jemalloc)
func testMallocProducerLeaks() throws {
let mallocStatsProducer = MallocStatsProducer()
let startMallocStats = mallocStatsProducer.makeMallocStats()
Expand All @@ -68,4 +68,5 @@ final class OperatingSystemAndMallocTests: XCTestCase {
XCTAssertGreaterThanOrEqual(stopMallocStats.allocatedResidentMemory - startMallocStats.allocatedResidentMemory,
100 * 1_024)
}
#endif
}

0 comments on commit 93b8ae9

Please sign in to comment.