Skip to content

Add placeholder ordo-benchmark and JMH benchmarks #134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 2 additions & 2 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install System Dependencies
run: apt-get -qq update && apt-get -qq install -y make curl wget
run: apt-get -qq update && apt-get -qq install -y make curl wget libjemalloc2 libjemalloc-dev
- name: Cache JDK
id: cache-jdk
uses: actions/cache@v4
Expand Down Expand Up @@ -86,7 +86,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Install System Dependencies
run: apt-get -qq update && apt-get -qq install -y make curl wget
run: apt-get -qq update && apt-get -qq install -y make curl wget libjemalloc2 libjemalloc-dev
- name: Cache JDK
id: cache-jdk
uses: actions/cache@v4
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import Benchmark
import Foundation
import JavaKit
import JavaKitNetwork

@MainActor let benchmarks = {
var jvm: JavaVirtualMachine {
get throws {
try .shared()
}
}
Benchmark("Simple call to Java library") { benchmark in
for _ in benchmark.scaledIterations {
let environment = try jvm.environment()

let urlConnectionClass = try JavaClass<URLConnection>(environment: environment)
blackHole(urlConnectionClass.getDefaultAllowUserInteraction())
}
}
}
69 changes: 69 additions & 0 deletions Benchmarks/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// swift-tools-version: 6.0

import PackageDescription

import class Foundation.FileManager
import class Foundation.ProcessInfo

// Note: the JAVA_HOME environment variable must be set to point to where
// Java is installed, e.g.,
// Library/Java/JavaVirtualMachines/openjdk-21.jdk/Contents/Home.
func findJavaHome() -> String {
if let home = ProcessInfo.processInfo.environment["JAVA_HOME"] {
return home
}

// This is a workaround for envs (some IDEs) which have trouble with
// picking up env variables during the build process
let path = "\(FileManager.default.homeDirectoryForCurrentUser.path()).java_home"
if let home = try? String(contentsOfFile: path, encoding: .utf8) {
if let lastChar = home.last, lastChar.isNewline {
return String(home.dropLast())
}

return home
}

fatalError("Please set the JAVA_HOME environment variable to point to where Java is installed.")
}
let javaHome = findJavaHome()

let javaIncludePath = "\(javaHome)/include"
#if os(Linux)
let javaPlatformIncludePath = "\(javaIncludePath)/linux"
#elseif os(macOS)
let javaPlatformIncludePath = "\(javaIncludePath)/darwin"
#else
// TODO: Handle windows as well
#error("Currently only macOS and Linux platforms are supported, this may change in the future.")
#endif

let package = Package(
name: "benchmarks",
platforms: [
.macOS("15.03")
],
dependencies: [
.package(path: "../"),
.package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")),
],
targets: [
.executableTarget(
name: "JavaApiCallBenchmarks",
dependencies: [
.product(name: "JavaRuntime", package: "swift-java"),
.product(name: "JavaKit", package: "swift-java"),
.product(name: "JavaKitNetwork", package: "swift-java"),
.product(name: "Benchmark", package: "package-benchmark"),
],
path: "Benchmarks/JavaApiCallBenchmarks",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool structure is looking good now

swiftSettings: [
.unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"]),
.swiftLanguageMode(.v5),
],
plugins: [
.plugin(name: "BenchmarkPlugin", package: "package-benchmark")
]
)
]
)
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,12 @@ jextract-generate: jextract-swift generate-JExtract-interface-files
swift run jextract-swift \
--package-name com.example.swift.generated \
--swift-module ExampleSwiftLibrary \
--output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/src/generated/java \
--output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/build/generated/sources/jextract/main \
$(BUILD_DIR)/jextract/ExampleSwiftLibrary/MySwiftLibrary.swiftinterface; \
swift run jextract-swift \
--package-name org.swift.swiftkit.generated \
--swift-module SwiftKitSwift \
--output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/src/generated/java \
--output-directory ${SAMPLES_DIR}/SwiftKitSampleApp/build/generated/sources/jextract/main \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense!

$(BUILD_DIR)/jextract/SwiftKitSwift/SwiftKit.swiftinterface


Expand Down
33 changes: 17 additions & 16 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,18 +94,18 @@ let package = Package(

// ==== Plugin for building Java code
.plugin(
name: "JavaCompilerPlugin",
targets: [
"JavaCompilerPlugin"
]
name: "JavaCompilerPlugin",
targets: [
"JavaCompilerPlugin"
]
),

// ==== Plugin for wrapping Java classes in Swift
.plugin(
name: "Java2SwiftPlugin",
targets: [
"Java2SwiftPlugin"
]
name: "Java2SwiftPlugin",
targets: [
"Java2SwiftPlugin"
]
),

// ==== jextract-swift (extract Java accessors from Swift interface files)
Expand Down Expand Up @@ -140,6 +140,7 @@ let package = Package(
.package(url: "https://github.com/swiftlang/swift-syntax.git", branch: "main"),
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.5.0"),
.package(url: "https://github.com/apple/swift-collections.git", .upToNextMinor(from: "1.1.0")),
.package(url: "https://github.com/ordo-one/package-benchmark", .upToNextMajor(from: "1.4.0")),
],
targets: [
.macro(
Expand Down Expand Up @@ -225,16 +226,16 @@ let package = Package(
]
),
.plugin(
name: "JavaCompilerPlugin",
capability: .buildTool()
name: "JavaCompilerPlugin",
capability: .buildTool()
),

.plugin(
name: "Java2SwiftPlugin",
capability: .buildTool(),
dependencies: [
"Java2Swift"
]
name: "Java2SwiftPlugin",
capability: .buildTool(),
dependencies: [
"Java2Swift"
]
),

.target(
Expand Down Expand Up @@ -373,6 +374,6 @@ let package = Package(
.swiftLanguageMode(.v5),
.unsafeFlags(["-I\(javaIncludePath)", "-I\(javaPlatformIncludePath)"])
]
),
)
]
)
68 changes: 26 additions & 42 deletions Samples/SwiftKitSampleApp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.swift.swiftkit.gradle.BuildUtils

plugins {
id("build-logic.java-application-conventions")
id("me.champeau.jmh") version "0.7.2"
}

group = "org.swift.swiftkit"
Expand All @@ -31,43 +32,38 @@ java {
}
}

sourceSets {
generated {
java.srcDir "${buildDir}/generated/src/java/"
}

// Make the 'main' and 'test' source sets depend on the generated sources
main {
compileClasspath += sourceSets.generated.output
runtimeClasspath += sourceSets.generated.output
}
test {
compileClasspath += sourceSets.main.output
runtimeClasspath += sourceSets.main.output
def jextract = tasks.register("jextract", Exec) {
description = "Extracts Java accessor sources using jextract"

outputs.dir(layout.buildDirectory.dir("generated/sources/jextract/main"))
inputs.dir("$rootDir/Sources/ExampleSwiftLibrary") // monitored library

// any changes in the source generator sources also mean the resulting output might change
inputs.dir("$rootDir/Sources/JExtractSwift")
inputs.dir("$rootDir/Sources/JExtractSwiftTool")

compileClasspath += sourceSets.generated.output
runtimeClasspath += sourceSets.generated.output
workingDir = rootDir
commandLine "make"
args "jextract-generate"
}

sourceSets {
main {
java {
srcDir(jextract)
}
}
}

dependencies {
implementation(project(':SwiftKit'))
generatedImplementation(project(':SwiftKit'))

testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter")
}

configurations {
generatedImplementation.extendsFrom(mainImplementation)
generatedRuntimeOnly.extendsFrom(mainRuntimeOnly)
}

tasks.named("compileJava").configure {
dependsOn("jextract")
}

tasks.test {
tasks.named('test', Test) {
useJUnitPlatform()
}

Expand All @@ -84,27 +80,15 @@ application {
"--enable-native-access=ALL-UNNAMED",

// Include the library paths where our dylibs are that we want to load and call
"-Djava.library.path=" + BuildUtils.javaLibraryPaths().join(":"),
"-Djava.library.path=" + BuildUtils.javaLibraryPaths(rootDir).join(":"),

// Enable tracing downcalls (to Swift)
"-Djextract.trace.downcalls=true"
]
}

task jextract(type: Exec) {
description = "Extracts Java accessor sources using jextract"
outputs.dir(layout.buildDirectory.dir("generated"))
inputs.dir("$rootDir/Sources/ExampleSwiftLibrary") // monitored library

// any changes in the source generator sources also mean the resulting output might change
inputs.dir("$rootDir/Sources/JExtractSwift")
inputs.dir("$rootDir/Sources/JExtractSwiftTool")

workingDir = rootDir
commandLine "make"
args "jextract-generate"
}

tasks.named("compileGeneratedJava").configure {
dependsOn jextract
jmh {
jvmArgsAppend = [
"-Djava.library.path=" + BuildUtils.javaLibraryPaths(rootDir).join(":"),
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 Apple Inc. and the Swift.org project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Swift.org project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

package org.swift.swiftkit;

import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;

import com.example.swift.generated.MySwiftClass;

public class JavaToSwiftBenchmark {

@State(Scope.Benchmark)
public static class BenchmarkState {
MySwiftClass obj;

@Setup(Level.Trial)
public void beforeALl() {
System.loadLibrary("swiftCore");
System.loadLibrary("ExampleSwiftLibrary");

// Tune down debug statements so they don't fill up stdout
System.setProperty("jextract.trace.downcalls", "false");

obj = new MySwiftClass(1, 2);
}
}

@Benchmark @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS)
public void simpleSwiftApiCall(BenchmarkState state, Blackhole blackhole) {
blackhole.consume(state.obj.makeRandomIntMethod());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@

package org.swift.swiftkit;

import com.example.swift.generated.MySwiftClass;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import com.example.swift.generated.MySwiftClass;

public class MySwiftClassTest {

Expand Down
4 changes: 4 additions & 0 deletions Sources/ExampleSwiftLibrary/MySwiftLibrary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ public class MySwiftClass {
p("make int -> 12")
return 12
}

public func makeRandomIntMethod() -> Int {
return Int.random(in: 1..<256)
}
}

@_silgen_name("swift_getTypeByMangledNameInEnvironment")
Expand Down
Loading