mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Add Swift Benchmark Suite
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -28,9 +28,6 @@ cscope.out
|
||||
#==============================================================================#
|
||||
# Directories to ignore (do not add trailing '/'s, they skip symlinks).
|
||||
#==============================================================================#
|
||||
# Swift performance test suite.
|
||||
benchmark/PerfTestSuite
|
||||
|
||||
# Generated docs
|
||||
docs/_build
|
||||
|
||||
|
||||
@@ -660,7 +660,7 @@ if(SWIFT_BUILD_TOOLS)
|
||||
endif()
|
||||
add_subdirectory(utils)
|
||||
add_subdirectory(stdlib)
|
||||
if(SWIFT_BUILD_PERF_TESTSUITE)
|
||||
if(SWIFT_BUILD_PERF_TESTSUITE AND "${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||
add_subdirectory(benchmark)
|
||||
endif()
|
||||
if(SWIFT_INCLUDE_TESTS)
|
||||
|
||||
@@ -1,10 +1,211 @@
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
# Performance test harness only builds on Darwin.
|
||||
set(PERF_TESTSUITE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/PerfTestSuite" CACHE STRING "Path to swift performance testsuite repo.")
|
||||
if(EXISTS ${PERF_TESTSUITE_DIR}/CMakeLists.txt)
|
||||
add_subdirectory(${PERF_TESTSUITE_DIR})
|
||||
else()
|
||||
message(FATAL_ERROR "Can't find the Swift performance suite at ${PERF_TESTSUITE_DIR}/.")
|
||||
endif()
|
||||
# -*- mode: cmake -*-
|
||||
################################################################################
|
||||
# WARNING: This file is automatically generated from templates and should not
|
||||
# be directly modified. Instead, make changes to
|
||||
# scripts/generate_harness/CMakeLists.txt_template and run
|
||||
# scripts/generate_harness/generate_harness.py to regenerate this file.
|
||||
################################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
# Add path for custom CMake modules.
|
||||
list(APPEND CMAKE_MODULE_PATH
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
|
||||
|
||||
include(add-swift-benchmark-suite)
|
||||
|
||||
set(SWIFT_BENCH_MODULES
|
||||
Ackermann
|
||||
AngryPhonebook
|
||||
Array2D
|
||||
ArrayAppend
|
||||
ArrayInClass
|
||||
ArrayLiteral
|
||||
ArrayOfGenericPOD
|
||||
ArrayOfGenericRef
|
||||
ArrayOfPOD
|
||||
ArrayOfRef
|
||||
ArraySubscript
|
||||
BitCount
|
||||
ByteSwap
|
||||
Calculator
|
||||
CaptureProp
|
||||
Chars
|
||||
ClassArrayGetter
|
||||
DeadArray
|
||||
DictionaryBridge
|
||||
DictionaryLiteral
|
||||
DictionaryRemove
|
||||
DictionarySwap
|
||||
DictTest
|
||||
DictTest2
|
||||
DictTest3
|
||||
ErrorHandling
|
||||
Fibonacci
|
||||
GlobalClass
|
||||
Hanoi
|
||||
Hash
|
||||
Histogram
|
||||
Join
|
||||
LinkedList
|
||||
MapReduce
|
||||
Memset
|
||||
MonteCarloE
|
||||
MonteCarloPi
|
||||
NopDeinit
|
||||
NSDictionaryCastToSwift
|
||||
NSError
|
||||
NSStringConversion
|
||||
ObjectAllocation
|
||||
OpenClose
|
||||
Phonebook
|
||||
PolymorphicCalls
|
||||
PopFront
|
||||
PopFrontGeneric
|
||||
Prims
|
||||
ProtocolDispatch
|
||||
RangeAssignment
|
||||
RC4
|
||||
RecursiveOwnedParameter
|
||||
RGBHistogram
|
||||
SetTests
|
||||
SevenBoom
|
||||
Sim2DArray
|
||||
SortLettersInPlace
|
||||
SortStrings
|
||||
StrComplexWalk
|
||||
StringBuilder
|
||||
StringInterpolation
|
||||
StringTests
|
||||
StringWalk
|
||||
StrToInt
|
||||
SuperChars
|
||||
TwoSum
|
||||
Walsh
|
||||
XorLoop
|
||||
)
|
||||
|
||||
set(SWIFT_MULTISOURCE_BENCHES
|
||||
)
|
||||
|
||||
|
||||
set(BENCH_DRIVER_LIBRARY_MODULES
|
||||
DriverUtils
|
||||
TestsUtils
|
||||
)
|
||||
|
||||
set(BENCH_DRIVER_LIBRARY_FLAGS)
|
||||
if (SWIFT_RUNTIME_ENABLE_LEAK_CHECKER)
|
||||
set(BENCH_DRIVER_LIBRARY_FLAGS -DSWIFT_RUNTIME_ENABLE_LEAK_CHECKER)
|
||||
endif()
|
||||
|
||||
set(BENCH_LIBRARY_MODULES
|
||||
)
|
||||
|
||||
add_definitions(-DSWIFT_EXEC -DSWIFT_LIBRARY_PATH -DONLY_PLATFORMS
|
||||
-DSWIFT_OPTIMIZATION_LEVELS -DSWIFT_BENCHMARK_EMIT_SIB)
|
||||
|
||||
if(NOT ONLY_PLATFORMS)
|
||||
set(ONLY_PLATFORMS "macosx" "iphoneos" "appletvos" "watchos")
|
||||
endif()
|
||||
|
||||
if(NOT SWIFT_EXEC)
|
||||
runcmd(COMMAND "xcrun" "-f" "swiftc"
|
||||
VARIABLE SWIFT_EXEC
|
||||
ERROR "Unable to find Swift driver")
|
||||
endif()
|
||||
|
||||
if(NOT SWIFT_LIBRARY_PATH)
|
||||
get_filename_component(tmp_dir "${SWIFT_EXEC}" DIRECTORY)
|
||||
get_filename_component(tmp_dir "${tmp_dir}" DIRECTORY)
|
||||
set(SWIFT_LIBRARY_PATH "${tmp_dir}/lib/swift")
|
||||
endif()
|
||||
|
||||
runcmd(COMMAND "xcrun" "-f" "clang"
|
||||
VARIABLE CLANG_EXEC
|
||||
ERROR "Unable to find Clang driver")
|
||||
|
||||
# You have to delete CMakeCache.txt in the swift build to force a
|
||||
# reconfiguration.
|
||||
set(SWIFT_EXTRA_BENCH_CONFIGS CACHE STRING
|
||||
"A semicolon separated list of benchmark configurations. \
|
||||
Available configurations: <Optlevel>_SINGLEFILE, <Optlevel>_MULTITHREADED")
|
||||
|
||||
# Syntax for an optset: <optimization-level>_<configuration>
|
||||
# where "_<configuration>" is optional.
|
||||
if(NOT SWIFT_OPTIMIZATION_LEVELS)
|
||||
set(SWIFT_OPTIMIZATION_LEVELS "Onone" "O" "Ounchecked"
|
||||
${SWIFT_EXTRA_BENCH_CONFIGS})
|
||||
endif()
|
||||
|
||||
# Options for the default (= empty) configuration
|
||||
set(BENCHOPTS "-whole-module-optimization")
|
||||
|
||||
# Options for other configurations
|
||||
set(BENCHOPTS_MULTITHREADED
|
||||
"-whole-module-optimization" "-num-threads" "4")
|
||||
set(BENCHOPTS_SINGLEFILE "")
|
||||
|
||||
set(macosx_arch "x86_64")
|
||||
set(iphoneos_arch "arm64" "armv7")
|
||||
set(appletvos_arch "arm64")
|
||||
set(watchos_arch "armv7k")
|
||||
|
||||
set(macosx_ver "10.9")
|
||||
set(iphoneos_ver "8.0")
|
||||
set(appletvos_ver "9.1")
|
||||
set(watchos_ver "2.0")
|
||||
|
||||
set(macosx_triple_platform "macosx")
|
||||
set(iphoneos_triple_platform "ios")
|
||||
set(appletvos_triple_platform "tvos")
|
||||
set(watchos_triple_platform "watchos")
|
||||
|
||||
set(sdks)
|
||||
set(platforms)
|
||||
foreach(platform ${ONLY_PLATFORMS})
|
||||
execute_process(
|
||||
COMMAND "xcrun" "--sdk" "${platform}" "--show-sdk-path"
|
||||
OUTPUT_VARIABLE ${platform}_sdk
|
||||
RESULT_VARIABLE result
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if("${result}" MATCHES "0")
|
||||
list(APPEND sdks "${${platform}_sdk}")
|
||||
list(APPEND platforms ${platform})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
message("--")
|
||||
message("-- Swift Benchmark Suite:")
|
||||
message("-- SWIFT_EXEC = ${SWIFT_EXEC}")
|
||||
message("-- SWIFT_LIBRARY_PATH = ${SWIFT_LIBRARY_PATH}")
|
||||
message("-- CLANG_EXEC = ${CLANG_EXEC}")
|
||||
message("-- SWIFT_OPTIMIZATION_LEVELS = ${SWIFT_OPTIMIZATION_LEVELS}")
|
||||
message("-- ONLY_PLATFORMS = ${ONLY_PLATFORMS}")
|
||||
|
||||
message("-- found platforms: ${platforms}")
|
||||
message("-- found sdks:")
|
||||
foreach(sdk ${sdks})
|
||||
message("-- ${sdk}")
|
||||
endforeach()
|
||||
|
||||
set(executable_targets)
|
||||
|
||||
set(srcdir "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(bindir "${CMAKE_CURRENT_BINARY_DIR}/bin")
|
||||
set(libdir "${CMAKE_CURRENT_BINARY_DIR}/lib")
|
||||
set(libswiftdir "${CMAKE_CURRENT_BINARY_DIR}/lib/swift")
|
||||
file(MAKE_DIRECTORY "${bindir}")
|
||||
file(MAKE_DIRECTORY "${libdir}")
|
||||
file(MAKE_DIRECTORY "${libswiftdir}")
|
||||
|
||||
if(SWIFT_SDKS)
|
||||
set(IS_SWIFT_BUILD true)
|
||||
endif()
|
||||
|
||||
# Compile the perf test suite for each platform
|
||||
foreach(platform ${platforms})
|
||||
swift_benchmark_compile(PLATFORM ${platform})
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(scripts)
|
||||
203
benchmark/README.md
Normal file
203
benchmark/README.md
Normal file
@@ -0,0 +1,203 @@
|
||||
Swift Benchmark Suite
|
||||
=====================
|
||||
|
||||
This directory contains the Swift Benchmark Suite.
|
||||
|
||||
Running Swift Benchmarks
|
||||
------------------------
|
||||
|
||||
To run Swift benchmarks, pass the `--benchmark` flag to `build-script`. The
|
||||
current benchmark results will be compared to the previous run's results if
|
||||
available. Results for each benchmark run are logged for future comparison.
|
||||
|
||||
For branch based development, take a baseline benchmark on the Swift `master`
|
||||
branch, switch to a development branch containing potentially performance
|
||||
impacting changes, and run the benchmarks again. Upon benchmark completion, the
|
||||
benchmark results for the development branch will be compared to the most
|
||||
recent benchmark results for `master`.
|
||||
|
||||
Building with build-script
|
||||
--------------------------
|
||||
|
||||
By default, Swift benchmarks for OS X are compiled during the Swift build
|
||||
process. To build Swift benchmarks for additional platforms, pass the following
|
||||
flags:
|
||||
|
||||
$ swift/utils/build-script --ios --watchos --tvos
|
||||
|
||||
OS X benchmark driver binaries are placed in `bin` alongside `swiftc`.
|
||||
Additional platform binaries are placed in the `benchmark/bin` build directory.
|
||||
|
||||
Building Independently
|
||||
----------------------
|
||||
|
||||
To build the Swift benchmarks using only an Xcode installation: install an
|
||||
Xcode version with Swift support, install cmake 2.8.12, and ensure Xcode is
|
||||
selected with xcode-select.
|
||||
|
||||
The following build options are available:
|
||||
|
||||
* `-DSWIFT_EXEC`
|
||||
* An absolute path to the Swift driver (`swiftc`) to use to compile the
|
||||
benchmarks (default: Xcode's `swiftc`)
|
||||
* `-DSWIFT_LIBRARY_PATH`
|
||||
* An absolute path to the Swift standard library to use during compilation
|
||||
(default: `swiftc_directory`/../lib/swift)
|
||||
* `-DONLY_PLATFORMS`
|
||||
* A list of platforms to build the benchmarks for
|
||||
(default: "macosx;iphoneos;appletvos;watchos")
|
||||
* `-DSWIFT_OPTIMIZATION_LEVELS`
|
||||
* A list of Swift optimization levels to build against
|
||||
(default: "O;Onone;Ounchecked")
|
||||
* `-DSWIFT_BENCHMARK_EMIT_SIB`
|
||||
* A boolean value indicating whether .sib files should be generated
|
||||
alongside .o files (default: FALSE)
|
||||
|
||||
The following build targets are available:
|
||||
|
||||
1. `swift-benchmark-macosx-x86_64`
|
||||
2. `swift-benchmark-iphoneos-arm64`
|
||||
3. `swift-benchmark-iphoneos-armv7`
|
||||
4. `swift-benchmark-appletvos-arm64`
|
||||
5. `swift-benchmark-watchos-armv7k`
|
||||
|
||||
Build steps (with example options):
|
||||
|
||||
1. `$ cd benchmark`
|
||||
2. `$ mkdir build`
|
||||
3. `$ cd build`
|
||||
4. `$ cmake ..`
|
||||
5. `$ make -j8 swift-benchmark-macosx-x86_64`
|
||||
|
||||
Benchmark driver binaries are placed in `build/bin` and the required Swift
|
||||
standard library dylibs are placed in `build/lib`. The drivers dynamically link
|
||||
Swift standard library dylibs from a path relative to their location
|
||||
(../lib/swift) so the standard library should be distributed alongside them.
|
||||
|
||||
Using the Benchmark Driver
|
||||
--------------------------
|
||||
|
||||
### Usage
|
||||
|
||||
`./Driver [ test_name [ test_name ] ] [ option [ option ] ]`
|
||||
|
||||
* `--num-iters`
|
||||
* Control the number of loop iterations in each test sample
|
||||
* `--num-samples`
|
||||
* Control the number of samples to take for each test
|
||||
* `--list`
|
||||
* Print a list of available tests
|
||||
|
||||
### Examples
|
||||
|
||||
1. `$ ./Benchmark_O --num-iters=1 --num-samples=1`
|
||||
2. `$ ./Benchmark_Onone --list`
|
||||
3. `$ ./Benchmark_Ounchecked Ackermann`
|
||||
|
||||
Using the Harness Generator
|
||||
---------------------------
|
||||
|
||||
`scripts/generate_harness/generate_harness.py` generates and replaces
|
||||
`CMakeLists.txt` and `utils/main.swift` from single and multiple file tests
|
||||
contained in the directories `single-source` and `multi-source`. It gathers
|
||||
information about the tests and then generates the files from templates using
|
||||
jinja2. The motivation for creating this script was to eliminate the need to
|
||||
manually add atleast three lines to harness files (one to `CMakeLists.txt` and
|
||||
two to `utils/main.swift`) for every new benchmark added.
|
||||
|
||||
**Warning:**
|
||||
|
||||
Since `CMakeLists.txt` and `utils/main.swift` are now generated from templates,
|
||||
they should not be directly modified. Work may be lost if the harness is
|
||||
executed after making changes to derived files. Instead, modifications should
|
||||
be made to the template files stored in the `scripts/generate_harness`
|
||||
directory.
|
||||
|
||||
### Generating harness files
|
||||
|
||||
Start by installing jinja2 if it isn't already installed:
|
||||
|
||||
$ sudo easy_install -U jinja2
|
||||
|
||||
To generate `CMakeLists.txt` and `utils/main.swift` from test sources, run the
|
||||
command:
|
||||
|
||||
$ scripts/generate_harness/generate_harness.py
|
||||
|
||||
**Note:**
|
||||
|
||||
Ensure `generate_harness.py` remains in `scripts/generate_harness` as it
|
||||
modifies files relative to its location instead of the current working
|
||||
directory.
|
||||
|
||||
### Modifying CMakeLists.txt or utils/main.swift
|
||||
|
||||
To make changes to `CMakeLists.txt` or `utils/main.swift`, modify the template
|
||||
files `CMakeLists.txt_template` and `main.swift_template` stored in the
|
||||
`scripts/generate_harness` directory. These are jinja2 templates, rendered by
|
||||
jinja2 calls in `generate_harness.py`, so ensure static changes don't interfere
|
||||
with the template portions. Test changes by regenerating the harness
|
||||
(*Generating harness files*) and rebuilding the repository with `build-script`.
|
||||
|
||||
Adding New Benchmarks
|
||||
---------------------
|
||||
|
||||
The harness generator supports both single and multiple file tests.
|
||||
|
||||
To add a new single file test:
|
||||
|
||||
1. Add a new Swift file (`YourTestNameHere.swift`), built according to
|
||||
the template below, to the `single-source` directory.
|
||||
2. Regenerate harness files by following the directions in
|
||||
*Generating harness files* before committing changes.
|
||||
|
||||
To add a new multiple file test:
|
||||
|
||||
1. Add a new directory and files under the `multi-source` directory as
|
||||
specified below:
|
||||
|
||||
├── multi-source
|
||||
│ ├── YourTestName
|
||||
│ │ ├── TestFile1.swift
|
||||
│ │ ├── TestFile2.swift
|
||||
│ │ ├── TestFile3.swift
|
||||
|
||||
Atleast one run function (specified in the template below) must
|
||||
exist in the files.
|
||||
|
||||
2. Regenerate harness files by following the directions in
|
||||
*Generating harness files* before committing changes.
|
||||
|
||||
**Note:**
|
||||
|
||||
The generator script looks for functions prefixed with `run_` in order to
|
||||
populate `utils/main.swift`.
|
||||
|
||||
Each iteration of work performed in the for-loop below should run in under a
|
||||
few milliseconds. The benchmark driver will automatically calculate the
|
||||
necessary number of iterations to run each benchmark in approximately one
|
||||
second.
|
||||
|
||||
**Performance Test Template**
|
||||
|
||||
``` {.sourceCode .swift}
|
||||
// YourTestNameHere benchmark
|
||||
//
|
||||
// rdar://problem/00000000
|
||||
import Foundation
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_YourTestNameHere(N: Int) {
|
||||
# Declare variables
|
||||
|
||||
for i in 1...N {
|
||||
# Perform work
|
||||
|
||||
# Verify work was done; break otherwise
|
||||
}
|
||||
|
||||
# Assert with CheckResults that work was done
|
||||
}
|
||||
```
|
||||
|
||||
356
benchmark/cmake/modules/add-swift-benchmark-suite.cmake
Normal file
356
benchmark/cmake/modules/add-swift-benchmark-suite.cmake
Normal file
@@ -0,0 +1,356 @@
|
||||
|
||||
include(CMakeParseArguments)
|
||||
|
||||
|
||||
# Run a shell command and assign output to a variable or fail with an error.
|
||||
# Example usage:
|
||||
# runcmd(COMMAND "xcode-select" "-p"
|
||||
# VARIABLE xcodepath
|
||||
# ERROR "Unable to find current Xcode path")
|
||||
function(runcmd)
|
||||
cmake_parse_arguments(RUNCMD "" "VARIABLE;ERROR" "COMMAND" ${ARGN})
|
||||
execute_process(
|
||||
COMMAND ${RUNCMD_COMMAND}
|
||||
OUTPUT_VARIABLE ${RUNCMD_VARIABLE}
|
||||
RESULT_VARIABLE result
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT "${result}" MATCHES "0")
|
||||
message(FATAL_ERROR "${RUNCMD_ERROR}")
|
||||
endif()
|
||||
set(${RUNCMD_VARIABLE} ${${RUNCMD_VARIABLE}} PARENT_SCOPE)
|
||||
endfunction(runcmd)
|
||||
|
||||
|
||||
function(swift_benchmark_compile)
|
||||
cmake_parse_arguments(SWIFT_BENCHMARK_COMPILE "" "PLATFORM" "" ${ARGN})
|
||||
if(IS_SWIFT_BUILD)
|
||||
set(stdlib_dependencies "swift"
|
||||
${UNIVERSAL_LIBRARY_NAMES_${SWIFT_BENCHMARK_COMPILE_PLATFORM}})
|
||||
endif()
|
||||
|
||||
add_custom_target("copy-swift-stdlib-${SWIFT_BENCHMARK_COMPILE_PLATFORM}"
|
||||
DEPENDS ${stdlib_dependencies}
|
||||
COMMAND
|
||||
"${CMAKE_COMMAND}" "-E" "copy_directory"
|
||||
"${SWIFT_LIBRARY_PATH}/${SWIFT_BENCHMARK_COMPILE_PLATFORM}"
|
||||
"${libswiftdir}/${SWIFT_BENCHMARK_COMPILE_PLATFORM}")
|
||||
|
||||
add_custom_target("adhoc-sign-swift-stdlib-${SWIFT_BENCHMARK_COMPILE_PLATFORM}"
|
||||
DEPENDS "copy-swift-stdlib-${SWIFT_BENCHMARK_COMPILE_PLATFORM}"
|
||||
COMMAND
|
||||
"codesign" "-f" "-s" "-"
|
||||
"${libswiftdir}/${SWIFT_BENCHMARK_COMPILE_PLATFORM}/*.dylib" "2>/dev/null")
|
||||
|
||||
set(platform_executables)
|
||||
foreach(arch ${${SWIFT_BENCHMARK_COMPILE_PLATFORM}_arch})
|
||||
foreach(optset ${SWIFT_OPTIMIZATION_LEVELS})
|
||||
set(sdk ${${SWIFT_BENCHMARK_COMPILE_PLATFORM}_sdk})
|
||||
set(ver ${${SWIFT_BENCHMARK_COMPILE_PLATFORM}_ver})
|
||||
set(triple_platform ${${SWIFT_BENCHMARK_COMPILE_PLATFORM}_triple_platform})
|
||||
|
||||
set(target "${arch}-apple-${triple_platform}${ver}")
|
||||
|
||||
set(objdir "${CMAKE_CURRENT_BINARY_DIR}/${optset}-${target}")
|
||||
file(MAKE_DIRECTORY "${objdir}")
|
||||
|
||||
string(REGEX REPLACE "_.*" "" optflag "${optset}")
|
||||
string(REGEX REPLACE "^[^_]+" "" opt_suffix "${optset}")
|
||||
|
||||
set(benchvar "BENCHOPTS${opt_suffix}")
|
||||
if (NOT DEFINED ${benchvar})
|
||||
message(FATAL_ERROR "Invalid benchmark configuration ${optset}")
|
||||
endif()
|
||||
|
||||
set(bench_flags "${${benchvar}}")
|
||||
|
||||
set(common_options
|
||||
"-c"
|
||||
"-sdk" "${sdk}"
|
||||
"-target" "${target}"
|
||||
"-F" "${sdk}/../../../Developer/Library/Frameworks"
|
||||
"-${optset}"
|
||||
"-D" "INTERNAL_CHECKS_ENABLED"
|
||||
"-D" "SWIFT_ENABLE_OBJECT_LITERALS"
|
||||
"-no-link-objc-runtime")
|
||||
|
||||
# Always optimize the driver modules.
|
||||
# Note that we compile the driver for Ounchecked also with -Ounchecked
|
||||
# (and not with -O), because of <rdar://problem/19614516>.
|
||||
string(REPLACE "Onone" "O" driver_opt "${optflag}")
|
||||
|
||||
set(common_options_driver
|
||||
"-c"
|
||||
"-sdk" "${sdk}"
|
||||
"-target" "${target}"
|
||||
"-F" "${sdk}/../../../Developer/Library/Frameworks"
|
||||
"-${driver_opt}"
|
||||
"-D" "INTERNAL_CHECKS_ENABLED"
|
||||
"-D" "SWIFT_ENABLE_OBJECT_LITERALS"
|
||||
"-no-link-objc-runtime")
|
||||
|
||||
set(bench_library_objects)
|
||||
set(bench_library_sibfiles)
|
||||
foreach(module_name ${BENCH_DRIVER_LIBRARY_MODULES})
|
||||
if("${module_name}" STREQUAL "DriverUtils")
|
||||
set(extra_sources "${srcdir}/utils/ArgParse.swift")
|
||||
endif()
|
||||
|
||||
set(objfile "${objdir}/${module_name}.o")
|
||||
set(swiftmodule "${objdir}/${module_name}.swiftmodule")
|
||||
list(APPEND bench_library_objects "${objfile}")
|
||||
set(source "${srcdir}/utils/${module_name}.swift")
|
||||
add_custom_command(
|
||||
OUTPUT "${objfile}"
|
||||
DEPENDS ${stdlib_dependencies} "${source}" ${extra_sources}
|
||||
COMMAND "${SWIFT_EXEC}"
|
||||
${common_options_driver}
|
||||
${BENCH_DRIVER_LIBRARY_FLAGS}
|
||||
"-force-single-frontend-invocation"
|
||||
"-parse-as-library"
|
||||
"-module-name" "${module_name}"
|
||||
"-emit-module" "-emit-module-path" "${swiftmodule}"
|
||||
"-o" "${objfile}"
|
||||
"${source}" ${extra_sources})
|
||||
if(SWIFT_BENCHMARK_EMIT_SIB)
|
||||
set(sibfile "${objdir}/${module_name}.sib")
|
||||
list(APPEND bench_library_sibfiles "${sibfile}")
|
||||
add_custom_command(
|
||||
OUTPUT "${sibfile}"
|
||||
DEPENDS
|
||||
${stdlib_dependencies} "${srcdir}/utils/${module_name}.swift"
|
||||
${extra_sources}
|
||||
COMMAND "${SWIFT_EXEC}"
|
||||
${common_options_driver}
|
||||
${BENCH_DRIVER_LIBRARY_FLAGS}
|
||||
"-force-single-frontend-invocation"
|
||||
"-parse-as-library"
|
||||
"-module-name" "${module_name}"
|
||||
"-emit-sib"
|
||||
"-o" "${sibfile}"
|
||||
"${srcdir}/utils/${module_name}.swift" ${extra_sources})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(module_name ${BENCH_LIBRARY_MODULES})
|
||||
set(objfile "${objdir}/${module_name}.o")
|
||||
set(swiftmodule "${objdir}/${module_name}.swiftmodule")
|
||||
list(APPEND bench_library_objects "${objfile}")
|
||||
add_custom_command(
|
||||
OUTPUT "${objfile}"
|
||||
DEPENDS
|
||||
${stdlib_dependencies} "${srcdir}/utils/${module_name}.swift"
|
||||
${extra_sources}
|
||||
COMMAND "${SWIFT_EXEC}"
|
||||
${common_options}
|
||||
"-force-single-frontend-invocation"
|
||||
"-parse-as-library"
|
||||
"-module-name" "${module_name}"
|
||||
"-emit-module" "-emit-module-path" "${swiftmodule}"
|
||||
"-o" "${objfile}"
|
||||
"${srcdir}/utils/${module_name}.swift" ${extra_sources})
|
||||
if (SWIFT_BENCHMARK_EMIT_SIB)
|
||||
set(sibfile "${objdir}/${module_name}.sib")
|
||||
list(APPEND bench_library_sibfiles "${sibfile}")
|
||||
add_custom_command(
|
||||
OUTPUT "${sibfile}"
|
||||
DEPENDS
|
||||
${stdlib_dependencies} "${srcdir}/utils/${module_name}.swift"
|
||||
${extra_sources}
|
||||
COMMAND "${SWIFT_EXEC}"
|
||||
${common_options}
|
||||
"-force-single-frontend-invocation"
|
||||
"-parse-as-library"
|
||||
"-module-name" "${module_name}"
|
||||
"-emit-sib"
|
||||
"-o" "${sibfile}"
|
||||
"${srcdir}/utils/${module_name}.swift" ${extra_sources})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(SWIFT_BENCH_OBJFILES)
|
||||
set(SWIFT_BENCH_SIBFILES)
|
||||
foreach(module_name ${SWIFT_BENCH_MODULES})
|
||||
if(module_name)
|
||||
set(objfile "${objdir}/${module_name}.o")
|
||||
set(swiftmodule "${objdir}/${module_name}.swiftmodule")
|
||||
list(APPEND SWIFT_BENCH_OBJFILES "${objfile}")
|
||||
add_custom_command(
|
||||
OUTPUT "${objfile}"
|
||||
DEPENDS
|
||||
${stdlib_dependencies} ${bench_library_objects}
|
||||
"${srcdir}/single-source/${module_name}.swift"
|
||||
COMMAND "${SWIFT_EXEC}"
|
||||
${common_options}
|
||||
"-parse-as-library"
|
||||
${bench_flags}
|
||||
"-module-name" "${module_name}"
|
||||
"-emit-module" "-emit-module-path" "${swiftmodule}"
|
||||
"-I" "${objdir}"
|
||||
"-o" "${objfile}"
|
||||
"${srcdir}/single-source/${module_name}.swift")
|
||||
if (SWIFT_BENCHMARK_EMIT_SIB)
|
||||
set(sibfile "${objdir}/${module_name}.sib")
|
||||
list(APPEND SWIFT_BENCH_SIBFILES "${sibfile}")
|
||||
add_custom_command(
|
||||
OUTPUT "${sibfile}"
|
||||
DEPENDS
|
||||
${stdlib_dependencies} ${bench_library_sibfiles}
|
||||
"${srcdir}/single-source/${module_name}.swift"
|
||||
COMMAND "${SWIFT_EXEC}"
|
||||
${common_options}
|
||||
"-parse-as-library"
|
||||
${bench_flags}
|
||||
"-module-name" "${module_name}"
|
||||
"-I" "${objdir}"
|
||||
"-emit-sib"
|
||||
"-o" "${sibfile}"
|
||||
"${srcdir}/single-source/${module_name}.swift")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(module_name ${SWIFT_MULTISOURCE_BENCHES})
|
||||
if ("${bench_flags}" MATCHES "-whole-module.*" AND
|
||||
NOT "${bench_flags}" MATCHES "-num-threads.*")
|
||||
# Regular whole-module-compilation: only a single object file is
|
||||
# generated.
|
||||
set(objfile "${objdir}/${module_name}.o")
|
||||
list(APPEND SWIFT_BENCH_OBJFILES "${objfile}")
|
||||
set(sources)
|
||||
foreach(source ${${module_name}_sources})
|
||||
list(APPEND sources "${srcdir}/multi-source/${source}")
|
||||
endforeach()
|
||||
add_custom_command(
|
||||
OUTPUT "${objfile}"
|
||||
DEPENDS
|
||||
${stdlib_dependencies} ${bench_library_objects} ${sources}
|
||||
COMMAND "${SWIFT_EXEC}"
|
||||
${common_options}
|
||||
${bench_flags}
|
||||
"-parse-as-library"
|
||||
"-emit-module" "-module-name" "${module_name}"
|
||||
"-I" "${objdir}"
|
||||
"-o" "${objfile}"
|
||||
${sources})
|
||||
else()
|
||||
|
||||
# No whole-module-compilation or multi-threaded compilation.
|
||||
# There is an output object file for each input file. We have to write
|
||||
# an output-map-file to specify the output object file names.
|
||||
set(sources)
|
||||
set(objfiles)
|
||||
set(json "{\n")
|
||||
foreach(source ${${module_name}_sources})
|
||||
list(APPEND sources "${srcdir}/multi-source/${source}")
|
||||
|
||||
get_filename_component(basename "${source}" NAME_WE)
|
||||
set(objfile "${objdir}/${module_name}/${basename}.o")
|
||||
|
||||
string(CONCAT json "${json}"
|
||||
" \"${srcdir}/multi-source/${source}\": { \"object\": \"${objfile}\" },\n")
|
||||
|
||||
list(APPEND objfiles "${objfile}")
|
||||
list(APPEND SWIFT_BENCH_OBJFILES "${objfile}")
|
||||
endforeach()
|
||||
string(CONCAT json "${json}" "}")
|
||||
file(WRITE "${objdir}/${module_name}/outputmap.json" ${json})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${objfiles}
|
||||
DEPENDS
|
||||
${stdlib_dependencies} ${bench_library_objects} ${sources}
|
||||
COMMAND "${SWIFT_EXEC}"
|
||||
${common_options}
|
||||
${bench_flags}
|
||||
"-parse-as-library"
|
||||
"-module-name" "${module_name}"
|
||||
"-I" "${objdir}"
|
||||
"-output-file-map" "${objdir}/${module_name}/outputmap.json"
|
||||
${sources})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(module_name "main")
|
||||
set(source "${srcdir}/utils/${module_name}.swift")
|
||||
add_custom_command(
|
||||
OUTPUT "${objdir}/${module_name}.o"
|
||||
DEPENDS
|
||||
${stdlib_dependencies}
|
||||
${bench_library_objects} ${SWIFT_BENCH_OBJFILES}
|
||||
${bench_library_sibfiles} ${SWIFT_BENCH_SIBFILES} "${source}"
|
||||
COMMAND "${SWIFT_EXEC}"
|
||||
${common_options}
|
||||
"-force-single-frontend-invocation"
|
||||
"-emit-module" "-module-name" "${module_name}"
|
||||
"-I" "${objdir}"
|
||||
"-o" "${objdir}/${module_name}.o"
|
||||
"${source}")
|
||||
list(APPEND SWIFT_BENCH_OBJFILES "${objdir}/${module_name}.o")
|
||||
|
||||
if("${SWIFT_BENCHMARK_COMPILE_PLATFORM}" STREQUAL "macosx")
|
||||
set(OUTPUT_EXEC "${bindir}/Benchmark_${optset}")
|
||||
else()
|
||||
set(OUTPUT_EXEC "${bindir}/Benchmark_${optset}-${target}")
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${OUTPUT_EXEC}"
|
||||
DEPENDS
|
||||
${bench_library_objects} ${SWIFT_BENCH_OBJFILES}
|
||||
"adhoc-sign-swift-stdlib-${SWIFT_BENCHMARK_COMPILE_PLATFORM}"
|
||||
COMMAND
|
||||
"${CLANG_EXEC}"
|
||||
"-fno-stack-protector"
|
||||
"-fPIC"
|
||||
"-Werror=date-time"
|
||||
"-fcolor-diagnostics"
|
||||
"-O3"
|
||||
"-Wl,-search_paths_first"
|
||||
"-Wl,-headerpad_max_install_names"
|
||||
"-target" "${target}"
|
||||
"-isysroot" "${sdk}"
|
||||
"-arch" "${arch}"
|
||||
"-F" "${sdk}/../../../Developer/Library/Frameworks"
|
||||
"-m${triple_platform}-version-min=${ver}"
|
||||
"-lobjc"
|
||||
"-L${SWIFT_LIBRARY_PATH}/${SWIFT_BENCHMARK_COMPILE_PLATFORM}"
|
||||
"-Xlinker" "-rpath"
|
||||
"-Xlinker" "@executable_path/../lib/swift/${SWIFT_BENCHMARK_COMPILE_PLATFORM}"
|
||||
${bench_library_objects}
|
||||
${SWIFT_BENCH_OBJFILES}
|
||||
"-o" "${OUTPUT_EXEC}"
|
||||
COMMAND
|
||||
"codesign" "-f" "-s" "-" "${OUTPUT_EXEC}")
|
||||
|
||||
list(APPEND platform_executables "${OUTPUT_EXEC}")
|
||||
endforeach()
|
||||
|
||||
set(executable_target "swift-benchmark-${SWIFT_BENCHMARK_COMPILE_PLATFORM}-${arch}")
|
||||
|
||||
add_custom_target("${executable_target}"
|
||||
DEPENDS ${platform_executables})
|
||||
|
||||
if(IS_SWIFT_BUILD AND "${SWIFT_BENCHMARK_COMPILE_PLATFORM}" STREQUAL "macosx")
|
||||
add_custom_command(
|
||||
TARGET "${executable_target}"
|
||||
POST_BUILD
|
||||
COMMAND
|
||||
"mv" ${platform_executables} "${SWIFT_RUNTIME_OUTPUT_INTDIR}")
|
||||
|
||||
add_custom_target("check-${executable_target}"
|
||||
COMMAND "${SWIFT_RUNTIME_OUTPUT_INTDIR}/Benchmark_Driver" "run"
|
||||
"-o" "O" "--output-dir" "${CMAKE_CURRENT_BINARY_DIR}/logs"
|
||||
"--swift-repo" "${SWIFT_SOURCE_DIR}"
|
||||
"--iterations" "3"
|
||||
COMMAND "${SWIFT_RUNTIME_OUTPUT_INTDIR}/Benchmark_Driver" "run"
|
||||
"-o" "Onone" "--output-dir" "${CMAKE_CURRENT_BINARY_DIR}/logs"
|
||||
"--swift-repo" "${SWIFT_SOURCE_DIR}"
|
||||
"--iterations" "3"
|
||||
COMMAND "${SWIFT_RUNTIME_OUTPUT_INTDIR}/Benchmark_Driver" "compare"
|
||||
"--log-dir" "${CMAKE_CURRENT_BINARY_DIR}/logs"
|
||||
"--swift-repo" "${SWIFT_SOURCE_DIR}"
|
||||
"--compare-script"
|
||||
"${SWIFT_SOURCE_DIR}/benchmark/scripts/compare_perf_tests.py")
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
380
benchmark/scripts/Benchmark_Driver
Executable file
380
benchmark/scripts/Benchmark_Driver
Executable file
@@ -0,0 +1,380 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ===--- Benchmark_Driver -------------------------------------------------===//
|
||||
#
|
||||
# This source file is part of the Swift.org open source project
|
||||
#
|
||||
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
# Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
#
|
||||
# See http://swift.org/LICENSE.txt for license information
|
||||
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
#
|
||||
# ===----------------------------------------------------------------------===//
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import urllib2
|
||||
import urllib
|
||||
import datetime
|
||||
import argparse
|
||||
import time
|
||||
import glob
|
||||
|
||||
DRIVER_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
def parse_results(res, optset):
|
||||
# Parse lines like this
|
||||
# #,TEST,SAMPLES,MIN(μs),MAX(μs),MEAN(μs),SD(μs),MEDIAN(μs),PEAK_MEMORY(B)
|
||||
SCORERE = re.compile(r"(\d+),[ \t]*(\w+)," + \
|
||||
",".join([r"[ \t]*([\d.]+)"]*7))
|
||||
# The Totals line would be parsed like this.
|
||||
TOTALRE = re.compile(r"()(Totals)," + \
|
||||
",".join([r"[ \t]*([\d.]+)"]*7))
|
||||
KEYGROUP = 2
|
||||
VALGROUP = 4
|
||||
MEMGROUP = 9
|
||||
|
||||
tests = []
|
||||
for line in res.split():
|
||||
m = SCORERE.match(line)
|
||||
if not m:
|
||||
m = TOTALRE.match(line)
|
||||
if not m:
|
||||
continue
|
||||
testresult = int(m.group(VALGROUP))
|
||||
testname = m.group(KEYGROUP)
|
||||
test = {}
|
||||
test['Data'] = [testresult]
|
||||
test['Info'] = {}
|
||||
test['Name'] = "nts.swift/"+optset+"."+testname+".exec"
|
||||
tests.append(test)
|
||||
if testname != 'Totals':
|
||||
mem_testresult = int(m.group(MEMGROUP))
|
||||
mem_test = {}
|
||||
mem_test['Data'] = [mem_testresult]
|
||||
mem_test['Info'] = {}
|
||||
mem_test['Name'] = "nts.swift/mem_maxrss."+optset+"."+testname+".mem"
|
||||
tests.append(mem_test)
|
||||
return tests
|
||||
|
||||
def submit_to_LNT(data, url):
|
||||
print "\nSubmitting results to LNT server..."
|
||||
json_report = {'input_data': json.dumps(data), 'commit': '1'}
|
||||
data = urllib.urlencode(json_report)
|
||||
response_str = urllib2.urlopen(urllib2.Request(url, data))
|
||||
response = json.loads(response_str.read())
|
||||
if 'success' in response:
|
||||
print "Server response:\tSuccess"
|
||||
else:
|
||||
print "Server response:\tError"
|
||||
print "Error:\t", response['error']
|
||||
sys.exit(1)
|
||||
|
||||
def instrument_test(driver_path, test, num_samples):
|
||||
"""Run a test and instrument its peak memory use"""
|
||||
test_outputs = []
|
||||
for _ in range(num_samples):
|
||||
test_output_raw = subprocess.check_output(
|
||||
['time', '-lp', driver_path, test],
|
||||
stderr=subprocess.STDOUT
|
||||
)
|
||||
peak_memory = re.match('\s*(\d+)\s*maximum resident set size',
|
||||
test_output_raw.split('\n')[-15]).group(1)
|
||||
test_outputs.append(test_output_raw.split()[1].split(',') + \
|
||||
[peak_memory])
|
||||
|
||||
# Average sample results
|
||||
NUM_SAMPLES_INDEX = 2
|
||||
MIN_INDEX = 3
|
||||
MAX_INDEX = 4
|
||||
AVG_START_INDEX = 5
|
||||
|
||||
# TODO: Correctly take stdev
|
||||
avg_test_output = test_outputs[0]
|
||||
avg_test_output[AVG_START_INDEX:] = map(int,
|
||||
avg_test_output[AVG_START_INDEX:])
|
||||
for test_output in test_outputs[1:]:
|
||||
for i in range(AVG_START_INDEX, len(test_output)):
|
||||
avg_test_output[i] += int(test_output[i])
|
||||
for i in range(AVG_START_INDEX, len(avg_test_output)):
|
||||
avg_test_output[i] = int(round(avg_test_output[i] / \
|
||||
float(len(test_outputs))))
|
||||
avg_test_output[NUM_SAMPLES_INDEX] = num_samples
|
||||
avg_test_output[MIN_INDEX] = min(test_outputs,
|
||||
key=lambda x: x[MIN_INDEX])[MIN_INDEX]
|
||||
avg_test_output[MAX_INDEX] = max(test_outputs,
|
||||
key=lambda x: x[MAX_INDEX])[MAX_INDEX]
|
||||
avg_test_output = map(str, avg_test_output)
|
||||
|
||||
return avg_test_output
|
||||
|
||||
def get_tests(driver_path):
|
||||
"""Return a list of available performance tests"""
|
||||
return subprocess.check_output([driver_path, '--list']).split()[2:]
|
||||
|
||||
def get_current_git_branch(git_repo_path):
|
||||
"""Return the selected branch for the repo `git_repo_path`"""
|
||||
return subprocess.check_output(['git', '-C', git_repo_path, 'rev-parse',
|
||||
'--abbrev-ref', 'HEAD'], stderr=subprocess.STDOUT).strip()
|
||||
|
||||
def log_results(log_directory, driver, formatted_output, swift_repo=None):
|
||||
"""Log `formatted_output` to a branch specific directory in
|
||||
`log_directory`"""
|
||||
try:
|
||||
branch = get_current_git_branch(swift_repo)
|
||||
except:
|
||||
branch = None
|
||||
timestamp = time.strftime("%Y%m%d%H%M%S", time.localtime())
|
||||
if branch:
|
||||
output_directory = os.path.join(log_directory, branch)
|
||||
else:
|
||||
output_directory = log_directory
|
||||
driver_name = os.path.basename(driver)
|
||||
try:
|
||||
os.makedirs(output_directory)
|
||||
except:
|
||||
pass
|
||||
log_file = os.path.join(output_directory,
|
||||
driver_name + '-' + timestamp + '.log')
|
||||
print 'Logging results to: %s' % log_file
|
||||
with open(log_file, 'w') as f:
|
||||
f.write(formatted_output)
|
||||
|
||||
def run_benchmarks(driver, benchmarks=[], num_samples=10, verbose=False,
|
||||
log_directory=None, swift_repo=None):
|
||||
"""Run perf tests individually and return results in a format that's
|
||||
compatible with `parse_results`. If `benchmarks` is not empty,
|
||||
only run tests included in it."""
|
||||
(total_tests, total_min, total_max, total_mean) = (0, 0, 0, 0)
|
||||
output = []
|
||||
headings = ['#', 'TEST','SAMPLES','MIN(μs)','MAX(μs)','MEAN(μs)','SD(μs)',
|
||||
'MEDIAN(μs)','MAX_RSS(B)']
|
||||
line_format = '{:>3} {:<25} {:>7} {:>7} {:>7} {:>8} {:>6} {:>10} {:>10}'
|
||||
if verbose and log_directory:
|
||||
print line_format.format(*headings)
|
||||
for test in get_tests(driver):
|
||||
if benchmarks and test not in benchmarks:
|
||||
continue
|
||||
test_output = instrument_test(driver, test, num_samples)
|
||||
if test_output[0] == 'Totals':
|
||||
continue
|
||||
if verbose:
|
||||
if log_directory:
|
||||
print line_format.format(*test_output)
|
||||
else:
|
||||
print ','.join(test_output)
|
||||
output.append(test_output)
|
||||
(samples, _min, _max, mean) = map(int, test_output[2:6])
|
||||
total_tests += 1
|
||||
total_min += _min
|
||||
total_max += _max
|
||||
total_mean += mean
|
||||
if not output:
|
||||
return
|
||||
formatted_output = '\n'.join([','.join(l) for l in output])
|
||||
totals = map(str, ['Totals', total_tests, total_min, total_max,
|
||||
total_mean, '0', '0', '0'])
|
||||
totals_output = '\n\n' + ','.join(totals)
|
||||
if verbose:
|
||||
if log_directory:
|
||||
print line_format.format(*(['']+totals))
|
||||
else:
|
||||
print totals_output[1:]
|
||||
formatted_output += totals_output
|
||||
if log_directory:
|
||||
log_results(log_directory, driver, formatted_output, swift_repo)
|
||||
return formatted_output
|
||||
|
||||
def submit(args):
|
||||
print "SVN revision:\t", args.revision
|
||||
print "Machine name:\t", args.machine
|
||||
print "Iterations:\t", args.iterations
|
||||
print "Optimizations:\t", ','.join(args.optimization)
|
||||
print "LNT host:\t", args.lnt_host
|
||||
starttime = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
|
||||
print "Start time:\t", starttime
|
||||
data = {}
|
||||
data['Tests'] = []
|
||||
data['Machine'] = {'Info': {'name': args.machine}, 'Name': args.machine}
|
||||
print "\nRunning benchmarks..."
|
||||
for optset in args.optimization:
|
||||
print "Opt level:\t", optset
|
||||
file = os.path.join(args.tests, "Benchmark_"+optset)
|
||||
try:
|
||||
res = run_benchmarks(file, benchmarks=args.benchmark,
|
||||
num_samples=args.iterations)
|
||||
data['Tests'].extend(parse_results(res, optset))
|
||||
except subprocess.CalledProcessError as e:
|
||||
print "Execution failed.. Test results are empty."
|
||||
print "Process output:\n", e.output
|
||||
|
||||
endtime = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
|
||||
data['Run'] = {'End Time': endtime,
|
||||
'Info': {'inferred_run_order': str(args.revision),
|
||||
'run_order': str(args.revision),
|
||||
'tag': 'nts',
|
||||
'test_suite_revision': 'None'},
|
||||
'Start Time': starttime}
|
||||
print "End time:\t", endtime
|
||||
|
||||
submit_to_LNT(data, args.lnt_host)
|
||||
return 0
|
||||
|
||||
def run(args):
|
||||
optset = args.optimization
|
||||
file = os.path.join(args.tests, "Benchmark_"+optset)
|
||||
run_benchmarks(file, benchmarks=args.benchmarks,
|
||||
num_samples=args.iterations, verbose=True,
|
||||
log_directory=args.output_dir,
|
||||
swift_repo=args.swift_repo)
|
||||
return 0
|
||||
|
||||
def format_name(log_path):
|
||||
"""Return the filename and directory for a log file"""
|
||||
return '/'.join(log_path.split('/')[-2:])
|
||||
|
||||
def compare_logs(compare_script, new_log, old_log):
|
||||
"""Return diff of log files at paths `new_log` and `old_log`"""
|
||||
print 'Comparing %s %s ...' % (format_name(old_log), format_name(new_log))
|
||||
subprocess.call([compare_script, old_log, new_log])
|
||||
|
||||
def compare(args):
|
||||
log_dir = args.log_dir
|
||||
swift_repo = args.swift_repo
|
||||
compare_script = args.compare_script
|
||||
current_branch = get_current_git_branch(swift_repo)
|
||||
current_branch_dir = os.path.join(log_dir, current_branch)
|
||||
master_branch_dir = os.path.join(log_dir, 'master')
|
||||
|
||||
if current_branch != 'master' and not os.path.isdir(master_branch_dir):
|
||||
print 'Unable to find benchmark logs for master branch. Set a ' + \
|
||||
'baseline benchmark log by passing --benchmark to ' + \
|
||||
'build-script while on master branch.'
|
||||
return 1
|
||||
|
||||
recent_logs = {}
|
||||
for branch_dir in [current_branch_dir, master_branch_dir]:
|
||||
for opt in ['O', 'Onone']:
|
||||
recent_logs[os.path.basename(branch_dir) + '_' + opt] = \
|
||||
sorted(glob.glob(os.path.join(branch_dir,
|
||||
'Benchmark_' + opt + '-*.log')), key=os.path.getctime,
|
||||
reverse=True)
|
||||
|
||||
if current_branch == 'master':
|
||||
if len(recent_logs['master_O']) > 1 and \
|
||||
len(recent_logs['master_Onone']) > 1:
|
||||
compare_logs(compare_script,
|
||||
recent_logs['master_O'][0],
|
||||
recent_logs['master_O'][1])
|
||||
compare_logs(compare_script,
|
||||
recent_logs['master_Onone'][0],
|
||||
recent_logs['master_Onone'][1])
|
||||
else:
|
||||
print 'master/master comparison skipped: no previous master logs'
|
||||
else:
|
||||
# TODO: Check for outdated master branch log
|
||||
if len(recent_logs[current_branch + '_O']) == 0 or \
|
||||
len(recent_logs[current_branch + '_Onone']) == 0:
|
||||
print 'branch sanity failure: missing branch logs'
|
||||
return 1
|
||||
|
||||
if len(recent_logs[current_branch + '_O']) == 1 or \
|
||||
len(recent_logs[current_branch + '_Onone']) == 1:
|
||||
print 'branch/branch comparison skipped: no previous branch logs'
|
||||
else:
|
||||
compare_logs(compare_script,
|
||||
recent_logs[current_branch + '_O'][0],
|
||||
recent_logs[current_branch + '_O'][1])
|
||||
compare_logs(compare_script,
|
||||
recent_logs[current_branch + '_Onone'][0],
|
||||
recent_logs[current_branch + '_Onone'][1])
|
||||
|
||||
if len(recent_logs['master_O']) == 0 or \
|
||||
len(recent_logs['master_Onone']) == 0:
|
||||
print 'branch/master failure: no master logs'
|
||||
return 1
|
||||
else:
|
||||
compare_logs(compare_script,
|
||||
recent_logs[current_branch + '_O'][0],
|
||||
recent_logs['master_O'][0])
|
||||
compare_logs(compare_script,
|
||||
recent_logs[current_branch + '_Onone'][0],
|
||||
recent_logs['master_Onone'][0])
|
||||
|
||||
# TODO: Fail on large regressions
|
||||
|
||||
return 0
|
||||
|
||||
def positive_int(value):
|
||||
ivalue = int(value)
|
||||
if not (ivalue > 0):
|
||||
raise ValueError
|
||||
return ivalue
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Swift benchmarks driver')
|
||||
subparsers = parser.add_subparsers()
|
||||
|
||||
submit_parser = subparsers.add_parser('submit',
|
||||
help='run benchmarks and submit results to LNT')
|
||||
submit_parser.add_argument('-t', '--tests',
|
||||
help='directory containing Benchmark_O{,none,unchecked} ' + \
|
||||
'(default: DRIVER_DIR)',
|
||||
default=DRIVER_DIR)
|
||||
submit_parser.add_argument('-m', '--machine', required=True,
|
||||
help='LNT machine name')
|
||||
submit_parser.add_argument('-r', '--revision', required=True,
|
||||
help='SVN revision of compiler to identify the LNT run', type=int)
|
||||
submit_parser.add_argument('-l', '--lnt_host', required=True,
|
||||
help='LNT host to submit results to')
|
||||
submit_parser.add_argument('-i', '--iterations',
|
||||
help='number of times to run each test (default: 10)',
|
||||
type=positive_int, default=10)
|
||||
submit_parser.add_argument('-o', '--optimization', nargs='+',
|
||||
help='optimization levels to use (default: O Onone Ounchecked)',
|
||||
default=['O', 'Onone', 'Ounchecked'])
|
||||
submit_parser.add_argument('benchmark',
|
||||
help='benchmark to run (default: all)', nargs='*')
|
||||
submit_parser.set_defaults(func=submit)
|
||||
|
||||
run_parser = subparsers.add_parser('run',
|
||||
help='run benchmarks and output results to stdout')
|
||||
run_parser.add_argument('-t', '--tests',
|
||||
help='directory containing Benchmark_O{,none,unchecked} ' + \
|
||||
'(default: DRIVER_DIR)',
|
||||
default=DRIVER_DIR)
|
||||
run_parser.add_argument('-i', '--iterations',
|
||||
help='number of times to run each test (default: 1)',
|
||||
type=positive_int, default=1)
|
||||
run_parser.add_argument('-o', '--optimization',
|
||||
help='optimization level to use (default: O)', default='O')
|
||||
run_parser.add_argument('--output-dir',
|
||||
help='log results to directory (default: no logging)')
|
||||
run_parser.add_argument('--swift-repo',
|
||||
help='absolute path to Swift source repo for branch comparison')
|
||||
run_parser.add_argument('benchmarks',
|
||||
help='benchmark to run (default: all)', nargs='*')
|
||||
run_parser.set_defaults(func=run)
|
||||
|
||||
compare_parser = subparsers.add_parser('compare',
|
||||
help='compare benchmark results')
|
||||
compare_parser.add_argument('--log-dir', required=True,
|
||||
help='directory containing benchmark logs')
|
||||
compare_parser.add_argument('--swift-repo', required=True,
|
||||
help='absolute path to Swift source repo')
|
||||
compare_parser.add_argument('--compare-script', required=True,
|
||||
help='absolute path to compare script')
|
||||
compare_parser.set_defaults(func=compare)
|
||||
|
||||
args = parser.parse_args()
|
||||
if args.func != compare and isinstance(args.optimization, list):
|
||||
args.optimization = sorted(list(set(args.optimization)))
|
||||
return args.func(args)
|
||||
|
||||
if __name__ == '__main__':
|
||||
exit(main())
|
||||
60
benchmark/scripts/Benchmark_GuardMalloc.in
Normal file
60
benchmark/scripts/Benchmark_GuardMalloc.in
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# ===--- Benchmark_GuardMalloc.in -----------------------------------------===//
|
||||
#
|
||||
# This source file is part of the Swift.org open source project
|
||||
#
|
||||
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
# Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
#
|
||||
# See http://swift.org/LICENSE.txt for license information
|
||||
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
#
|
||||
# ===----------------------------------------------------------------------===//
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
sys.path.append("@PATH_TO_DRIVER_LIBRARY@")
|
||||
|
||||
import perf_test_driver
|
||||
|
||||
# Regexes for the XFAIL_LIST. Matches against '([Onone|O|Ounchecked],TestName)'
|
||||
XFAIL_LIST = [
|
||||
]
|
||||
|
||||
class GuardMallocResult(perf_test_driver.Result):
|
||||
|
||||
def __init__(self, name, status):
|
||||
perf_test_driver.Result.__init__(self, name, status, "", XFAIL_LIST)
|
||||
|
||||
class GuardMallocBenchmarkDriver(perf_test_driver.BenchmarkDriver):
|
||||
def __init__(self, binary, xfail_list):
|
||||
perf_test_driver.BenchmarkDriver.__init__(self, binary, xfail_list,
|
||||
enable_parallel=True)
|
||||
self.new_env = os.environ.copy()
|
||||
self.new_env['DYLD_INSERT_LIBRARIES'] = '/usr/lib/libgmalloc.dylib'
|
||||
|
||||
def prepare_input(self, name):
|
||||
return {'env': self.new_env}
|
||||
|
||||
def process_input(self, data):
|
||||
test_name = '({},{})'.format(data['opt'], data['test_name'])
|
||||
print "Running {}...".format(test_name)
|
||||
sys.stdout.flush()
|
||||
status = subprocess.call([data['path'], data['test_name'], '--num-iters=2'],
|
||||
env=data['env'],
|
||||
stderr=open('/dev/null', 'w'),
|
||||
stdout=open('/dev/null', 'w'))
|
||||
return GuardMallocResult(test_name, status)
|
||||
|
||||
SWIFT_BIN_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
if __name__ == "__main__":
|
||||
g = GuardMallocBenchmarkDriver(SWIFT_BIN_DIR, XFAIL_LIST)
|
||||
if g.run():
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(-1)
|
||||
|
||||
109
benchmark/scripts/Benchmark_RuntimeLeaksRunner.in
Normal file
109
benchmark/scripts/Benchmark_RuntimeLeaksRunner.in
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# ===--- Benchmark_RuntimeLeaksRunner.in ----------------------------------===//
|
||||
#
|
||||
# This source file is part of the Swift.org open source project
|
||||
#
|
||||
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
# Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
#
|
||||
# See http://swift.org/LICENSE.txt for license information
|
||||
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
#
|
||||
# ===----------------------------------------------------------------------===//
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
sys.path.append("@PATH_TO_DRIVER_LIBRARY@")
|
||||
|
||||
import perf_test_driver
|
||||
|
||||
# This is a hacked up XFAIL list. It should really be a json file, but it will
|
||||
# work for now. Add in the exact name of the pass to XFAIL.
|
||||
XFAIL_LIST = [
|
||||
]
|
||||
|
||||
# A list of Functions mapped to the number of globals in that function. These
|
||||
# show up as leaks. But we can count them, whitelist them, and then ignore them.
|
||||
FUNC_TO_GLOBAL_COUNTS = {
|
||||
'Ackermann': {"swift_count": 1, "objc_count": 0},
|
||||
'AngryPhonebook': {"swift_count": 1, "objc_count": 0},
|
||||
'GlobalClass': {'swift_count': 1, 'objc_count': 0},
|
||||
'Histogram': {'swift_count': 1, 'objc_count': 0},
|
||||
'Phonebook': {'swift_count': 1, 'objc_count': 0},
|
||||
'RC4': {'swift_count': 1, 'objc_count': 0},
|
||||
'RGBHistogram': {'swift_count': 1, 'objc_count': 0},
|
||||
'SortStrings': {'swift_count': 1, 'objc_count': 0},
|
||||
'TwoSum': {'swift_count': 1, 'objc_count': 0},
|
||||
}
|
||||
|
||||
# Global objective-c classes created by various frameworks. We do not care about these.
|
||||
IGNORABLE_GLOBAL_OBJC_CLASSES = set([
|
||||
'__NSPlaceholderDate',
|
||||
'NSCache',
|
||||
'__NSPlaceholderTimeZone',
|
||||
'NSPlaceholderNumber',
|
||||
'NSPlaceholderString',
|
||||
'__NSPlaceholderArray',
|
||||
'__NSPlaceholderDictionary',
|
||||
'_NSPlaceholderData',
|
||||
'_NSJSONReader'
|
||||
])
|
||||
|
||||
class LeaksRunnerResult(perf_test_driver.Result):
|
||||
|
||||
def __init__(self, name, status):
|
||||
perf_test_driver.Result.__init__(self, name, status, "", XFAIL_LIST)
|
||||
|
||||
class LeaksRunnerBenchmarkDriver(perf_test_driver.BenchmarkDriver):
|
||||
|
||||
def __init__(self, binary, xfail_list):
|
||||
perf_test_driver.BenchmarkDriver.__init__(self, binary, xfail_list,
|
||||
enable_parallel=True)
|
||||
def prepare_input(self, name):
|
||||
return {}
|
||||
|
||||
def process_input(self, data):
|
||||
test_name = '({},{})'.format(data['opt'], data['test_name'])
|
||||
print "Running {}...".format(test_name)
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
p = subprocess.Popen([data['path'], "--run-all", "--num-samples=2",
|
||||
"--num-iters={}".format(2), data['test_name']],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
status = p.wait()
|
||||
output = p.stdout.readlines()
|
||||
error_out = p.stderr.readlines()
|
||||
except:
|
||||
print("Child Process Failed! (%s,%s)" % (data['path'], data['test_name']))
|
||||
return LeaksRunnerResult(test_name, True)
|
||||
|
||||
try:
|
||||
# We grab the second line since swift globals get lazily created in the
|
||||
# first iteration.
|
||||
d = json.loads(error_out[1])
|
||||
d['objc_objects'] = [x for x in d['objc_objects'] if x not in IGNORABLE_GLOBAL_OBJC_CLASSES]
|
||||
d['objc_count'] = len(d['objc_objects'])
|
||||
|
||||
# Subtract out known global counts.
|
||||
if data['test_name'] in FUNC_TO_GLOBAL_COUNTS:
|
||||
d['swift_count'] -= FUNC_TO_GLOBAL_COUNTS[data['test_name']]['swift_count']
|
||||
d['objc_count'] -= FUNC_TO_GLOBAL_COUNTS[data['test_name']]['objc_count']
|
||||
|
||||
return LeaksRunnerResult(test_name, (d['objc_count'] + d['swift_count']) > 0)
|
||||
except:
|
||||
print "Failed parse output! (%s,%s)" % (data['path'], data['test_name'])
|
||||
return LeaksRunnerResult(test_name, True)
|
||||
|
||||
SWIFT_BIN_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
if __name__ == "__main__":
|
||||
l = LeaksRunnerBenchmarkDriver(SWIFT_BIN_DIR, XFAIL_LIST)
|
||||
if l.run():
|
||||
sys.exit(0)
|
||||
else:
|
||||
sys.exit(-1)
|
||||
26
benchmark/scripts/CMakeLists.txt
Normal file
26
benchmark/scripts/CMakeLists.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
set(PATH_TO_DRIVER_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/perf_test_driver")
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Benchmark_GuardMalloc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Benchmark_GuardMalloc
|
||||
@ONLY)
|
||||
configure_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Benchmark_RuntimeLeaksRunner.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Benchmark_RuntimeLeaksRunner
|
||||
@ONLY)
|
||||
set(PATH_TO_DRIVER_LIBRARY)
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_BINARY_DIR}/Benchmark_GuardMalloc
|
||||
DESTINATION ${CMAKE_BINARY_DIR}/bin
|
||||
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
|
||||
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_BINARY_DIR}/Benchmark_RuntimeLeaksRunner
|
||||
DESTINATION ${CMAKE_BINARY_DIR}/bin
|
||||
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
|
||||
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/Benchmark_Driver
|
||||
DESTINATION ${CMAKE_BINARY_DIR}/bin
|
||||
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ
|
||||
GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
196
benchmark/scripts/compare_perf_tests.py
Executable file
196
benchmark/scripts/compare_perf_tests.py
Executable file
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ===--- compare_perf_tests.py --------------------------------------------===//
|
||||
#
|
||||
# This source file is part of the Swift.org open source project
|
||||
#
|
||||
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
# Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
#
|
||||
# See http://swift.org/LICENSE.txt for license information
|
||||
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
#
|
||||
# ===----------------------------------------------------------------------===//
|
||||
|
||||
# e.g.
|
||||
# repeat.sh 3 tot/bin/Benchmark_Driver run -o -O > tot.O.times
|
||||
# repeat.sh 3 mypatch/bin/Benchmark_Driver run -o -O > mypatch.O.times
|
||||
# compare_perf_tests.py tot.O.times mypatch.O.times | sort -t, -n -k 6 | column -s, -t
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
|
||||
VERBOSE=0
|
||||
|
||||
# #,TEST,SAMPLES,MIN(ms),MAX(ms),MEAN(ms),SD(ms),MEDIAN(ms)
|
||||
SCORERE=re.compile(r"(\d+),[ \t]*(\w+),[ \t]*([\d.]+),[ \t]*([\d.]+)")
|
||||
TOTALRE=re.compile(r"()(Totals),[ \t]*([\d.]+),[ \t]*([\d.]+)")
|
||||
KEYGROUP=2
|
||||
VALGROUP=4
|
||||
NUMGROUP=1
|
||||
|
||||
IsTime=1
|
||||
ShowSpeedup=1
|
||||
PrintAllScores=0
|
||||
|
||||
def parseInt(word):
|
||||
try:
|
||||
return int(word)
|
||||
except:
|
||||
raise ScoreParserException("Expected integer value, not "+word)
|
||||
|
||||
def getScores(fname):
|
||||
scores = {}
|
||||
nums = {}
|
||||
runs = 0
|
||||
f = open(fname)
|
||||
try:
|
||||
for line in f:
|
||||
if VERBOSE: print "Parsing", line,
|
||||
m = SCORERE.match(line)
|
||||
is_total = False
|
||||
if not m:
|
||||
is_total = True
|
||||
m = TOTALRE.match(line)
|
||||
if not m:
|
||||
continue
|
||||
|
||||
if VERBOSE: print " match", m.group(KEYGROUP), m.group(VALGROUP)
|
||||
|
||||
if not m.group(KEYGROUP) in scores:
|
||||
scores[m.group(KEYGROUP)] = []
|
||||
scores[m.group(KEYGROUP)].append(parseInt(m.group(VALGROUP)))
|
||||
if is_total:
|
||||
nums[m.group(KEYGROUP)] = ""
|
||||
else:
|
||||
nums[m.group(KEYGROUP)] = m.group(NUMGROUP)
|
||||
if len(scores[m.group(KEYGROUP)]) > runs:
|
||||
runs = len(scores[m.group(KEYGROUP)])
|
||||
finally:
|
||||
f.close()
|
||||
return scores, runs, nums
|
||||
|
||||
def isMaxScore(newscore, maxscore, invert):
|
||||
return not maxscore or (newscore > maxscore if not invert else newscore < maxscore)
|
||||
|
||||
def compareScores(key, score1, score2, runs, num):
|
||||
print num.rjust(3),
|
||||
print key.ljust(25),
|
||||
bestscore1 = None
|
||||
bestscore2 = None
|
||||
worstscore1 = None
|
||||
worstscore2 = None
|
||||
minbest = IsTime
|
||||
minworst = not minbest
|
||||
r = 0
|
||||
for score in score1:
|
||||
if isMaxScore(newscore=score, maxscore=bestscore1, invert=minbest):
|
||||
bestscore1 = score
|
||||
if isMaxScore(newscore=score, maxscore=worstscore1, invert=minworst):
|
||||
worstscore1 = score
|
||||
if PrintAllScores: print ("%d" % score).rjust(16),
|
||||
for score in score2:
|
||||
if isMaxScore(newscore=score, maxscore=bestscore2, invert=minbest):
|
||||
bestscore2 = score
|
||||
if isMaxScore(newscore=score, maxscore=worstscore2, invert=minworst):
|
||||
worstscore2 = score
|
||||
if PrintAllScores: print ("%d" % score).rjust(16),
|
||||
r += 1
|
||||
while r < runs:
|
||||
if PrintAllScores: print ("0").rjust(9),
|
||||
r += 1
|
||||
|
||||
if not PrintAllScores:
|
||||
print ("%d" % bestscore1).rjust(16),
|
||||
print ("%d" % bestscore2).rjust(16),
|
||||
|
||||
print ("%+d" % (bestscore2-bestscore1)).rjust(9),
|
||||
|
||||
if bestscore1 != 0 and bestscore2 != 0:
|
||||
print ("%+.1f%%"%(((float(bestscore2)/bestscore1)-1)*100)).rjust(9),
|
||||
if ShowSpeedup:
|
||||
Num, Den = float(bestscore2), float(bestscore1)
|
||||
if IsTime:
|
||||
Num, Den = Den, Num
|
||||
print ("%.2fx"%(Num/Den)).rjust(9),
|
||||
else:
|
||||
print "*".rjust(9),
|
||||
if ShowSpeedup:
|
||||
print "*".rjust(9),
|
||||
# if the interval endpoints have inverse relationship, then they overlap
|
||||
if minbest:
|
||||
if bestscore1 < worstscore2:
|
||||
print "(!)",
|
||||
else:
|
||||
if bestscore1 > worstscore2:
|
||||
print "(!)",
|
||||
print
|
||||
|
||||
def printBestScores(key, scores):
|
||||
print key,
|
||||
bestscore = None
|
||||
minbest = IsTime
|
||||
for score in scores:
|
||||
if isMaxScore(newscore=score, maxscore=bestscore, invert=minbest):
|
||||
bestscore = score
|
||||
print ", %d" % bestscore
|
||||
|
||||
def usage():
|
||||
print "repeat.sh <n> Benchmark_O[none|unchecked] > file.times"
|
||||
print "compare_perf_tests.py <file.times> [<file2.times>]"
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
usage()
|
||||
sys.exit(1)
|
||||
file1 = sys.argv[1]
|
||||
if len(sys.argv) < 3:
|
||||
scores, runs, nums = getScores(file1)
|
||||
keys = [f for f in set(scores.keys())]
|
||||
keys.sort()
|
||||
for key in keys:
|
||||
printBestScores(key, scores[key])
|
||||
sys.exit(0)
|
||||
|
||||
file2 = sys.argv[2]
|
||||
if len(sys.argv) > 3:
|
||||
SCORERE = re.compile(sys.argv[3])
|
||||
|
||||
scores1, runs1, nums = getScores(file1)
|
||||
scores2, runs2, nums = getScores(file2)
|
||||
|
||||
runs = runs1
|
||||
if runs2 > runs:
|
||||
runs = runs2
|
||||
|
||||
if VERBOSE: print scores1; print scores2
|
||||
|
||||
keys = [f for f in set(scores1.keys() + scores2.keys())]
|
||||
keys.sort()
|
||||
if VERBOSE:
|
||||
print "comparing ", file1, "vs", file2, "=",
|
||||
if IsTime: print file1, "/", file2
|
||||
else: print file2, "/", file1
|
||||
|
||||
print "#".rjust(3),
|
||||
print "TEST".ljust(25),
|
||||
if PrintAllScores:
|
||||
for i in range(0,runs):
|
||||
print ("OLD_RUN%d" % i).rjust(9),
|
||||
for i in range(0,runs):
|
||||
print ("NEW_RUN%d" % i).rjust(9),
|
||||
else:
|
||||
print "BEST_OLD_MIN(μs)".rjust(17),
|
||||
print "BEST_NEW_MIN(μs)".rjust(17),
|
||||
print 'DELTA'.rjust(9), '%DELTA'.rjust(9), 'SPEEDUP'.rjust(9)
|
||||
|
||||
for key in keys:
|
||||
if not key in scores1:
|
||||
print key, "not in", file1
|
||||
continue
|
||||
if not key in scores2:
|
||||
print key, "not in", file2
|
||||
continue
|
||||
compareScores(key, scores1[key], scores2[key], runs, nums[key])
|
||||
157
benchmark/scripts/generate_harness/CMakeLists.txt_template
Normal file
157
benchmark/scripts/generate_harness/CMakeLists.txt_template
Normal file
@@ -0,0 +1,157 @@
|
||||
# -*- mode: cmake -*-
|
||||
################################################################################
|
||||
# WARNING: This file is automatically generated from templates and should not
|
||||
# be directly modified. Instead, make changes to
|
||||
# scripts/generate_harness/CMakeLists.txt_template and run
|
||||
# scripts/generate_harness/generate_harness.py to regenerate this file.
|
||||
################################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
|
||||
# Add path for custom CMake modules.
|
||||
list(APPEND CMAKE_MODULE_PATH
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules")
|
||||
|
||||
include(add-swift-benchmark-suite)
|
||||
|
||||
set(SWIFT_BENCH_MODULES
|
||||
{% for test in tests %}
|
||||
{{ test }}
|
||||
{% endfor %}
|
||||
)
|
||||
|
||||
set(SWIFT_MULTISOURCE_BENCHES
|
||||
{% for multisource_bench in multisource_benches %}
|
||||
{{ multisource_bench.name }}
|
||||
{% endfor %}
|
||||
)
|
||||
|
||||
{% for multisource_bench in multisource_benches %}
|
||||
set({{ multisource_bench.name }}_sources
|
||||
{% for file in multisource_bench.files %}
|
||||
{{ multisource_bench.name }}/{{ file }}
|
||||
{% endfor %}
|
||||
)
|
||||
|
||||
{% endfor %}
|
||||
|
||||
set(BENCH_DRIVER_LIBRARY_MODULES
|
||||
DriverUtils
|
||||
TestsUtils
|
||||
)
|
||||
|
||||
set(BENCH_DRIVER_LIBRARY_FLAGS)
|
||||
if (SWIFT_RUNTIME_ENABLE_LEAK_CHECKER)
|
||||
set(BENCH_DRIVER_LIBRARY_FLAGS -DSWIFT_RUNTIME_ENABLE_LEAK_CHECKER)
|
||||
endif()
|
||||
|
||||
set(BENCH_LIBRARY_MODULES
|
||||
)
|
||||
|
||||
add_definitions(-DSWIFT_EXEC -DSWIFT_LIBRARY_PATH -DONLY_PLATFORMS
|
||||
-DSWIFT_OPTIMIZATION_LEVELS -DSWIFT_BENCHMARK_EMIT_SIB)
|
||||
|
||||
if(NOT ONLY_PLATFORMS)
|
||||
set(ONLY_PLATFORMS "macosx" "iphoneos" "appletvos" "watchos")
|
||||
endif()
|
||||
|
||||
if(NOT SWIFT_EXEC)
|
||||
runcmd(COMMAND "xcrun" "-f" "swiftc"
|
||||
VARIABLE SWIFT_EXEC
|
||||
ERROR "Unable to find Swift driver")
|
||||
endif()
|
||||
|
||||
if(NOT SWIFT_LIBRARY_PATH)
|
||||
get_filename_component(tmp_dir "${SWIFT_EXEC}" DIRECTORY)
|
||||
get_filename_component(tmp_dir "${tmp_dir}" DIRECTORY)
|
||||
set(SWIFT_LIBRARY_PATH "${tmp_dir}/lib/swift")
|
||||
endif()
|
||||
|
||||
runcmd(COMMAND "xcrun" "-f" "clang"
|
||||
VARIABLE CLANG_EXEC
|
||||
ERROR "Unable to find Clang driver")
|
||||
|
||||
# You have to delete CMakeCache.txt in the swift build to force a
|
||||
# reconfiguration.
|
||||
set(SWIFT_EXTRA_BENCH_CONFIGS CACHE STRING
|
||||
"A semicolon separated list of benchmark configurations. \
|
||||
Available configurations: <Optlevel>_SINGLEFILE, <Optlevel>_MULTITHREADED")
|
||||
|
||||
# Syntax for an optset: <optimization-level>_<configuration>
|
||||
# where "_<configuration>" is optional.
|
||||
if(NOT SWIFT_OPTIMIZATION_LEVELS)
|
||||
set(SWIFT_OPTIMIZATION_LEVELS "Onone" "O" "Ounchecked"
|
||||
${SWIFT_EXTRA_BENCH_CONFIGS})
|
||||
endif()
|
||||
|
||||
# Options for the default (= empty) configuration
|
||||
set(BENCHOPTS "-whole-module-optimization")
|
||||
|
||||
# Options for other configurations
|
||||
set(BENCHOPTS_MULTITHREADED
|
||||
"-whole-module-optimization" "-num-threads" "4")
|
||||
set(BENCHOPTS_SINGLEFILE "")
|
||||
|
||||
set(macosx_arch "x86_64")
|
||||
set(iphoneos_arch "arm64" "armv7")
|
||||
set(appletvos_arch "arm64")
|
||||
set(watchos_arch "armv7k")
|
||||
|
||||
set(macosx_ver "10.9")
|
||||
set(iphoneos_ver "8.0")
|
||||
set(appletvos_ver "9.1")
|
||||
set(watchos_ver "2.0")
|
||||
|
||||
set(macosx_triple_platform "macosx")
|
||||
set(iphoneos_triple_platform "ios")
|
||||
set(appletvos_triple_platform "tvos")
|
||||
set(watchos_triple_platform "watchos")
|
||||
|
||||
set(sdks)
|
||||
set(platforms)
|
||||
foreach(platform ${ONLY_PLATFORMS})
|
||||
execute_process(
|
||||
COMMAND "xcrun" "--sdk" "${platform}" "--show-sdk-path"
|
||||
OUTPUT_VARIABLE ${platform}_sdk
|
||||
RESULT_VARIABLE result
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if("${result}" MATCHES "0")
|
||||
list(APPEND sdks "${${platform}_sdk}")
|
||||
list(APPEND platforms ${platform})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
message("--")
|
||||
message("-- Swift Benchmark Suite:")
|
||||
message("-- SWIFT_EXEC = ${SWIFT_EXEC}")
|
||||
message("-- SWIFT_LIBRARY_PATH = ${SWIFT_LIBRARY_PATH}")
|
||||
message("-- CLANG_EXEC = ${CLANG_EXEC}")
|
||||
message("-- SWIFT_OPTIMIZATION_LEVELS = ${SWIFT_OPTIMIZATION_LEVELS}")
|
||||
message("-- ONLY_PLATFORMS = ${ONLY_PLATFORMS}")
|
||||
|
||||
message("-- found platforms: ${platforms}")
|
||||
message("-- found sdks:")
|
||||
foreach(sdk ${sdks})
|
||||
message("-- ${sdk}")
|
||||
endforeach()
|
||||
|
||||
set(executable_targets)
|
||||
|
||||
set(srcdir "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(bindir "${CMAKE_CURRENT_BINARY_DIR}/bin")
|
||||
set(libdir "${CMAKE_CURRENT_BINARY_DIR}/lib")
|
||||
set(libswiftdir "${CMAKE_CURRENT_BINARY_DIR}/lib/swift")
|
||||
file(MAKE_DIRECTORY "${bindir}")
|
||||
file(MAKE_DIRECTORY "${libdir}")
|
||||
file(MAKE_DIRECTORY "${libswiftdir}")
|
||||
|
||||
if(SWIFT_SDKS)
|
||||
set(IS_SWIFT_BUILD true)
|
||||
endif()
|
||||
|
||||
# Compile the perf test suite for each platform
|
||||
foreach(platform ${platforms})
|
||||
swift_benchmark_compile(PLATFORM ${platform})
|
||||
endforeach()
|
||||
|
||||
add_subdirectory(scripts)
|
||||
90
benchmark/scripts/generate_harness/generate_harness.py
Normal file
90
benchmark/scripts/generate_harness/generate_harness.py
Normal file
@@ -0,0 +1,90 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# ===--- generate_harness.py ----------------------------------------------===//
|
||||
#
|
||||
# This source file is part of the Swift.org open source project
|
||||
#
|
||||
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
# Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
#
|
||||
# See http://swift.org/LICENSE.txt for license information
|
||||
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
#
|
||||
# ===----------------------------------------------------------------------===//
|
||||
|
||||
# Generate CMakeLists.txt and utils/main.swift from templates.
|
||||
|
||||
import jinja2
|
||||
import os
|
||||
import glob
|
||||
import re
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
perf_dir = os.path.realpath(os.path.join(script_dir, '../..'))
|
||||
single_source_dir = os.path.join(perf_dir, 'single-source')
|
||||
multi_source_dir = os.path.join(perf_dir, 'multi-source')
|
||||
|
||||
template_map = {
|
||||
'CMakeLists.txt_template': os.path.join(perf_dir, 'CMakeLists.txt'),
|
||||
'main.swift_template': os.path.join(perf_dir, 'utils/main.swift')
|
||||
}
|
||||
ignored_run_funcs = ["Ackermann", "Fibonacci"]
|
||||
|
||||
template_loader = jinja2.FileSystemLoader(searchpath="/")
|
||||
template_env = jinja2.Environment(loader=template_loader, trim_blocks=True,
|
||||
lstrip_blocks=True)
|
||||
|
||||
if __name__ == '__main__':
|
||||
# CMakeList single-source
|
||||
tests = [os.path.basename(x).split('.')[0]
|
||||
for x in glob.glob(os.path.join(single_source_dir, '*.swift'))]
|
||||
|
||||
# CMakeList multi-source
|
||||
class multi_source_bench(object):
|
||||
def __init__(self, path):
|
||||
self.name = os.path.basename(path)
|
||||
self.files = [x for x in os.listdir(path)
|
||||
if x.endswith('.swift')]
|
||||
if os.path.isdir(multi_source_dir):
|
||||
multisource_benches = [
|
||||
multi_source_bench(os.path.join(multi_source_dir, x))
|
||||
for x in os.listdir(multi_source_dir)
|
||||
if os.path.isdir(os.path.join(multi_source_dir, x))
|
||||
]
|
||||
else:
|
||||
multisource_benches = []
|
||||
|
||||
# main.swift imports
|
||||
imports = sorted(tests + [msb.name for msb in multisource_benches])
|
||||
|
||||
# main.swift run functions
|
||||
def get_run_funcs(filepath):
|
||||
content = open(filepath).read()
|
||||
matches = re.findall(r'func run_(.*?)\(', content)
|
||||
return filter(lambda x: x not in ignored_run_funcs, matches)
|
||||
def find_run_funcs(dirs):
|
||||
ret_run_funcs = []
|
||||
for d in dirs:
|
||||
for root, _, files in os.walk(d):
|
||||
for name in filter(lambda x: x.endswith('.swift'), files):
|
||||
run_funcs = get_run_funcs(os.path.join(root, name))
|
||||
ret_run_funcs.extend(run_funcs)
|
||||
return ret_run_funcs
|
||||
run_funcs = sorted(
|
||||
[(x, x)
|
||||
for x in find_run_funcs([single_source_dir, multi_source_dir])],
|
||||
key=lambda x: x[0]
|
||||
)
|
||||
|
||||
# Replace originals with files generated from templates
|
||||
for template_file in template_map:
|
||||
template_path = os.path.join(script_dir, template_file)
|
||||
template = template_env.get_template(template_path)
|
||||
print template_map[template_file]
|
||||
open(template_map[template_file], 'w').write(
|
||||
template.render(tests=tests,
|
||||
multisource_benches=multisource_benches,
|
||||
imports=imports,
|
||||
run_funcs=run_funcs)
|
||||
)
|
||||
|
||||
40
benchmark/scripts/generate_harness/main.swift_template
Normal file
40
benchmark/scripts/generate_harness/main.swift_template
Normal file
@@ -0,0 +1,40 @@
|
||||
//===--- main.swift -------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// WARNING: This file is automatically generated from templates and should not
|
||||
// be directly modified. Instead, make changes to
|
||||
// scripts/generate_harness/main.swift_template and run
|
||||
// scripts/generate_harness/generate_harness.py to regenerate this file.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is just a driver for performance overview tests.
|
||||
import TestsUtils
|
||||
import DriverUtils
|
||||
{% for import in imports %}
|
||||
import {{ import }}
|
||||
{% endfor %}
|
||||
|
||||
precommitTests = [
|
||||
{% for run_func in run_funcs %}
|
||||
"{{ run_func[0] }}": run_{{ run_func[1] }},
|
||||
{% endfor %}
|
||||
]
|
||||
|
||||
otherTests = [
|
||||
"Ackermann": run_Ackermann,
|
||||
"Fibonacci": run_Fibonacci,
|
||||
]
|
||||
|
||||
|
||||
main()
|
||||
|
||||
115
benchmark/scripts/perf_test_driver/perf_test_driver.py
Normal file
115
benchmark/scripts/perf_test_driver/perf_test_driver.py
Normal file
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# ===--- perf_test_driver.py ----------------------------------------------===//
|
||||
#
|
||||
# This source file is part of the Swift.org open source project
|
||||
#
|
||||
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
# Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
#
|
||||
# See http://swift.org/LICENSE.txt for license information
|
||||
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
#
|
||||
# ===----------------------------------------------------------------------===//
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import multiprocessing
|
||||
import re
|
||||
|
||||
class Result(object):
|
||||
def __init__(self, name, status, output, xfail_list):
|
||||
self.name = name
|
||||
self.status = status
|
||||
self.output = output
|
||||
self.is_xfailed = any((re.match(x, self.name) is not None for x in xfail_list))
|
||||
|
||||
def is_failure(self):
|
||||
return self.get_result() in ['FAIL', 'XPASS']
|
||||
|
||||
def get_result(self):
|
||||
if self.is_xfailed:
|
||||
if self.status:
|
||||
return 'XFAIL'
|
||||
return 'XPASS'
|
||||
if self.status:
|
||||
return 'FAIL'
|
||||
return 'PASS'
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
def get_status(self):
|
||||
return self.status
|
||||
|
||||
def get_output(self):
|
||||
return self.output
|
||||
|
||||
def get_data(self):
|
||||
return self.data
|
||||
|
||||
def merge_in_extra_data(self, d):
|
||||
"""Rather than modifying the extra data dict, just return it as a no-op"""
|
||||
return d
|
||||
|
||||
def _unwrap_self(args):
|
||||
return type(args[0]).process_input(*args)
|
||||
|
||||
class BenchmarkDriver(object):
|
||||
|
||||
OptLevels = ['Onone', 'O', 'Ounchecked']
|
||||
|
||||
def __init__(self, binary_dir, xfail_list, enable_parallel=False):
|
||||
self.targets = [(os.path.join(binary_dir, 'Benchmark_%s' % o), o) for o in BenchmarkDriver.OptLevels]
|
||||
self.xfail_list = xfail_list
|
||||
self.enable_parallel = enable_parallel
|
||||
self.data = None
|
||||
|
||||
def prepare_input(self, name, opt_level):
|
||||
raise RuntimeError("Abstract method")
|
||||
|
||||
def process_input(self, data):
|
||||
raise RuntimeError("Abstract method")
|
||||
|
||||
def run_for_opt_level(self, binary, opt_level):
|
||||
print("testing driver at path: %s" % binary)
|
||||
names = [n.strip() for n in subprocess.check_output([binary, "--list"]).split()[2:]]
|
||||
|
||||
def prepare_input_wrapper(name):
|
||||
x = {'opt': opt_level, 'path': binary, 'test_name': name}
|
||||
x.update(self.prepare_input(name))
|
||||
return x
|
||||
|
||||
prepared_input = [prepare_input_wrapper(n) for n in names]
|
||||
results = None
|
||||
if self.enable_parallel:
|
||||
p = multiprocessing.Pool()
|
||||
z = zip([self]*len(prepared_input), prepared_input)
|
||||
results = p.map(_unwrap_self, z)
|
||||
else:
|
||||
results = map(self.process_input, prepared_input)
|
||||
|
||||
def reduce_results(acc, r):
|
||||
acc['result'].append(r)
|
||||
acc['has_failure'] = acc['has_failure'] or r.is_failure()
|
||||
acc['max_test_len'] = max(acc['max_test_len'], len(r.get_name()))
|
||||
acc['extra_data'] = r.merge_in_extra_data(acc['extra_data'])
|
||||
return acc
|
||||
|
||||
return reduce(reduce_results, results, {'result': [], 'has_failure': False, 'max_test_len': 0, 'extra_data': {}})
|
||||
|
||||
def print_data(self, data, max_test_len):
|
||||
print("Results:")
|
||||
fmt = '{:<%d}{:}' % (max_test_len + 5)
|
||||
for d in data:
|
||||
for r in d['result']:
|
||||
print(fmt.format(r.get_name(), r.get_result()))
|
||||
|
||||
def run(self):
|
||||
self.data = [self.run_for_opt_level(binary, opt_level) for binary, opt_level in self.targets]
|
||||
max_test_len = reduce(max, [d['max_test_len']for d in self.data])
|
||||
has_failure = reduce(max, [d['has_failure']for d in self.data])
|
||||
self.print_data(self.data, max_test_len)
|
||||
return not has_failure
|
||||
|
||||
47
benchmark/single-source/Ackermann.swift
Normal file
47
benchmark/single-source/Ackermann.swift
Normal file
@@ -0,0 +1,47 @@
|
||||
//===--- Ackermann.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test is based on test Ackermann from utils/benchmark, with modifications
|
||||
// for performance measuring.
|
||||
import TestsUtils
|
||||
|
||||
func ackermann(M : Int, _ N : Int) -> Int {
|
||||
if (M == 0) { return N + 1 }
|
||||
if (N == 0) { return ackermann(M - 1, 1) }
|
||||
return ackermann(M - 1, ackermann(M, N - 1))
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func Ackermann(M : Int, _ N : Int) -> Int {
|
||||
// This if prevents optimizer from computing return value of Ackermann(3,9)
|
||||
// at compile time.
|
||||
if False() { return 0 }
|
||||
if (M == 0) { return N + 1 }
|
||||
if (N == 0) { return ackermann(M - 1, 1) }
|
||||
return ackermann(M - 1, ackermann(M, N - 1))
|
||||
}
|
||||
|
||||
let ref_result = [5, 13, 29, 61, 125, 253, 509, 1021, 2045, 4093, 8189, 16381, 32765, 65533, 131069];
|
||||
|
||||
@inline(never)
|
||||
public func run_Ackermann(N: Int) {
|
||||
let (m, n) = (3, 9)
|
||||
var result = 0
|
||||
for _ in 1...N {
|
||||
result = Ackermann(m, n)
|
||||
if result != ref_result[n] {
|
||||
break
|
||||
}
|
||||
}
|
||||
CheckResults(result == ref_result[n],
|
||||
"IncorrectResults in Ackermann: \(result) != \(ref_result[n]).")
|
||||
}
|
||||
43
benchmark/single-source/AngryPhonebook.swift
Normal file
43
benchmark/single-source/AngryPhonebook.swift
Normal file
@@ -0,0 +1,43 @@
|
||||
//===--- AngryPhonebook.swift ---------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test is based on single-source/Phonebook, with
|
||||
// to test uppercase and lowercase ASCII string fast paths.
|
||||
import TestsUtils
|
||||
import Foundation
|
||||
|
||||
var words = [
|
||||
"James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph",
|
||||
"Charles", "Thomas", "Christopher", "Daniel", "Matthew", "Donald", "Anthony",
|
||||
"Paul", "Mark", "George", "Steven", "Kenneth", "Andrew", "Edward", "Brian",
|
||||
"Joshua", "Kevin", "Ronald", "Timothy", "Jason", "Jeffrey", "Gary", "Ryan",
|
||||
"Nicholas", "Eric", "Stephen", "Jacob", "Larry", "Frank", "Jonathan", "Scott",
|
||||
"Justin", "Raymond", "Brandon", "Gregory", "Samuel", "Patrick", "Benjamin",
|
||||
"Jack", "Dennis", "Jerry", "Alexander", "Tyler", "Douglas", "Henry", "Peter",
|
||||
"Walter", "Aaron", "Jose", "Adam", "Harold", "Zachary", "Nathan", "Carl",
|
||||
"Kyle", "Arthur", "Gerald", "Lawrence", "Roger", "Albert", "Keith", "Jeremy",
|
||||
"Terry", "Joe", "Sean", "Willie", "Jesse", "Ralph", "Billy", "Austin", "Bruce",
|
||||
"Christian", "Roy", "Bryan", "Eugene", "Louis", "Harry", "Wayne", "Ethan",
|
||||
"Jordan", "Russell", "Alan", "Philip", "Randy", "Juan", "Howard", "Vincent",
|
||||
"Bobby", "Dylan", "Johnny", "Phillip", "Craig"]
|
||||
|
||||
@inline(never)
|
||||
public func run_AngryPhonebook(N: Int) {
|
||||
// Permute the names.
|
||||
for _ in 1...N {
|
||||
for firstname in words {
|
||||
for lastname in words {
|
||||
(firstname.uppercaseString, lastname.lowercaseString)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
benchmark/single-source/Array2D.swift
Normal file
31
benchmark/single-source/Array2D.swift
Normal file
@@ -0,0 +1,31 @@
|
||||
//===--- Array2D.swift ----------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@inline(never)
|
||||
public func run_Array2D(N: Int) {
|
||||
var A: [[Int]] = []
|
||||
for _ in 0 ..< 1024 {
|
||||
var B: [Int] = []
|
||||
for y in 0 ..< 1024 {
|
||||
B.append(y)
|
||||
}
|
||||
A.append(B)
|
||||
}
|
||||
for _ in 0..<N {
|
||||
for i in 0 ..< 1024 {
|
||||
for y in 0 ..< 1024 {
|
||||
A[i][y] = A[i][y] + 1
|
||||
A[i][y] = A[i][y] - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
benchmark/single-source/ArrayAppend.swift
Normal file
40
benchmark/single-source/ArrayAppend.swift
Normal file
@@ -0,0 +1,40 @@
|
||||
//===--- ArrayAppend.swift ------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test checks the performance of appending to an array.
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayAppend(N: Int) {
|
||||
for _ in 0..<N {
|
||||
for _ in 0..<10 {
|
||||
var nums = [Int]()
|
||||
for _ in 0..<40000 {
|
||||
nums.append(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayAppendReserved(N: Int) {
|
||||
for _ in 0..<N {
|
||||
for _ in 0..<10 {
|
||||
var nums = [Int]()
|
||||
nums.reserveCapacity(40000)
|
||||
for _ in 0..<40000 {
|
||||
nums.append(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
benchmark/single-source/ArrayInClass.swift
Normal file
38
benchmark/single-source/ArrayInClass.swift
Normal file
@@ -0,0 +1,38 @@
|
||||
//===--- ArrayInClass.swift -----------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class ArrayContainer {
|
||||
final var arr : [Int]
|
||||
|
||||
init() {
|
||||
arr = [Int] (count: 100_000, repeatedValue: 0)
|
||||
}
|
||||
|
||||
func runLoop(N: Int) {
|
||||
for _ in 0 ..< N {
|
||||
for i in 0 ..< arr.count {
|
||||
arr[i] = arr[i] + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func getArrayContainer() -> ArrayContainer {
|
||||
return ArrayContainer()
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayInClass(N: Int) {
|
||||
let a = getArrayContainer()
|
||||
a.runLoop(N)
|
||||
}
|
||||
105
benchmark/single-source/ArrayLiteral.swift
Normal file
105
benchmark/single-source/ArrayLiteral.swift
Normal file
@@ -0,0 +1,105 @@
|
||||
//===--- ArrayLiteral.swift -----------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test checks performance of creating array from literal and array value
|
||||
// propagation.
|
||||
// It is reported to be slow: <rdar://problem/17297449>
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
func makeArray() -> [Int] {
|
||||
return [1,2,3]
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayLiteral(N: Int) {
|
||||
for _ in 1...10000*N {
|
||||
makeArray()
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func addLiteralArray() -> Int {
|
||||
let Arr = [1, 2, 3]
|
||||
return Arr[0] + Arr[1] + Arr[2]
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayValueProp(N: Int) {
|
||||
var res = 123
|
||||
for _ in 1...10000*N {
|
||||
res += addLiteralArray()
|
||||
res -= addLiteralArray()
|
||||
}
|
||||
CheckResults(res == 123, "Wrong result in ArrayValueProp 123 != \(res)")
|
||||
}
|
||||
|
||||
|
||||
@inline(never)
|
||||
func addLiteralArray2() -> Int {
|
||||
let Arr = [1, 2, 3]
|
||||
var r = 0
|
||||
for elt in Arr {
|
||||
r += elt
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func addLiteralArray3() -> Int {
|
||||
let Arr = [1, 2, 3]
|
||||
var r = 0
|
||||
for i in 0..<Arr.count {
|
||||
r += Arr[i]
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func addLiteralArray4() -> Int {
|
||||
let Arr = [1, 2, 3]
|
||||
var r = 0
|
||||
for i in 0..<3 {
|
||||
r += Arr[i]
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayValueProp2(N: Int) {
|
||||
var res = 123
|
||||
for _ in 1...10000*N {
|
||||
res += addLiteralArray2()
|
||||
res -= addLiteralArray2()
|
||||
}
|
||||
CheckResults(res == 123, "Wrong result in ArrayValueProp 123 != \(res)")
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayValueProp3(N: Int) {
|
||||
var res = 123
|
||||
for _ in 1...10000*N {
|
||||
res += addLiteralArray3()
|
||||
res -= addLiteralArray3()
|
||||
}
|
||||
CheckResults(res == 123, "Wrong result in ArrayValueProp 123 != \(res)")
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayValueProp4(N: Int) {
|
||||
var res = 123
|
||||
for _ in 1...10000*N {
|
||||
res += addLiteralArray4()
|
||||
res -= addLiteralArray4()
|
||||
}
|
||||
CheckResults(res == 123, "Wrong result in ArrayValueProp 123 != \(res)")
|
||||
}
|
||||
67
benchmark/single-source/ArrayOfGenericPOD.swift
Normal file
67
benchmark/single-source/ArrayOfGenericPOD.swift
Normal file
@@ -0,0 +1,67 @@
|
||||
//===--- ArrayOfGenericPOD.swift ------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This benchmark tests creation and destruction of arrays of enum and
|
||||
// generic type bound to trivial types. It should take the same time as
|
||||
// ArrayOfPOD. (In practice, it takes a little longer to construct
|
||||
// the optional arrays).
|
||||
//
|
||||
// For comparison, we always create three arrays of 200,000 words.
|
||||
// An integer enum takes two words.
|
||||
|
||||
class RefArray<T> {
|
||||
var array : [T]
|
||||
|
||||
init(_ i:T) {
|
||||
array = [T](count: 100000, repeatedValue: i)
|
||||
}
|
||||
}
|
||||
|
||||
// Check the performance of destroying an array of enums (optional) where the
|
||||
// enum has a single payload of trivial type. Destroying the
|
||||
// elements should be a nop.
|
||||
@inline(never)
|
||||
func genEnumArray() {
|
||||
_ = RefArray<Int?>(3)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
// Check the performance of destroying an array of implicit unwrapped
|
||||
// optional where the optional has a single payload of trivial
|
||||
// type. Destroying the elements should be a nop.
|
||||
@inline(never)
|
||||
func genIOUArray() {
|
||||
_ = RefArray<Int!>(3)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
// Check the performance of destroying an array of structs where the
|
||||
// struct has a multipe fields of trivial type. Destroying the
|
||||
// elements should be a nop.
|
||||
struct S<T> {
|
||||
var x : T
|
||||
var y : T
|
||||
}
|
||||
@inline(never)
|
||||
func genStructArray() {
|
||||
_ = RefArray<S<Int>>(S(x:3,y:4))
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayOfGenericPOD(N: Int) {
|
||||
for _ in 0...N {
|
||||
genEnumArray()
|
||||
genIOUArray()
|
||||
genStructArray()
|
||||
}
|
||||
}
|
||||
96
benchmark/single-source/ArrayOfGenericRef.swift
Normal file
96
benchmark/single-source/ArrayOfGenericRef.swift
Normal file
@@ -0,0 +1,96 @@
|
||||
//===--- ArrayOfGenericRef.swift ------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This benchmark tests creation and destruction of an array of enum
|
||||
// and generic type bound to nontrivial types.
|
||||
//
|
||||
// For comparison, we always create three arrays of 10,000 words.
|
||||
|
||||
protocol Constructible {
|
||||
typealias Element
|
||||
init(e:Element)
|
||||
}
|
||||
class ConstructibleArray<T:Constructible> {
|
||||
var array : [T]
|
||||
|
||||
init(_ e:T.Element) {
|
||||
array = [T]()
|
||||
array.reserveCapacity(10_000)
|
||||
for _ in 0...10_000 {
|
||||
array.append(T(e:e) as T)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GenericRef<T> : Constructible {
|
||||
typealias Element=T
|
||||
var x : T
|
||||
required init(e:T) { self.x = e }
|
||||
}
|
||||
|
||||
// Reference to a POD class.
|
||||
@inline(never)
|
||||
func genPODRefArray() {
|
||||
_ = ConstructibleArray<GenericRef<Int>>(3)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
class Dummy {}
|
||||
|
||||
// Reference to a reference. The nested reference is shared across elements.
|
||||
@inline(never)
|
||||
func genCommonRefArray() {
|
||||
let d = Dummy()
|
||||
_ = ConstructibleArray<GenericRef<Dummy>>(d)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
// Reuse the same enum value for each element.
|
||||
class RefArray<T> {
|
||||
var array : [T]
|
||||
|
||||
init(_ i:T, count:Int = 10_000) {
|
||||
array = [T](count: count, repeatedValue: i)
|
||||
}
|
||||
}
|
||||
|
||||
// enum holding a reference.
|
||||
@inline(never)
|
||||
func genRefEnumArray() {
|
||||
let d = Dummy()
|
||||
_ = RefArray<Dummy?>(d)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
struct GenericVal<T> : Constructible {
|
||||
typealias Element=T
|
||||
var x : T
|
||||
init(e:T) { self.x = e }
|
||||
}
|
||||
|
||||
// Struct holding a reference.
|
||||
@inline(never)
|
||||
func genRefStructArray() {
|
||||
let d = Dummy()
|
||||
_ = ConstructibleArray<GenericVal<Dummy>>(d)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayOfGenericRef(N: Int) {
|
||||
for _ in 0...N {
|
||||
genPODRefArray()
|
||||
genCommonRefArray()
|
||||
genRefEnumArray()
|
||||
genRefStructArray()
|
||||
}
|
||||
}
|
||||
62
benchmark/single-source/ArrayOfPOD.swift
Normal file
62
benchmark/single-source/ArrayOfPOD.swift
Normal file
@@ -0,0 +1,62 @@
|
||||
//===--- ArrayOfPOD.swift -------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This benchmark tests creation and destruction of an array of
|
||||
// trivial static type. It is meant to be a baseline for comparison against
|
||||
// ArrayOfGenericPOD.
|
||||
//
|
||||
// For comparison, we always create three arrays of 200,000 words.
|
||||
|
||||
class RefArray<T> {
|
||||
var array : [T]
|
||||
|
||||
init(_ i:T, count:Int = 100_000) {
|
||||
array = [T](count: count, repeatedValue: i)
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func genIntArray() {
|
||||
_ = RefArray<Int>(3, count:200_000)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
enum PODEnum {
|
||||
case Some(Int)
|
||||
|
||||
init(i:Int) { self = .Some(i) }
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func genEnumArray() {
|
||||
_ = RefArray<PODEnum>(PODEnum.Some(3))
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
struct S {
|
||||
var x : Int
|
||||
var y : Int
|
||||
}
|
||||
@inline(never)
|
||||
func genStructArray() {
|
||||
_ = RefArray<S>(S(x:3, y:4))
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayOfPOD(N: Int) {
|
||||
for _ in 0...N {
|
||||
genIntArray()
|
||||
genEnumArray()
|
||||
genStructArray()
|
||||
}
|
||||
}
|
||||
107
benchmark/single-source/ArrayOfRef.swift
Normal file
107
benchmark/single-source/ArrayOfRef.swift
Normal file
@@ -0,0 +1,107 @@
|
||||
//===--- ArrayOfRef.swift -------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This benchmark tests creation and destruction of an array of
|
||||
// references. It is meant to be a baseline for comparison against
|
||||
// ArrayOfGenericRef.
|
||||
//
|
||||
// For comparison, we always create four arrays of 10,000 words.
|
||||
|
||||
protocol Constructible {
|
||||
typealias Element
|
||||
init(e:Element)
|
||||
}
|
||||
class ConstructibleArray<T:Constructible> {
|
||||
var array : [T]
|
||||
|
||||
init(_ e:T.Element) {
|
||||
array = [T]()
|
||||
array.reserveCapacity(10_000)
|
||||
for _ in 0...10_000 {
|
||||
array.append(T(e:e) as T)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reference to a POD class.
|
||||
class POD : Constructible {
|
||||
typealias Element=Int
|
||||
var x : Int
|
||||
required init(e:Int) { self.x = e }
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func genPODRefArray() {
|
||||
_ = ConstructibleArray<POD>(3)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
class Dummy {}
|
||||
|
||||
// Reference to a reference. The nested reference is shared across elements.
|
||||
class CommonRef : Constructible {
|
||||
typealias Element=Dummy
|
||||
var d : Dummy
|
||||
required init(e:Dummy) { self.d = e }
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func genCommonRefArray() {
|
||||
let d = Dummy()
|
||||
_ = ConstructibleArray<CommonRef>(d)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
enum RefEnum {
|
||||
case None
|
||||
case Some(Dummy)
|
||||
}
|
||||
|
||||
// Reuse the same enum value for each element.
|
||||
class RefArray<T> {
|
||||
var array : [T]
|
||||
|
||||
init(_ i:T, count:Int = 10_000) {
|
||||
array = [T](count: count, repeatedValue: i)
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func genRefEnumArray() {
|
||||
let e = RefEnum.Some(Dummy())
|
||||
_ = RefArray<RefEnum>(e)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
// Struct holding a reference.
|
||||
struct S : Constructible {
|
||||
typealias Element=Dummy
|
||||
var d : Dummy
|
||||
init(e:Dummy) { self.d = e }
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func genRefStructArray() {
|
||||
let d = Dummy()
|
||||
_ = ConstructibleArray<S>(d)
|
||||
// should be a nop
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ArrayOfRef(N: Int) {
|
||||
for _ in 0...N {
|
||||
genPODRefArray()
|
||||
genCommonRefArray()
|
||||
genRefEnumArray()
|
||||
genRefStructArray()
|
||||
}
|
||||
}
|
||||
39
benchmark/single-source/ArraySubscript.swift
Normal file
39
benchmark/single-source/ArraySubscript.swift
Normal file
@@ -0,0 +1,39 @@
|
||||
//===--- ArraySubscript.swift ---------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test checks the performance of modifying an array element.
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_ArraySubscript(N: Int) {
|
||||
SRand()
|
||||
|
||||
let numArrays = 200*N
|
||||
let numArrayElements = 100
|
||||
|
||||
func bound(x: Int) -> Int { return min(x, numArrayElements-1) }
|
||||
|
||||
var arrays = [[Int]](count: numArrays, repeatedValue: [])
|
||||
for i in 0..<numArrays {
|
||||
for _ in 0..<numArrayElements {
|
||||
arrays[i].append(Int(truncatingBitPattern: Random()))
|
||||
}
|
||||
}
|
||||
|
||||
// Do a max up the diagonal.
|
||||
for i in 1..<numArrays {
|
||||
arrays[i][bound(i)] =
|
||||
max(arrays[i-1][bound(i-1)], arrays[i][bound(i)])
|
||||
}
|
||||
CheckResults(arrays[0][0] <= arrays[numArrays-1][bound(numArrays-1)],
|
||||
"Incorrect results in QuickSort.")
|
||||
}
|
||||
40
benchmark/single-source/BitCount.swift
Normal file
40
benchmark/single-source/BitCount.swift
Normal file
@@ -0,0 +1,40 @@
|
||||
//===--- BitCount.swift ---------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test checks performance of Swift bit count.
|
||||
// and mask operator.
|
||||
// rdar://problem/22151678
|
||||
import Foundation
|
||||
import TestsUtils
|
||||
|
||||
func countBitSet(num: Int) -> Int {
|
||||
let bits = sizeof(Int) * 8
|
||||
var cnt : Int = 0
|
||||
var mask: Int = 1
|
||||
for _ in 0...bits {
|
||||
if num & mask != 0 {
|
||||
cnt += 1
|
||||
}
|
||||
mask <<= 1
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_BitCount(N: Int) {
|
||||
for _ in 1...100*N {
|
||||
// Check some results.
|
||||
CheckResults(countBitSet(1) == 1, "Incorrect results in BitCount.")
|
||||
CheckResults(countBitSet(2) == 1, "Incorrect results in BitCount.")
|
||||
CheckResults(countBitSet(2457) == 6, "Incorrect results in BitCount.")
|
||||
}
|
||||
}
|
||||
48
benchmark/single-source/ByteSwap.swift
Normal file
48
benchmark/single-source/ByteSwap.swift
Normal file
@@ -0,0 +1,48 @@
|
||||
//===--- ByteSwap.swift ---------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test checks performance of Swift byte swap.
|
||||
// rdar://problem/22151907
|
||||
|
||||
import Foundation
|
||||
import TestsUtils
|
||||
|
||||
// a naive O(n) implementation of byteswap.
|
||||
func byteswap_n(a: UInt64) -> UInt64 {
|
||||
return ((a & 0x00000000000000FF) << 56) |
|
||||
((a & 0x000000000000FF00) << 40) |
|
||||
((a & 0x0000000000FF0000) << 24) |
|
||||
((a & 0x00000000FF000000) << 8) |
|
||||
((a & 0x000000FF00000000) >> 8) |
|
||||
((a & 0x0000FF0000000000) >> 24) |
|
||||
((a & 0x00FF000000000000) >> 40) |
|
||||
((a & 0xFF00000000000000) >> 56)
|
||||
}
|
||||
|
||||
// a O(logn) implementation of byteswap.
|
||||
func byteswap_logn(a: UInt64) -> UInt64 {
|
||||
var a = a
|
||||
a = (a & 0x00000000FFFFFFFF) << 32 | (a & 0xFFFFFFFF00000000) >> 32
|
||||
a = (a & 0x0000FFFF0000FFFF) << 16 | (a & 0xFFFF0000FFFF0000) >> 16
|
||||
a = (a & 0x00FF00FF00FF00FF) << 8 | (a & 0xFF00FF00FF00FF00) >> 8
|
||||
return a
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ByteSwap(N: Int) {
|
||||
for _ in 1...100*N {
|
||||
// Check some results.
|
||||
CheckResults(byteswap_logn(byteswap_n(2457)) == 2457, "Incorrect results in ByteSwap.")
|
||||
CheckResults(byteswap_logn(byteswap_n(9129)) == 9129, "Incorrect results in ByteSwap.")
|
||||
CheckResults(byteswap_logn(byteswap_n(3333)) == 3333, "Incorrect results in ByteSwap.")
|
||||
}
|
||||
}
|
||||
41
benchmark/single-source/Calculator.swift
Normal file
41
benchmark/single-source/Calculator.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
//===--- Calculator.swift -------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
import Foundation
|
||||
|
||||
@inline(never)
|
||||
func my_atoi_impl(input : String) -> Int {
|
||||
switch input {
|
||||
case "0": return 0
|
||||
case "1": return 1
|
||||
case "2": return 2
|
||||
case "3": return 3
|
||||
case "4": return 4
|
||||
case "5": return 5
|
||||
case "6": return 6
|
||||
case "7": return 7
|
||||
case "8": return 8
|
||||
case "9": return 9
|
||||
default: return 0
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_Calculator(N: Int) {
|
||||
var c = 0
|
||||
for _ in 1...N*5000 {
|
||||
c += my_atoi_impl("10")
|
||||
}
|
||||
CheckResults(c == 0, "IncorrectResults in run_Calculator")
|
||||
}
|
||||
|
||||
32
benchmark/single-source/CaptureProp.swift
Normal file
32
benchmark/single-source/CaptureProp.swift
Normal file
@@ -0,0 +1,32 @@
|
||||
//===--- CaptureProp.swift ------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
func sum(x:Int, y:Int) -> Int {
|
||||
return x + y
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func benchCaptureProp<S : SequenceType
|
||||
>(
|
||||
s:S, _ f:(S.Generator.Element, S.Generator.Element)->S.Generator.Element) -> S.Generator.Element {
|
||||
|
||||
var g = s.generate()
|
||||
let initial = g.next()!
|
||||
return GeneratorSequence(g).reduce(initial, combine: f)
|
||||
}
|
||||
|
||||
public func run_CaptureProp(N: Int) {
|
||||
let a = 1...10_000
|
||||
for _ in 1...100*N {
|
||||
benchCaptureProp(a, sum)
|
||||
}
|
||||
}
|
||||
37
benchmark/single-source/Chars.swift
Normal file
37
benchmark/single-source/Chars.swift
Normal file
@@ -0,0 +1,37 @@
|
||||
//===--- Chars.swift ------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test tests the performance of ASCII Character comparison.
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_Chars(N: Int) {
|
||||
// Permute some characters.
|
||||
let alphabet: [Character] = [
|
||||
"A", "B", "C", "D", "E", "F", "G",
|
||||
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
|
||||
"S", "T", "U",
|
||||
"V", "W", "X", "Y", "Z", "/", "f", "Z", "z", "6", "7", "C", "j", "f", "9",
|
||||
"g", "g", "I", "J", "K", "c", "x", "i", ".",
|
||||
"2", "a", "t", "i", "o", "e", "q", "n", "X", "Y", "Z", "?", "m", "Z", ","
|
||||
]
|
||||
|
||||
for _ in 0...N {
|
||||
for firstChar in alphabet {
|
||||
for middleChar in alphabet {
|
||||
for lastChar in alphabet {
|
||||
_ = ((firstChar == middleChar) != (middleChar < lastChar))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
benchmark/single-source/ClassArrayGetter.swift
Normal file
37
benchmark/single-source/ClassArrayGetter.swift
Normal file
@@ -0,0 +1,37 @@
|
||||
//===--- ClassArrayGetter.swift -------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class Box {
|
||||
var v: Int
|
||||
init(v: Int) { self.v = v }
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func sumArray(a: [Box]) -> Int {
|
||||
var s = 0
|
||||
for i in 0..<a.count {
|
||||
s += a[i].v
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
public func run_ClassArrayGetter(N: Int) {
|
||||
let aSize = 10_000
|
||||
var a: [Box] = []
|
||||
a.reserveCapacity(aSize)
|
||||
for i in 1...aSize {
|
||||
a.append(Box(v:i))
|
||||
}
|
||||
for _ in 1...N {
|
||||
sumArray(a)
|
||||
}
|
||||
}
|
||||
39
benchmark/single-source/DeadArray.swift
Normal file
39
benchmark/single-source/DeadArray.swift
Normal file
@@ -0,0 +1,39 @@
|
||||
//===--- DeadArray.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// rdar://problem/20980377
|
||||
import TestsUtils
|
||||
|
||||
@inline(__always)
|
||||
func debug(m:String) {}
|
||||
|
||||
private var Count = 0
|
||||
|
||||
@inline(never)
|
||||
func bar() { Count += 1 }
|
||||
|
||||
@inline(never)
|
||||
func runLoop(var1: Int, var2: Int) {
|
||||
for _ in 0..<100_000 {
|
||||
debug("Var1: \(var1) Var2: \(var2)")
|
||||
bar()
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_DeadArray(N: Int) {
|
||||
for _ in 1...N {
|
||||
Count = 0
|
||||
runLoop(0, var2: 0)
|
||||
}
|
||||
CheckResults(Count == 100_000, "Incorrect number of calls in loop")
|
||||
}
|
||||
147
benchmark/single-source/DictTest.swift
Normal file
147
benchmark/single-source/DictTest.swift
Normal file
@@ -0,0 +1,147 @@
|
||||
//===--- DictTest.swift ---------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_Dictionary(scale: Int) {
|
||||
let Input = [
|
||||
// Text from http://en.wikipedia.org/wiki/Hash_table
|
||||
"hash", "table",
|
||||
"in", "computing", "a", "hash", "table", "also", "hash", "map", "is",
|
||||
"a", "data", "structure", "used", "to", "implement", "an", "associative",
|
||||
"array", "a", "structure", "that", "can", "map", "keys", "to", "values",
|
||||
"a", "hash", "table", "uses", "a", "hash", "function", "to", "compute",
|
||||
"an", "index", "into", "an", "array", "of", "buckets", "or", "slots",
|
||||
"from", "which", "the", "correct", "value", "can", "be", "found",
|
||||
"ideally", "the", "hash", "function", "will", "assign", "each", "key",
|
||||
"to", "a", "unique", "bucket", "but", "this", "situation", "is",
|
||||
"rarely", "achievable", "in", "practice", "usually", "some", "keys",
|
||||
"will", "hash", "to", "the", "same", "bucket", "instead", "most", "hash",
|
||||
"table", "designs", "assume", "that", "hash", "collisions", "different",
|
||||
"keys", "that", "are", "assigned", "by", "the", "hash", "function", "to",
|
||||
"the", "same", "bucket", "will", "occur", "and", "must", "be",
|
||||
"accommodated", "in", "some", "way", "in", "a", "well", "dimensioned",
|
||||
"hash", "table", "the", "average", "cost", "number", "of",
|
||||
"instructions", "for", "each", "lookup", "is", "independent", "of",
|
||||
"the", "number", "of", "elements", "stored", "in", "the", "table",
|
||||
"many", "hash", "table", "designs", "also", "allow", "arbitrary",
|
||||
"insertions", "and", "deletions", "of", "key", "value", "pairs", "at",
|
||||
"amortized", "constant", "average", "cost", "per", "operation", "in",
|
||||
"many", "situations", "hash", "tables", "turn", "out", "to", "be",
|
||||
"more", "efficient", "than", "search", "trees", "or", "any", "other",
|
||||
"table", "lookup", "structure", "for", "this", "reason", "they", "are",
|
||||
"widely", "used", "in", "many", "kinds", "of", "computer", "software",
|
||||
"particularly", "for", "associative", "arrays", "database", "indexing",
|
||||
"caches", "and", "sets",
|
||||
|
||||
"hashing",
|
||||
"the", "idea", "of", "hashing", "is", "to", "distribute", "the",
|
||||
"entries", "key", "value", "pairs", "across", "an", "array", "of",
|
||||
"buckets", "given", "a", "key", "the", "algorithm", "computes", "an",
|
||||
"index", "that", "suggests", "where", "the", "entry", "can", "be",
|
||||
"found", "index", "f", "key", "array", "size", "often", "this", "is",
|
||||
"done", "in", "two", "steps", "hash", "hashfunc", "key", "index", "hash",
|
||||
"array", "size", "in", "this", "method", "the", "hash", "is",
|
||||
"independent", "of", "the", "array", "size", "and", "it", "is", "then",
|
||||
"reduced", "to", "an", "index", "a", "number", "between", "and", "array",
|
||||
"size", "using", "the", "modulus", "operator", "in", "the", "case",
|
||||
"that", "the", "array", "size", "is", "a", "power", "of", "two", "the",
|
||||
"remainder", "operation", "is", "reduced", "to", "masking", "which",
|
||||
"improves", "speed", "but", "can", "increase", "problems", "with", "a",
|
||||
"poor", "hash", "function",
|
||||
|
||||
"choosing", "a", "good", "hash", "function",
|
||||
"a", "good", "hash", "function", "and", "implementation", "algorithm",
|
||||
"are", "essential", "for", "good", "hash", "table", "performance", "but",
|
||||
"may", "be", "difficult", "to", "achieve", "a", "basic", "requirement",
|
||||
"is", "that", "the", "function", "should", "provide", "a", "uniform",
|
||||
"distribution", "of", "hash", "values", "a", "non", "uniform",
|
||||
"distribution", "increases", "the", "number", "of", "collisions", "and",
|
||||
"the", "cost", "of", "resolving", "them", "uniformity", "is",
|
||||
"sometimes", "difficult", "to", "ensure", "by", "design", "but", "may",
|
||||
"be", "evaluated", "empirically", "using", "statistical", "tests", "e",
|
||||
"g", "a", "pearson", "s", "chi", "squared", "test", "for", "discrete",
|
||||
"uniform", "distributions", "the", "distribution", "needs", "to", "be",
|
||||
"uniform", "only", "for", "table", "sizes", "that", "occur", "in", "the",
|
||||
"application", "in", "particular", "if", "one", "uses", "dynamic",
|
||||
"resizing", "with", "exact", "doubling", "and", "halving", "of", "the",
|
||||
"table", "size", "s", "then", "the", "hash", "function", "needs", "to",
|
||||
"be", "uniform", "only", "when", "s", "is", "a", "power", "of", "two",
|
||||
"on", "the", "other", "hand", "some", "hashing", "algorithms", "provide",
|
||||
"uniform", "hashes", "only", "when", "s", "is", "a", "prime", "number",
|
||||
"for", "open", "addressing", "schemes", "the", "hash", "function",
|
||||
"should", "also", "avoid", "clustering", "the", "mapping", "of", "two",
|
||||
"or", "more", "keys", "to", "consecutive", "slots", "such", "clustering",
|
||||
"may", "cause", "the", "lookup", "cost", "to", "skyrocket", "even", "if",
|
||||
"the", "load", "factor", "is", "low", "and", "collisions", "are",
|
||||
"infrequent", "the", "popular", "multiplicative", "hash", "3", "is",
|
||||
"claimed", "to", "have", "particularly", "poor", "clustering",
|
||||
"behavior", "cryptographic", "hash", "functions", "are", "believed",
|
||||
"to", "provide", "good", "hash", "functions", "for", "any", "table",
|
||||
"size", "s", "either", "by", "modulo", "reduction", "or", "by", "bit",
|
||||
"masking", "they", "may", "also", "be", "appropriate", "if", "there",
|
||||
"is", "a", "risk", "of", "malicious", "users", "trying", "to",
|
||||
"sabotage", "a", "network", "service", "by", "submitting", "requests",
|
||||
"designed", "to", "generate", "a", "large", "number", "of", "collisions",
|
||||
"in", "the", "server", "s", "hash", "tables", "however", "the", "risk",
|
||||
"of", "sabotage", "can", "also", "be", "avoided", "by", "cheaper",
|
||||
"methods", "such", "as", "applying", "a", "secret", "salt", "to", "the",
|
||||
"data", "or", "using", "a", "universal", "hash", "function",
|
||||
|
||||
"perfect", "hash", "function",
|
||||
"if", "all", "keys", "are", "known", "ahead", "of", "time", "a",
|
||||
"perfect", "hash", "function", "can", "be", "used", "to", "create", "a",
|
||||
"perfect", "hash", "table", "that", "has", "no", "collisions", "if",
|
||||
"minimal", "perfect", "hashing", "is", "used", "every", "location", "in",
|
||||
"the", "hash", "table", "can", "be", "used", "as", "well", "perfect",
|
||||
"hashing", "allows", "for", "constant", "time", "lookups", "in", "the",
|
||||
"worst", "case", "this", "is", "in", "contrast", "to", "most",
|
||||
"chaining", "and", "open", "addressing", "methods", "where", "the",
|
||||
"time", "for", "lookup", "is", "low", "on", "average", "but", "may",
|
||||
"be", "very", "large", "proportional", "to", "the", "number", "of",
|
||||
"entries", "for", "some", "sets", "of", "keys"
|
||||
]
|
||||
|
||||
var Dict: Dictionary<String, Bool> = [:]
|
||||
let N = 5*scale
|
||||
|
||||
// Check performance of filling the dictionary:
|
||||
for _ in 1...N {
|
||||
Dict = [:]
|
||||
for word in Input {
|
||||
Dict[word] = true;
|
||||
}
|
||||
}
|
||||
CheckResults(Dict.count == 270,
|
||||
"IncorrectResults in DictTest: \(Dict.count) != 270.")
|
||||
|
||||
// Check performance of searching in the dictionary:
|
||||
// Fill the dictionary with words from the first half of the text
|
||||
Dict = [:]
|
||||
for i in 0 ..< Input.count/2 {
|
||||
let word = Input[i]
|
||||
Dict[word] = true
|
||||
}
|
||||
|
||||
// Count number of words from the first half in the entire text
|
||||
var count = 0
|
||||
for _ in 1...N {
|
||||
for word in Input {
|
||||
if Dict[word] != nil {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
CheckResults(count == N*541,
|
||||
"IncorrectResults in DictTest: \(count) != \(N*541).")
|
||||
}
|
||||
38
benchmark/single-source/DictTest2.swift
Normal file
38
benchmark/single-source/DictTest2.swift
Normal file
@@ -0,0 +1,38 @@
|
||||
//===--- DictTest2.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_Dictionary2(N: Int) {
|
||||
let size = 500
|
||||
let ref_result = 199
|
||||
var res = 0
|
||||
for _ in 1...5*N {
|
||||
var x: [String:Int] = [:]
|
||||
for i in 1...size {
|
||||
x[String(i, radix:16)] = i
|
||||
}
|
||||
|
||||
res = 0
|
||||
for i in 0..<size {
|
||||
let i2 = size-i
|
||||
if x[String(i2)] != nil {
|
||||
res += 1
|
||||
}
|
||||
}
|
||||
if res != ref_result {
|
||||
break
|
||||
}
|
||||
}
|
||||
CheckResults(res == ref_result, "Incorrect results in Dictionary2: \(res) != \(ref_result)")
|
||||
}
|
||||
45
benchmark/single-source/DictTest3.swift
Normal file
45
benchmark/single-source/DictTest3.swift
Normal file
@@ -0,0 +1,45 @@
|
||||
//===--- DictTest3.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_Dictionary3(N: Int) {
|
||||
let size1 = 100
|
||||
let reps = 20
|
||||
let ref_result = "1 99 20 1980"
|
||||
var hash1 = [String:Int]()
|
||||
var hash2 = [String:Int]()
|
||||
var res = ""
|
||||
|
||||
for _ in 1...N {
|
||||
hash1 = [:]
|
||||
for i in 0..<size1 {
|
||||
hash1["foo_" + String(i)] = i
|
||||
}
|
||||
|
||||
hash2 = hash1
|
||||
|
||||
for _ in 1..<reps {
|
||||
for (k, v) in hash1 {
|
||||
hash2[k] = hash2[k]! + v
|
||||
}
|
||||
}
|
||||
|
||||
res = (String(hash1["foo_1"]!) + " " + String(hash1["foo_99"]!) + " " +
|
||||
String(hash2["foo_1"]!) + " " + String(hash2["foo_99"]!))
|
||||
if res != ref_result {
|
||||
break
|
||||
}
|
||||
}
|
||||
CheckResults(res == ref_result, "Incorrect results in Dictionary3: \(res) != \(ref_result)")
|
||||
}
|
||||
59
benchmark/single-source/DictionaryBridge.swift
Normal file
59
benchmark/single-source/DictionaryBridge.swift
Normal file
@@ -0,0 +1,59 @@
|
||||
//===--- DictionaryBridge.swift -------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// benchmark to test the performance of bridging an NSDictionary to a
|
||||
// Swift.Dictionary.
|
||||
|
||||
import Foundation
|
||||
import TestsUtils
|
||||
|
||||
class Thing : NSObject {
|
||||
|
||||
required override init() {
|
||||
let c = self.dynamicType.col()
|
||||
CheckResults(c!.count == 10, "The rules of the universe apply")
|
||||
}
|
||||
|
||||
private class func col() -> [String : AnyObject]? {
|
||||
let dict = NSMutableDictionary()
|
||||
dict.setValue(1, forKey: "one")
|
||||
dict.setValue(2, forKey: "two")
|
||||
dict.setValue(3, forKey: "three")
|
||||
dict.setValue(4, forKey: "four")
|
||||
dict.setValue(5, forKey: "five")
|
||||
dict.setValue(6, forKey: "six")
|
||||
dict.setValue(7, forKey: "seven")
|
||||
dict.setValue(8, forKey: "eight")
|
||||
dict.setValue(9, forKey: "nine")
|
||||
dict.setValue(10, forKey: "ten")
|
||||
|
||||
return NSDictionary(dictionary: dict) as? [String: AnyObject]
|
||||
}
|
||||
|
||||
class func mk() -> Thing {
|
||||
return self.init()
|
||||
}
|
||||
}
|
||||
|
||||
class Stuff {
|
||||
var c : Thing = Thing.mk()
|
||||
init() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_DictionaryBridge(N: Int) {
|
||||
for _ in 1...100*N {
|
||||
_ = Stuff()
|
||||
}
|
||||
}
|
||||
27
benchmark/single-source/DictionaryLiteral.swift
Normal file
27
benchmark/single-source/DictionaryLiteral.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
//===--- DictionaryLiteral.swift ------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Dictionary creation from literals benchmark
|
||||
// rdar://problem/19804127
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
func makeDictionary() -> [Int: Int] {
|
||||
return [1: 3, 2: 2, 3: 1]
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_DictionaryLiteral(N: Int) {
|
||||
for _ in 1...10000*N {
|
||||
makeDictionary()
|
||||
}
|
||||
}
|
||||
43
benchmark/single-source/DictionaryRemove.swift
Normal file
43
benchmark/single-source/DictionaryRemove.swift
Normal file
@@ -0,0 +1,43 @@
|
||||
//===--- DictionaryRemove.swift -------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Dictionary element removal benchmark
|
||||
// rdar://problem/19804127
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_DictionaryRemove(N: Int) {
|
||||
let size = 100
|
||||
var dict = [Int: Int](minimumCapacity: size)
|
||||
|
||||
// Fill dictionary
|
||||
for i in 1...size {
|
||||
dict[i] = i
|
||||
}
|
||||
CheckResults(dict.count == size,
|
||||
"Incorrect dict count: \(dict.count) != \(size).")
|
||||
|
||||
var tmpDict = dict
|
||||
for _ in 1...1000*N {
|
||||
tmpDict = dict
|
||||
// Empty dictionary
|
||||
for i in 1...size {
|
||||
tmpDict.removeValueForKey(i)
|
||||
}
|
||||
if !tmpDict.isEmpty {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
CheckResults(tmpDict.isEmpty,
|
||||
"tmpDict should be empty: \(tmpDict.count) != 0.")
|
||||
}
|
||||
46
benchmark/single-source/DictionarySwap.swift
Normal file
46
benchmark/single-source/DictionarySwap.swift
Normal file
@@ -0,0 +1,46 @@
|
||||
//===--- DictionarySwap.swift ---------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Dictionary element swapping benchmark
|
||||
// rdar://problem/19804127
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_DictionarySwap(N: Int) {
|
||||
let size = 100
|
||||
var dict = [Int: Int](minimumCapacity: size)
|
||||
|
||||
// Fill dictionary
|
||||
for i in 1...size {
|
||||
dict[i] = i
|
||||
}
|
||||
CheckResults(dict.count == size,
|
||||
"Incorrect dict count: \(dict.count) != \(size).")
|
||||
|
||||
var swapped = false
|
||||
for _ in 1...10000*N {
|
||||
swap(&dict[25]!, &dict[75]!)
|
||||
swapped = !swapped
|
||||
if !swappedCorrectly(swapped, dict[25]!, dict[75]!) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
CheckResults(swappedCorrectly(swapped, dict[25]!, dict[75]!),
|
||||
"Dictionary value swap failed")
|
||||
}
|
||||
|
||||
// Return true if correctly swapped, false otherwise
|
||||
func swappedCorrectly(swapped: Bool, _ p25: Int, _ p75: Int) -> Bool {
|
||||
return swapped && (p25 == 75 && p75 == 25) ||
|
||||
!swapped && (p25 == 25 && p75 == 75)
|
||||
}
|
||||
41
benchmark/single-source/ErrorHandling.swift
Normal file
41
benchmark/single-source/ErrorHandling.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
//===--- ErrorHandling.swift ----------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
enum PizzaError : ErrorType {
|
||||
case Pepperoni, Olives, Anchovy
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func doSomething() throws -> String {
|
||||
var sb = "pi"
|
||||
for str in ["z","z","a","?","?","?"] {
|
||||
sb += str
|
||||
if sb == "pizza" {
|
||||
throw PizzaError.Anchovy
|
||||
}
|
||||
}
|
||||
return sb
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ErrorHandling(N: Int) {
|
||||
for _ in 1...5000*N {
|
||||
do {
|
||||
try doSomething()
|
||||
} catch _ {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
43
benchmark/single-source/Fibonacci.swift
Normal file
43
benchmark/single-source/Fibonacci.swift
Normal file
@@ -0,0 +1,43 @@
|
||||
//===--- Fibonacci.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
func fibonacci(n: Int) -> Int {
|
||||
if (n < 2) { return 1 }
|
||||
return fibonacci(n - 2) + fibonacci(n - 1)
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func Fibonacci(n: Int) -> Int {
|
||||
// This if prevents optimizer from computing return value of Fibonacci(32)
|
||||
// at compile time.
|
||||
if False() { return 0 }
|
||||
|
||||
if (n < 2) { return 1 }
|
||||
return fibonacci(n - 2) + fibonacci(n - 1)
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_Fibonacci(N: Int) {
|
||||
let n = 32
|
||||
let ref_result = 3524578
|
||||
var result = 0
|
||||
for _ in 1...N {
|
||||
result = Fibonacci(n)
|
||||
if result != ref_result {
|
||||
break
|
||||
}
|
||||
}
|
||||
CheckResults(result == ref_result,
|
||||
"Incorrect results in Fibonacci: \(result) != \(ref_result)")
|
||||
}
|
||||
33
benchmark/single-source/GlobalClass.swift
Normal file
33
benchmark/single-source/GlobalClass.swift
Normal file
@@ -0,0 +1,33 @@
|
||||
//===--- GlobalClass.swift ------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Test inline cache with a global class. Make sure the retain|release pair
|
||||
// for the fast path is removed in the loop.
|
||||
import TestsUtils
|
||||
|
||||
class A
|
||||
{
|
||||
func f(a : Int) -> Int
|
||||
{
|
||||
return a + 1
|
||||
}
|
||||
}
|
||||
|
||||
var x = 0
|
||||
var a = A()
|
||||
@inline(never)
|
||||
public func run_GlobalClass(N: Int) {
|
||||
for _ in 0..<N
|
||||
{
|
||||
x = a.f(x)
|
||||
}
|
||||
}
|
||||
48
benchmark/single-source/Hanoi.swift
Normal file
48
benchmark/single-source/Hanoi.swift
Normal file
@@ -0,0 +1,48 @@
|
||||
//===--- Hanoi.swift ------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test checks performance of Swift hanoi tower.
|
||||
// <rdar://problem/22151932>
|
||||
import Foundation
|
||||
import TestsUtils
|
||||
|
||||
struct Move {
|
||||
var from: String
|
||||
var to : String
|
||||
init(from:String, to:String) {
|
||||
self.from = from
|
||||
self.to = to
|
||||
}
|
||||
}
|
||||
|
||||
class TowersOfHanoi {
|
||||
// Record all moves made.
|
||||
var moves : [Move] = [Move]()
|
||||
|
||||
func solve(n: Int, start: String, auxiliary: String, end: String) {
|
||||
if (n == 1) {
|
||||
moves.append(Move(from:start, to:end))
|
||||
} else {
|
||||
solve(n - 1, start: start, auxiliary: end, end: auxiliary)
|
||||
moves.append(Move(from:start, to:end))
|
||||
solve(n - 1, start: auxiliary, auxiliary: start, end: end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_Hanoi(N: Int) {
|
||||
for _ in 1...100*N {
|
||||
let hanoi: TowersOfHanoi = TowersOfHanoi()
|
||||
hanoi.solve(10, start: "A", auxiliary: "B", end: "C")
|
||||
}
|
||||
}
|
||||
682
benchmark/single-source/Hash.swift
Normal file
682
benchmark/single-source/Hash.swift
Normal file
@@ -0,0 +1,682 @@
|
||||
//===--- Hash.swift -------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Derived from the C samples in:
|
||||
// Source: http://en.wikipedia.org/wiki/MD5 and
|
||||
// http://en.wikipedia.org/wiki/SHA-1
|
||||
import TestsUtils
|
||||
|
||||
class Hash {
|
||||
/// \brief C'tor.
|
||||
init(_ bs: Int) {
|
||||
blocksize = bs
|
||||
messageLength = 0
|
||||
dataLength = 0
|
||||
assert(blocksize <= 64, "Invalid block size")
|
||||
}
|
||||
|
||||
/// \brief Add the bytes in \p Msg to the hash.
|
||||
func update(Msg: String) {
|
||||
for c in Msg.unicodeScalars {
|
||||
data[dataLength] = UInt8(ascii: c)
|
||||
dataLength += 1
|
||||
messageLength += 1
|
||||
if dataLength == blocksize { hash() }
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Add the bytes in \p Msg to the hash.
|
||||
func update(Msg: [UInt8]) {
|
||||
for c in Msg {
|
||||
data[dataLength] = c
|
||||
dataLength += 1
|
||||
messageLength += 1
|
||||
if dataLength == blocksize { hash() }
|
||||
}
|
||||
}
|
||||
|
||||
/// \returns the hash of the data that was updated.
|
||||
func digest() -> String {
|
||||
fillBlock()
|
||||
hash()
|
||||
let x = hashState()
|
||||
return x
|
||||
}
|
||||
|
||||
func digestFast(inout Res : [UInt8]) {
|
||||
fillBlock()
|
||||
hash()
|
||||
// We use [UInt8] to avoid using String::apend.
|
||||
hashStateFast(&Res)
|
||||
}
|
||||
|
||||
// private:
|
||||
|
||||
// Hash state:
|
||||
final var messageLength : Int = 0
|
||||
final var dataLength : Int = 0
|
||||
final var data = [UInt8](count: 64, repeatedValue: 0)
|
||||
final var blocksize : Int
|
||||
|
||||
/// \brief Hash the internal data.
|
||||
func hash() {
|
||||
fatalError("Pure virtual")
|
||||
}
|
||||
|
||||
/// \returns a string representation of the state.
|
||||
func hashState() -> String {
|
||||
fatalError("Pure virtual")
|
||||
}
|
||||
func hashStateFast(inout Res : [UInt8]) {
|
||||
fatalError("Pure virtual")
|
||||
}
|
||||
|
||||
/// \brief Blow the data to fill the block.
|
||||
func fillBlock() {
|
||||
fatalError("Pure virtual")
|
||||
}
|
||||
|
||||
var HexTbl = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"]
|
||||
final
|
||||
var HexTblFast : [UInt8] = [48,49,50,51,52,53,54,55,56,57,97,98,99,100,101,102]
|
||||
|
||||
/// \brief Convert a 4-byte integer to a hex string.
|
||||
final
|
||||
func toHex(In: UInt32) -> String {
|
||||
var In = In
|
||||
var Res = ""
|
||||
for _ in 0..<8 {
|
||||
Res = HexTbl[Int(In & 0xF)] + Res
|
||||
In = In >> 4
|
||||
}
|
||||
return Res
|
||||
}
|
||||
|
||||
final
|
||||
func toHexFast(In: UInt32, inout _ Res: Array<UInt8>, _ Index : Int) {
|
||||
var In = In
|
||||
for i in 0..<4 {
|
||||
// Convert one byte each iteration.
|
||||
Res[Index + 2*i] = HexTblFast[Int(In >> 4) & 0xF]
|
||||
Res[Index + 2*i + 1] = HexTblFast[Int(In & 0xF)]
|
||||
In = In >> 8
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Left-rotate \p x by \p c.
|
||||
final
|
||||
func rol(x: UInt32, _ c: UInt32) -> UInt32 {
|
||||
// TODO: use the &>> operator.
|
||||
let a = UInt32(truncatingBitPattern: Int64(x) << Int64(c))
|
||||
let b = UInt32(truncatingBitPattern: Int64(x) >> (32 - Int64(c)))
|
||||
return a|b
|
||||
}
|
||||
|
||||
/// \brief Right-rotate \p x by \p c.
|
||||
final
|
||||
func ror(x: UInt32, _ c: UInt32) -> UInt32 {
|
||||
// TODO: use the &>> operator.
|
||||
let a = UInt32(truncatingBitPattern: Int64(x) >> Int64(c))
|
||||
let b = UInt32(truncatingBitPattern: Int64(x) << (32 - Int64(c)))
|
||||
return a|b
|
||||
}
|
||||
}
|
||||
|
||||
final
|
||||
class MD5 : Hash {
|
||||
// Integer part of the sines of integers (in radians) * 2^32.
|
||||
var k : [UInt32] = [0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 ]
|
||||
|
||||
// Per-round shift amounts
|
||||
var r : [UInt32] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
|
||||
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]
|
||||
|
||||
// State
|
||||
var h0 : UInt32 = 0
|
||||
var h1 : UInt32 = 0
|
||||
var h2 : UInt32 = 0
|
||||
var h3 : UInt32 = 0
|
||||
|
||||
init() {
|
||||
super.init(64)
|
||||
reset()
|
||||
}
|
||||
|
||||
func reset() {
|
||||
// Set the initial values.
|
||||
h0 = 0x67452301
|
||||
h1 = 0xefcdab89
|
||||
h2 = 0x98badcfe
|
||||
h3 = 0x10325476
|
||||
messageLength = 0
|
||||
dataLength = 0
|
||||
}
|
||||
|
||||
func appendBytes(Val: Int, inout _ Message: Array<UInt8>, _ Offset : Int) {
|
||||
Message[Offset] = UInt8(truncatingBitPattern: Val)
|
||||
Message[Offset + 1] = UInt8(truncatingBitPattern: Val >> 8)
|
||||
Message[Offset + 2] = UInt8(truncatingBitPattern: Val >> 16)
|
||||
Message[Offset + 3] = UInt8(truncatingBitPattern: Val >> 24)
|
||||
}
|
||||
|
||||
override
|
||||
func fillBlock() {
|
||||
// Pre-processing:
|
||||
// Append "1" bit to message
|
||||
// Append "0" bits until message length in bits -> 448 (mod 512)
|
||||
// Append length mod (2^64) to message
|
||||
|
||||
var new_len = messageLength + 1
|
||||
while (new_len % (512/8) != 448/8) {
|
||||
new_len += 1
|
||||
}
|
||||
|
||||
// Append the "1" bit - most significant bit is "first"
|
||||
data[dataLength] = UInt8(0x80)
|
||||
dataLength += 1
|
||||
|
||||
// Append "0" bits
|
||||
for _ in 0..<(new_len - (messageLength + 1)) {
|
||||
if dataLength == blocksize { hash() }
|
||||
data[dataLength] = UInt8(0)
|
||||
dataLength += 1
|
||||
}
|
||||
|
||||
// Append the len in bits at the end of the buffer.
|
||||
// initial_len>>29 == initial_len*8>>32, but avoids overflow.
|
||||
appendBytes(messageLength * 8, &data, dataLength)
|
||||
appendBytes(messageLength>>29 * 8, &data, dataLength+4)
|
||||
dataLength += 8
|
||||
}
|
||||
|
||||
func toUInt32(Message: Array<UInt8>, _ Offset: Int) -> UInt32 {
|
||||
let first = UInt32(Message[Offset + 0])
|
||||
let second = UInt32(Message[Offset + 1]) << 8
|
||||
let third = UInt32(Message[Offset + 2]) << 16
|
||||
let fourth = UInt32(Message[Offset + 3]) << 24
|
||||
return first | second | third | fourth
|
||||
}
|
||||
|
||||
var w = [UInt32](count: 16, repeatedValue: 0)
|
||||
override
|
||||
func hash() {
|
||||
assert(dataLength == blocksize, "Invalid block size")
|
||||
|
||||
// Break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15
|
||||
for i in 0..<16 {
|
||||
w[i] = toUInt32(data, i*4)
|
||||
}
|
||||
|
||||
// We don't need the original data anymore.
|
||||
dataLength = 0
|
||||
|
||||
var a = h0
|
||||
var b = h1
|
||||
var c = h2
|
||||
var d = h3
|
||||
var f, g : UInt32
|
||||
|
||||
// Main loop:
|
||||
for i in 0..<64 {
|
||||
if i < 16 {
|
||||
f = (b & c) | ((~b) & d)
|
||||
g = UInt32(i)
|
||||
} else if i < 32 {
|
||||
f = (d & b) | ((~d) & c)
|
||||
g = UInt32(5*i + 1) % 16
|
||||
} else if i < 48 {
|
||||
f = b ^ c ^ d
|
||||
g = UInt32(3*i + 5) % 16
|
||||
} else {
|
||||
f = c ^ (b | (~d))
|
||||
g = UInt32(7*i) % 16
|
||||
}
|
||||
|
||||
let temp = d
|
||||
d = c
|
||||
c = b
|
||||
b = b &+ rol(a &+ f &+ k[i] &+ w[Int(g)], r[i])
|
||||
a = temp
|
||||
}
|
||||
|
||||
// Add this chunk's hash to result so far:
|
||||
h0 = a &+ h0
|
||||
h1 = b &+ h1
|
||||
h2 = c &+ h2
|
||||
h3 = d &+ h3
|
||||
}
|
||||
|
||||
func reverseBytes(In: UInt32) -> UInt32 {
|
||||
let B0 = (In >> 0 ) & 0xFF
|
||||
let B1 = (In >> 8 ) & 0xFF
|
||||
let B2 = (In >> 16) & 0xFF
|
||||
let B3 = (In >> 24) & 0xFF
|
||||
return (B0 << 24) | (B1 << 16) | (B2 << 8) | B3
|
||||
}
|
||||
|
||||
override
|
||||
func hashState() -> String {
|
||||
var S = ""
|
||||
for h in [h0, h1, h2, h3] {
|
||||
S += toHex(reverseBytes(h))
|
||||
}
|
||||
return S
|
||||
}
|
||||
|
||||
override
|
||||
func hashStateFast(inout Res : [UInt8]) {
|
||||
#if !NO_RANGE
|
||||
var Idx : Int = 0
|
||||
for h in [h0, h1, h2, h3] {
|
||||
toHexFast(h, &Res, Idx)
|
||||
Idx += 8
|
||||
}
|
||||
#else
|
||||
toHexFast(h0, &Res, 0)
|
||||
toHexFast(h1, &Res, 8)
|
||||
toHexFast(h2, &Res, 16)
|
||||
toHexFast(h3, &Res, 24)
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SHA1 : Hash {
|
||||
// State
|
||||
var h0 : UInt32 = 0
|
||||
var h1 : UInt32 = 0
|
||||
var h2 : UInt32 = 0
|
||||
var h3 : UInt32 = 0
|
||||
var h4 : UInt32 = 0
|
||||
|
||||
init() {
|
||||
super.init(64)
|
||||
reset()
|
||||
}
|
||||
|
||||
func reset() {
|
||||
// Set the initial values.
|
||||
h0 = 0x67452301
|
||||
h1 = 0xEFCDAB89
|
||||
h2 = 0x98BADCFE
|
||||
h3 = 0x10325476
|
||||
h4 = 0xC3D2E1F0
|
||||
messageLength = 0
|
||||
dataLength = 0
|
||||
}
|
||||
|
||||
override
|
||||
func fillBlock() {
|
||||
// Append a 1 to the message.
|
||||
data[dataLength] = UInt8(0x80)
|
||||
dataLength += 1
|
||||
|
||||
var new_len = messageLength + 1
|
||||
while ((new_len % 64) != 56) {
|
||||
new_len += 1
|
||||
}
|
||||
|
||||
for _ in 0..<new_len - (messageLength + 1) {
|
||||
if dataLength == blocksize { hash() }
|
||||
data[dataLength] = UInt8(0x0)
|
||||
dataLength += 1
|
||||
}
|
||||
|
||||
// Append the original message length as 64bit big endian:
|
||||
let len_in_bits = Int64(messageLength)*8
|
||||
for i in 0..<8 {
|
||||
let val = (len_in_bits >> ((7-i)*8)) & 0xFF
|
||||
data[dataLength] = UInt8(val)
|
||||
dataLength += 1
|
||||
}
|
||||
}
|
||||
|
||||
override
|
||||
func hash() {
|
||||
assert(dataLength == blocksize, "Invalid block size")
|
||||
|
||||
// Init the "W" buffer.
|
||||
var w = [UInt32](count: 80, repeatedValue: 0)
|
||||
|
||||
// Convert the Byte array to UInt32 array.
|
||||
var word : UInt32 = 0
|
||||
for i in 0..<64 {
|
||||
word = word << 8
|
||||
word = word &+ UInt32(data[i])
|
||||
if i%4 == 3 { w[i/4] = word; word = 0 }
|
||||
}
|
||||
|
||||
// Init the rest of the "W" buffer.
|
||||
for t in 16..<80 {
|
||||
w[t] = rol((w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16]) ,1)
|
||||
}
|
||||
|
||||
dataLength = 0
|
||||
|
||||
var A = h0
|
||||
var B = h1
|
||||
var C = h2
|
||||
var D = h3
|
||||
var E = h4
|
||||
var K : UInt32, F : UInt32
|
||||
|
||||
for t in 0..<80 {
|
||||
if t < 20 {
|
||||
K = 0x5a827999
|
||||
F = (B & C) | ((B ^ 0xFFFFFFFF) & D)
|
||||
} else if t < 40 {
|
||||
K = 0x6ed9eba1
|
||||
F = B ^ C ^ D
|
||||
} else if t < 60 {
|
||||
K = 0x8f1bbcdc
|
||||
F = (B & C) | (B & D) | (C & D)
|
||||
} else {
|
||||
K = 0xca62c1d6
|
||||
F = B ^ C ^ D
|
||||
}
|
||||
let Temp : UInt32 = rol(A,5) &+ F &+ E &+ w[t] &+ K
|
||||
|
||||
E = D
|
||||
D = C
|
||||
C = rol(B,30)
|
||||
B = A
|
||||
A = Temp
|
||||
}
|
||||
|
||||
h0 = h0 &+ A
|
||||
h1 = h1 &+ B
|
||||
h2 = h2 &+ C
|
||||
h3 = h3 &+ D
|
||||
h4 = h4 &+ E
|
||||
}
|
||||
|
||||
override
|
||||
func hashState() -> String {
|
||||
var Res : String = ""
|
||||
for state in [h0, h1, h2, h3, h4] {
|
||||
Res += toHex(state)
|
||||
}
|
||||
return Res
|
||||
}
|
||||
}
|
||||
|
||||
class SHA256 : Hash {
|
||||
// State
|
||||
var h0 : UInt32 = 0
|
||||
var h1 : UInt32 = 0
|
||||
var h2 : UInt32 = 0
|
||||
var h3 : UInt32 = 0
|
||||
var h4 : UInt32 = 0
|
||||
var h5 : UInt32 = 0
|
||||
var h6 : UInt32 = 0
|
||||
var h7 : UInt32 = 0
|
||||
|
||||
var k : [UInt32] = [
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]
|
||||
|
||||
init() {
|
||||
super.init(64)
|
||||
reset()
|
||||
}
|
||||
|
||||
func reset() {
|
||||
// Set the initial values.
|
||||
h0 = 0x6a09e667
|
||||
h1 = 0xbb67ae85
|
||||
h2 = 0x3c6ef372
|
||||
h3 = 0xa54ff53a
|
||||
h4 = 0x510e527f
|
||||
h5 = 0x9b05688c
|
||||
h6 = 0x1f83d9ab
|
||||
h7 = 0x5be0cd19
|
||||
messageLength = 0
|
||||
dataLength = 0
|
||||
}
|
||||
|
||||
override
|
||||
func fillBlock() {
|
||||
// Append a 1 to the message.
|
||||
data[dataLength] = UInt8(0x80)
|
||||
dataLength += 1
|
||||
|
||||
var new_len = messageLength + 1
|
||||
while ((new_len % 64) != 56) {
|
||||
new_len += 1
|
||||
}
|
||||
|
||||
for _ in 0..<new_len - (messageLength+1) {
|
||||
if dataLength == blocksize { hash() }
|
||||
data[dataLength] = UInt8(0)
|
||||
dataLength += 1
|
||||
}
|
||||
|
||||
// Append the original message length as 64bit big endian:
|
||||
let len_in_bits = Int64(messageLength)*8
|
||||
for i in 0..<8 {
|
||||
let val = (len_in_bits >> ((7-i)*8)) & 0xFF
|
||||
data[dataLength] = UInt8(val)
|
||||
dataLength += 1
|
||||
}
|
||||
}
|
||||
|
||||
override
|
||||
func hash() {
|
||||
assert(dataLength == blocksize, "Invalid block size")
|
||||
|
||||
// Init the "W" buffer.
|
||||
var w = [UInt32](count: 64, repeatedValue: 0)
|
||||
|
||||
// Convert the Byte array to UInt32 array.
|
||||
var word : UInt32 = 0
|
||||
for i in 0..<64 {
|
||||
word = word << 8
|
||||
word = word &+ UInt32(data[i])
|
||||
if i%4 == 3 { w[i/4] = word; word = 0 }
|
||||
}
|
||||
|
||||
// Init the rest of the "W" buffer.
|
||||
for i in 16..<64 {
|
||||
let s0 = ror(w[i-15], 7) ^ ror(w[i-15], 18) ^ (w[i-15] >> 3)
|
||||
let s1 = ror(w[i-2], 17) ^ ror(w[i-2], 19) ^ (w[i-2] >> 10)
|
||||
w[i] = w[i-16] &+ s0 &+ w[i-7] &+ s1
|
||||
}
|
||||
|
||||
dataLength = 0
|
||||
|
||||
var a = h0
|
||||
var b = h1
|
||||
var c = h2
|
||||
var d = h3
|
||||
var e = h4
|
||||
var f = h5
|
||||
var g = h6
|
||||
var h = h7
|
||||
|
||||
for i in 0..<64 {
|
||||
let S1 = ror(e, 6) ^ ror(e, 11) ^ ror(e, 25)
|
||||
let ch = (e & f) ^ ((~e) & g)
|
||||
let temp1 = h &+ S1 &+ ch &+ k[i] &+ w[i]
|
||||
let S0 = ror(a, 2) ^ ror(a, 13) ^ ror(a, 22)
|
||||
let maj = (a & b) ^ (a & c) ^ (b & c)
|
||||
let temp2 = S0 &+ maj
|
||||
|
||||
h = g
|
||||
g = f
|
||||
f = e
|
||||
e = d &+ temp1
|
||||
d = c
|
||||
c = b
|
||||
b = a
|
||||
a = temp1 &+ temp2
|
||||
}
|
||||
|
||||
h0 = h0 &+ a
|
||||
h1 = h1 &+ b
|
||||
h2 = h2 &+ c
|
||||
h3 = h3 &+ d
|
||||
h4 = h4 &+ e
|
||||
h5 = h5 &+ f
|
||||
h6 = h6 &+ g
|
||||
h7 = h7 &+ h
|
||||
}
|
||||
|
||||
override
|
||||
func hashState() -> String {
|
||||
var Res : String = ""
|
||||
for state in [h0, h1, h2, h3, h4, h5, h6, h7] {
|
||||
Res += toHex(state)
|
||||
}
|
||||
return Res
|
||||
}
|
||||
}
|
||||
|
||||
func == (lhs: [UInt8], rhs: [UInt8]) -> Bool {
|
||||
if lhs.count != rhs.count { return false }
|
||||
for idx in 0..<lhs.count {
|
||||
if lhs[idx] != rhs[idx] { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_HashTest(N: Int) {
|
||||
let TestMD5 = ["" : "d41d8cd98f00b204e9800998ecf8427e",
|
||||
"The quick brown fox jumps over the lazy dog." : "e4d909c290d0fb1ca068ffaddf22cbd0",
|
||||
"The quick brown fox jumps over the lazy cog." : "68aa5deab43e4df2b5e1f80190477fb0"]
|
||||
|
||||
let TestSHA1 = ["" : "da39a3ee5e6b4b0d3255bfef95601890afd80709",
|
||||
"The quick brown fox jumps over the lazy dog" : "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
|
||||
"The quick brown fox jumps over the lazy cog" : "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"]
|
||||
|
||||
let TestSHA256 = ["" : "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"The quick brown fox jumps over the lazy dog" : "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592",
|
||||
"The quick brown fox jumps over the lazy dog." : "ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c"]
|
||||
let size = 50
|
||||
|
||||
for _ in 1...10*N {
|
||||
// Check for precomputed values.
|
||||
let MD = MD5()
|
||||
for (K, V) in TestMD5 {
|
||||
MD.update(K)
|
||||
CheckResults(MD.digest() == V,
|
||||
"Incorrect result in Hash: check 1 failed.")
|
||||
MD.reset()
|
||||
}
|
||||
|
||||
// Check that we don't crash on large strings.
|
||||
var S : String = ""
|
||||
for _ in 1...size {
|
||||
S += "a"
|
||||
MD.reset()
|
||||
MD.update(S)
|
||||
}
|
||||
|
||||
// Check that the order in which we push values does not change the result.
|
||||
MD.reset()
|
||||
var L : String = ""
|
||||
for _ in 1...size {
|
||||
L += "a"
|
||||
MD.update("a")
|
||||
}
|
||||
let MD2 = MD5()
|
||||
MD2.update(L)
|
||||
CheckResults(MD.digest() == MD2.digest(),
|
||||
"Incorrect result in Hash: check 2 failed.")
|
||||
|
||||
// Test the famous MD5 collision from 2009: http://www.mscs.dal.ca/~selinger/md5collision/
|
||||
let Src1 : [UInt8] =
|
||||
[0xd1, 0x31, 0xdd, 0x02, 0xc5, 0xe6, 0xee, 0xc4, 0x69, 0x3d, 0x9a, 0x06, 0x98, 0xaf, 0xf9, 0x5c, 0x2f, 0xca, 0xb5, 0x87, 0x12, 0x46, 0x7e, 0xab, 0x40, 0x04, 0x58, 0x3e, 0xb8, 0xfb, 0x7f, 0x89,
|
||||
0x55, 0xad, 0x34, 0x06, 0x09, 0xf4, 0xb3, 0x02, 0x83, 0xe4, 0x88, 0x83, 0x25, 0x71, 0x41, 0x5a, 0x08, 0x51, 0x25, 0xe8, 0xf7, 0xcd, 0xc9, 0x9f, 0xd9, 0x1d, 0xbd, 0xf2, 0x80, 0x37, 0x3c, 0x5b,
|
||||
0xd8, 0x82, 0x3e, 0x31, 0x56, 0x34, 0x8f, 0x5b, 0xae, 0x6d, 0xac, 0xd4, 0x36, 0xc9, 0x19, 0xc6, 0xdd, 0x53, 0xe2, 0xb4, 0x87, 0xda, 0x03, 0xfd, 0x02, 0x39, 0x63, 0x06, 0xd2, 0x48, 0xcd, 0xa0,
|
||||
0xe9, 0x9f, 0x33, 0x42, 0x0f, 0x57, 0x7e, 0xe8, 0xce, 0x54, 0xb6, 0x70, 0x80, 0xa8, 0x0d, 0x1e, 0xc6, 0x98, 0x21, 0xbc, 0xb6, 0xa8, 0x83, 0x93, 0x96, 0xf9, 0x65, 0x2b, 0x6f, 0xf7, 0x2a, 0x70]
|
||||
|
||||
let Src2 : [UInt8] =
|
||||
[0xd1, 0x31, 0xdd, 0x02, 0xc5, 0xe6, 0xee, 0xc4, 0x69, 0x3d, 0x9a, 0x06, 0x98, 0xaf, 0xf9, 0x5c, 0x2f, 0xca, 0xb5, 0x07, 0x12, 0x46, 0x7e, 0xab, 0x40, 0x04, 0x58, 0x3e, 0xb8, 0xfb, 0x7f, 0x89,
|
||||
0x55, 0xad, 0x34, 0x06, 0x09, 0xf4, 0xb3, 0x02, 0x83, 0xe4, 0x88, 0x83, 0x25, 0xf1, 0x41, 0x5a, 0x08, 0x51, 0x25, 0xe8, 0xf7, 0xcd, 0xc9, 0x9f, 0xd9, 0x1d, 0xbd, 0x72, 0x80, 0x37, 0x3c, 0x5b,
|
||||
0xd8, 0x82, 0x3e, 0x31, 0x56, 0x34, 0x8f, 0x5b, 0xae, 0x6d, 0xac, 0xd4, 0x36, 0xc9, 0x19, 0xc6, 0xdd, 0x53, 0xe2, 0x34, 0x87, 0xda, 0x03, 0xfd, 0x02, 0x39, 0x63, 0x06, 0xd2, 0x48, 0xcd, 0xa0,
|
||||
0xe9, 0x9f, 0x33, 0x42, 0x0f, 0x57, 0x7e, 0xe8, 0xce, 0x54, 0xb6, 0x70, 0x80, 0x28, 0x0d, 0x1e, 0xc6, 0x98, 0x21, 0xbc, 0xb6, 0xa8, 0x83, 0x93, 0x96, 0xf9, 0x65, 0xab, 0x6f, 0xf7, 0x2a, 0x70]
|
||||
|
||||
let H1 = MD5()
|
||||
let H2 = MD5()
|
||||
|
||||
H1.update(Src1)
|
||||
H2.update(Src2)
|
||||
let A1 = H1.digest()
|
||||
let A2 = H2.digest()
|
||||
CheckResults(A1 == A2,
|
||||
"Incorrect result in Hash: check 3 failed.")
|
||||
CheckResults(A1 == "79054025255fb1a26e4bc422aef54eb4",
|
||||
"Incorrect result in Hash: check 4 failed.")
|
||||
H1.reset()
|
||||
H2.reset()
|
||||
|
||||
let SH = SHA1()
|
||||
let SH256 = SHA256()
|
||||
for (K, V) in TestSHA1 {
|
||||
SH.update(K)
|
||||
CheckResults(SH.digest() == V,
|
||||
"Incorrect result in Hash: check 5 failed.")
|
||||
SH.reset()
|
||||
}
|
||||
|
||||
for (K, V) in TestSHA256 {
|
||||
SH256.update(K)
|
||||
CheckResults(SH256.digest() == V,
|
||||
"Incorrect result in Hash: check 5 failed.")
|
||||
SH256.reset()
|
||||
}
|
||||
|
||||
// Check that we don't crash on large strings.
|
||||
S = ""
|
||||
for _ in 1...size {
|
||||
S += "a"
|
||||
SH.reset()
|
||||
SH.update(S)
|
||||
}
|
||||
|
||||
// Check that the order in which we push values does not chage the result.
|
||||
SH.reset()
|
||||
L = ""
|
||||
for _ in 1...size {
|
||||
L += "a"
|
||||
SH.update("a")
|
||||
}
|
||||
let SH2 = SHA1()
|
||||
SH2.update(L)
|
||||
CheckResults(SH.digest() == SH2.digest(),
|
||||
"Incorrect result in Hash: check 5 failed.")
|
||||
}
|
||||
}
|
||||
114
benchmark/single-source/Histogram.swift
Normal file
114
benchmark/single-source/Histogram.swift
Normal file
@@ -0,0 +1,114 @@
|
||||
//===--- Histogram.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test measures performance of histogram generating.
|
||||
// <rdar://problem/17384894>
|
||||
import TestsUtils
|
||||
|
||||
typealias rrggbb_t = UInt32
|
||||
|
||||
func output_sorted_sparse_rgb_histogram<S: SequenceType where S.Generator.Element == rrggbb_t>(samples: S, _ N: Int) {
|
||||
var histogram = Dictionary<rrggbb_t, Int>()
|
||||
for _ in 1...50*N {
|
||||
for sample in samples { // This part is really awful, I agree
|
||||
let i = histogram.indexForKey(sample)
|
||||
histogram[sample] = (i != nil ? histogram[i!].1 : 0) + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Packed-RGB test data: four gray samples, two red, two blue, and a 4 pixel gradient from black to white
|
||||
let samples: [rrggbb_t] = [
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF
|
||||
]
|
||||
|
||||
@inline(never)
|
||||
public func run_Histogram(N: Int) {
|
||||
output_sorted_sparse_rgb_histogram(samples, N);
|
||||
}
|
||||
24
benchmark/single-source/Join.swift
Normal file
24
benchmark/single-source/Join.swift
Normal file
@@ -0,0 +1,24 @@
|
||||
//===--- Join.swift -------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test tests the performance of ASCII Character comparison.
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_Join(N: Int) {
|
||||
var array: [String] = []
|
||||
for x in 0..<1000 * N {
|
||||
array.append(String(x))
|
||||
}
|
||||
_ = array.joinWithSeparator("")
|
||||
_ = array.joinWithSeparator(" ")
|
||||
}
|
||||
51
benchmark/single-source/LinkedList.swift
Normal file
51
benchmark/single-source/LinkedList.swift
Normal file
@@ -0,0 +1,51 @@
|
||||
//===--- LinkedList.swift -------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test checks performance of linked lists. It is based on LinkedList from
|
||||
// utils/benchmark, with modifications for performance measuring.
|
||||
import TestsUtils
|
||||
|
||||
final class Node {
|
||||
var next: Node?
|
||||
var data: Int
|
||||
|
||||
init(n: Node?, d: Int) {
|
||||
next = n
|
||||
data = d
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_LinkedList(N: Int) {
|
||||
let size = 100
|
||||
var head = Node(n:nil, d:0)
|
||||
for i in 0..<size {
|
||||
head = Node(n:head, d:i)
|
||||
}
|
||||
|
||||
var sum = 0
|
||||
let ref_result = size*(size-1)/2
|
||||
var ptr = head
|
||||
for _ in 1...5000*N {
|
||||
ptr = head
|
||||
sum = 0
|
||||
while let nxt = ptr.next {
|
||||
sum += ptr.data
|
||||
ptr = nxt
|
||||
}
|
||||
if sum != ref_result {
|
||||
break
|
||||
}
|
||||
}
|
||||
CheckResults(sum == ref_result,
|
||||
"Incorrect results in LinkedList: \(sum) != \(ref_result)")
|
||||
}
|
||||
27
benchmark/single-source/MapReduce.swift
Normal file
27
benchmark/single-source/MapReduce.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
//===--- MapReduce.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
import Foundation
|
||||
|
||||
@inline(never)
|
||||
public func run_MapReduce(N: Int) {
|
||||
var numbers = [Int](0..<1000)
|
||||
|
||||
var c = 0
|
||||
for _ in 1...N*100 {
|
||||
numbers = numbers.map({$0 &+ 5})
|
||||
c += numbers.reduce(0, combine: &+)
|
||||
}
|
||||
CheckResults(c != 0, "IncorrectResults in MapReduce")
|
||||
}
|
||||
|
||||
30
benchmark/single-source/Memset.swift
Normal file
30
benchmark/single-source/Memset.swift
Normal file
@@ -0,0 +1,30 @@
|
||||
//===--- Memset.swift -----------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
func memset(inout a: [Int], _ c: Int) {
|
||||
for i in 0..<a.count {
|
||||
a[i] = c
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_Memset(N: Int) {
|
||||
var a = [Int](count: 10_000, repeatedValue: 0)
|
||||
for _ in 1...50*N {
|
||||
memset(&a, 1)
|
||||
memset(&a, 0)
|
||||
}
|
||||
CheckResults(a[87] == 0, "Incorrect result in Memset.")
|
||||
}
|
||||
38
benchmark/single-source/MonteCarloE.swift
Normal file
38
benchmark/single-source/MonteCarloE.swift
Normal file
@@ -0,0 +1,38 @@
|
||||
//===--- MonteCarloE.swift ------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test measures performance of Monte Carlo estimation of the e constant.
|
||||
//
|
||||
// We use 'dart' method: we split an interval into N pieces and drop N darts
|
||||
// to this interval.
|
||||
// After that we count number of empty intervals. The probability of being
|
||||
// empty is (1 - 1/N)^N which estimates to e^-1 for large N.
|
||||
// Thus, e = N / Nempty.
|
||||
import TestsUtils
|
||||
|
||||
public func run_MonteCarloE(scale: Int) {
|
||||
let N = 200000*scale
|
||||
var intervals = [Bool](count: N, repeatedValue: false)
|
||||
for _ in 1...N {
|
||||
let pos = Int(UInt(truncatingBitPattern: Random())%UInt(N))
|
||||
intervals[pos] = true
|
||||
}
|
||||
let numEmptyIntervals = intervals.filter{!$0}.count
|
||||
// If there are no empty intervals, then obviously the random generator is
|
||||
// not 'random' enough.
|
||||
CheckResults(numEmptyIntervals != N,
|
||||
"Incorrect results in MonteCarloE: no empty intervals.")
|
||||
let e_estimate = Double(N)/Double(numEmptyIntervals)
|
||||
let e = 2.71828
|
||||
CheckResults(Double.abs(e_estimate - e) < 0.1,
|
||||
"Incorrect results in MonteCarloE: e_estimate == \(e_estimate)")
|
||||
}
|
||||
30
benchmark/single-source/MonteCarloPi.swift
Normal file
30
benchmark/single-source/MonteCarloPi.swift
Normal file
@@ -0,0 +1,30 @@
|
||||
//===--- MonteCarloPi.swift -----------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
public func run_MonteCarloPi(scale: Int) {
|
||||
var pointsInside = 0
|
||||
let r = 10000
|
||||
let N = 500000*scale
|
||||
for _ in 1...N {
|
||||
let x = Int(truncatingBitPattern: Random())%r
|
||||
let y = Int(truncatingBitPattern: Random())%r
|
||||
if x*x + y*y < r*r {
|
||||
pointsInside += 1
|
||||
}
|
||||
}
|
||||
let pi_estimate: Double = Double(pointsInside)*4.0/Double(N)
|
||||
let pi = 3.1415
|
||||
CheckResults(Double.abs(pi_estimate - pi) < 0.1,
|
||||
"Incorrect results in MonteCarloPi: pi_estimate == \(pi_estimate)")
|
||||
}
|
||||
34
benchmark/single-source/NSDictionaryCastToSwift.swift
Normal file
34
benchmark/single-source/NSDictionaryCastToSwift.swift
Normal file
@@ -0,0 +1,34 @@
|
||||
//===--- NSDictionaryCastToSwift.swift ------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Performance benchmark for casting NSDictionary to Swift Dictionary
|
||||
// rdar://problem/18539730
|
||||
//
|
||||
// Description:
|
||||
// Create a NSDictionary instance and cast it to [String: NSObject].
|
||||
import Foundation
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_NSDictionaryCastToSwift(N: Int) {
|
||||
let NSDict = NSDictionary()
|
||||
var swiftDict = [String: NSObject]()
|
||||
for _ in 1...10000*N {
|
||||
swiftDict = NSDict as! [String: NSObject]
|
||||
if !swiftDict.isEmpty {
|
||||
break
|
||||
}
|
||||
}
|
||||
CheckResults(swiftDict.isEmpty,
|
||||
"Incorrect result in swiftDict.isEmpty: " +
|
||||
"\(swiftDict.isEmpty) != true\n")
|
||||
}
|
||||
48
benchmark/single-source/NSError.swift
Normal file
48
benchmark/single-source/NSError.swift
Normal file
@@ -0,0 +1,48 @@
|
||||
//===--- NSError.swift ----------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
import Foundation
|
||||
|
||||
protocol P {
|
||||
func buzz() throws -> Int
|
||||
}
|
||||
|
||||
class K : P {
|
||||
init() {}
|
||||
func buzz() throws -> Int {
|
||||
throw NSError(domain: "AnDomain", code: 42, userInfo: nil)
|
||||
}
|
||||
}
|
||||
|
||||
class G : K {
|
||||
override init() {}
|
||||
override func buzz() throws -> Int { return 0 }
|
||||
}
|
||||
|
||||
func caller(x : P) throws {
|
||||
try x.buzz()
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_NSError(N: Int) {
|
||||
for _ in 1...N*1000 {
|
||||
let k = K()
|
||||
let g = G()
|
||||
do {
|
||||
try caller(g)
|
||||
try caller(k)
|
||||
} catch _ {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
22
benchmark/single-source/NSStringConversion.swift
Normal file
22
benchmark/single-source/NSStringConversion.swift
Normal file
@@ -0,0 +1,22 @@
|
||||
//===--- NSStringConversion.swift -----------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <rdar://problem/19003201>
|
||||
import TestsUtils
|
||||
import Foundation
|
||||
|
||||
public func run_NSStringConversion(N: Int) {
|
||||
let test:NSString = NSString(CString: "test", encoding: NSASCIIStringEncoding)!
|
||||
for _ in 1...N * 10000 {
|
||||
test as String
|
||||
}
|
||||
}
|
||||
36
benchmark/single-source/NopDeinit.swift
Normal file
36
benchmark/single-source/NopDeinit.swift
Normal file
@@ -0,0 +1,36 @@
|
||||
//===--- NopDeinit.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <rdar://problem/17838787>
|
||||
import TestsUtils
|
||||
|
||||
class X<T : Comparable> {
|
||||
let deinitIters = 10000
|
||||
var elem : T
|
||||
init(_ x : T) {elem = x}
|
||||
deinit {
|
||||
for _ in 1...deinitIters {
|
||||
if (elem > elem) { };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func run_NopDeinit(N: Int) {
|
||||
for _ in 1...N {
|
||||
var arr :[X<Int>] = []
|
||||
let size = 500
|
||||
for i in 1...size { arr.append(X(i)) }
|
||||
arr.removeAll()
|
||||
CheckResults(arr.count == 0,
|
||||
"Incorrect results in NopDeinit: \(arr.count) != 0.")
|
||||
}
|
||||
}
|
||||
135
benchmark/single-source/ObjectAllocation.swift
Normal file
135
benchmark/single-source/ObjectAllocation.swift
Normal file
@@ -0,0 +1,135 @@
|
||||
//===--- ObjectAllocation.swift -------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test checks the performance of allocations.
|
||||
import TestsUtils
|
||||
|
||||
final class XX {
|
||||
var xx: Int
|
||||
|
||||
init(_ x: Int) {
|
||||
xx = x
|
||||
}
|
||||
}
|
||||
|
||||
final class TreeNode {
|
||||
let left: XX
|
||||
let right: XX
|
||||
|
||||
init(_ l: XX, _ r: XX) {
|
||||
left = l
|
||||
right = r
|
||||
}
|
||||
}
|
||||
|
||||
final class LinkedNode {
|
||||
var next: LinkedNode?
|
||||
var xx: Int
|
||||
|
||||
init(_ x: Int, _ n: LinkedNode?) {
|
||||
xx = x
|
||||
next = n
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func getInt(x: XX) -> Int {
|
||||
return x.xx
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func testSingleObject() -> Int {
|
||||
var s = 0
|
||||
for i in 0..<1000 {
|
||||
let x = XX(i)
|
||||
s += getInt(x)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func addInts(t: TreeNode) -> Int {
|
||||
return t.left.xx + t.right.xx
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func testTree() -> Int {
|
||||
var s = 0
|
||||
for i in 0..<300 {
|
||||
let t = TreeNode(XX(i), XX(i + 1))
|
||||
s += addInts(t)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func addAllInts(n: LinkedNode) -> Int {
|
||||
var s = 0
|
||||
var iter: LinkedNode? = n
|
||||
while let iter2 = iter {
|
||||
s += iter2.xx
|
||||
iter = iter2.next
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func testList() -> Int {
|
||||
var s = 0
|
||||
for i in 0..<250 {
|
||||
let l = LinkedNode(i, LinkedNode(27, LinkedNode(42, nil)))
|
||||
s += addAllInts(l)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func identity(x: Int) -> Int {
|
||||
return x
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func testArray() -> Int {
|
||||
var s = 0
|
||||
for _ in 0..<1000 {
|
||||
for i in [0, 1, 2] {
|
||||
s += identity(i)
|
||||
}
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_ObjectAllocation(N: Int) {
|
||||
|
||||
var SingleObjectResult = 0
|
||||
var TreeResult = 0
|
||||
var ListResult = 0
|
||||
var ArrayResult = 0
|
||||
|
||||
for _ in 0..<N {
|
||||
SingleObjectResult = testSingleObject()
|
||||
TreeResult = testTree()
|
||||
ListResult = testList()
|
||||
ArrayResult = testArray()
|
||||
}
|
||||
|
||||
CheckResults(SingleObjectResult == 499500,
|
||||
"Incorrect results in testSingleObject")
|
||||
CheckResults(TreeResult == 90000,
|
||||
"Incorrect results in testTree")
|
||||
CheckResults(ListResult == 48375,
|
||||
"Incorrect results in testList")
|
||||
CheckResults(ArrayResult == 3000,
|
||||
"Incorrect results in testArray")
|
||||
}
|
||||
|
||||
37
benchmark/single-source/OpenClose.swift
Normal file
37
benchmark/single-source/OpenClose.swift
Normal file
@@ -0,0 +1,37 @@
|
||||
//===--- OpenClose.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
import Foundation
|
||||
|
||||
|
||||
// A micro benchmark for checking the speed of string-based enums.
|
||||
|
||||
enum MyState : String {
|
||||
case Closed = "Closed"
|
||||
case Opened = "Opened"
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func check_state(state : MyState) -> Int {
|
||||
return state == .Opened ? 1 : 0
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_OpenClose(N: Int) {
|
||||
var c = 0
|
||||
for _ in 1...N*10000 {
|
||||
c += check_state(MyState.Closed)
|
||||
}
|
||||
CheckResults(c == 0, "IncorrectResults in run_OpenClose")
|
||||
}
|
||||
|
||||
74
benchmark/single-source/Phonebook.swift
Normal file
74
benchmark/single-source/Phonebook.swift
Normal file
@@ -0,0 +1,74 @@
|
||||
//===--- Phonebook.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test is based on util/benchmarks/Phonebook, with modifications
|
||||
// for performance measuring.
|
||||
import TestsUtils
|
||||
|
||||
var words=[
|
||||
"James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph",
|
||||
"Charles", "Thomas", "Christopher", "Daniel", "Matthew", "Donald", "Anthony",
|
||||
"Paul", "Mark", "George", "Steven", "Kenneth", "Andrew", "Edward", "Brian",
|
||||
"Joshua", "Kevin", "Ronald", "Timothy", "Jason", "Jeffrey", "Gary", "Ryan",
|
||||
"Nicholas", "Eric", "Stephen", "Jacob", "Larry", "Frank", "Jonathan", "Scott",
|
||||
"Justin", "Raymond", "Brandon", "Gregory", "Samuel", "Patrick", "Benjamin",
|
||||
"Jack", "Dennis", "Jerry", "Alexander", "Tyler", "Douglas", "Henry", "Peter",
|
||||
"Walter", "Aaron", "Jose", "Adam", "Harold", "Zachary", "Nathan", "Carl",
|
||||
"Kyle", "Arthur", "Gerald", "Lawrence", "Roger", "Albert", "Keith", "Jeremy",
|
||||
"Terry", "Joe", "Sean", "Willie", "Jesse", "Ralph", "Billy", "Austin", "Bruce",
|
||||
"Christian", "Roy", "Bryan", "Eugene", "Louis", "Harry", "Wayne", "Ethan",
|
||||
"Jordan", "Russell", "Alan", "Philip", "Randy", "Juan", "Howard", "Vincent",
|
||||
"Bobby", "Dylan", "Johnny", "Phillip", "Craig"]
|
||||
|
||||
// This is a phone book record.
|
||||
struct Record : Comparable {
|
||||
var first : String
|
||||
var last : String
|
||||
|
||||
init(_ first_ : String,_ last_ : String) {
|
||||
first = first_
|
||||
last = last_
|
||||
}
|
||||
}
|
||||
func ==(lhs: Record, rhs: Record) -> Bool {
|
||||
return lhs.last == rhs.last && lhs.first == rhs.first
|
||||
}
|
||||
|
||||
func <(lhs: Record, rhs: Record) -> Bool {
|
||||
if lhs.last < rhs.last {
|
||||
return true
|
||||
}
|
||||
if lhs.last > rhs.last {
|
||||
return false
|
||||
}
|
||||
|
||||
if lhs.first < rhs.first {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_Phonebook(N: Int) {
|
||||
// The list of names in the phonebook.
|
||||
var Names : [Record] = []
|
||||
for first in words {
|
||||
for last in words {
|
||||
Names.append(Record(first, last))
|
||||
}
|
||||
}
|
||||
for _ in 1...N {
|
||||
var t = Names;
|
||||
t.sortInPlace()
|
||||
}
|
||||
}
|
||||
333
benchmark/single-source/PolymorphicCalls.swift
Normal file
333
benchmark/single-source/PolymorphicCalls.swift
Normal file
@@ -0,0 +1,333 @@
|
||||
//===--- PolymorphicCalls.swift -------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/*
|
||||
This benchmark is used to check the performance of polymorphic invocations.
|
||||
Essentially, it checks how good a compiler can optimize virtual calls of class
|
||||
methods in cases where multiple sub-classes of a given class are available.
|
||||
|
||||
In particular, this benchark would benefit from a good devirtualization.
|
||||
In case of applying a speculative devirtualization, it would be benefit from
|
||||
applying a jump-threading in combination with the speculative devirtualization.
|
||||
*/
|
||||
|
||||
import TestsUtils
|
||||
|
||||
public class A {
|
||||
let b: B
|
||||
init(b:B) {
|
||||
self.b = b
|
||||
}
|
||||
|
||||
public func run1() -> Int {
|
||||
return b.f1() + b.f2() + b.f3()
|
||||
}
|
||||
|
||||
public func run2() -> Int {
|
||||
return b.run()
|
||||
}
|
||||
}
|
||||
|
||||
// B has no known subclasses
|
||||
public class B {
|
||||
let x: Int
|
||||
init(x:Int) {
|
||||
self.x = x
|
||||
}
|
||||
public func f1() -> Int {
|
||||
return x + 1
|
||||
}
|
||||
public func f2() -> Int {
|
||||
return x + 11
|
||||
}
|
||||
public func f3() -> Int {
|
||||
return x + 111
|
||||
}
|
||||
public func run() -> Int {
|
||||
return f1() + f2() + f3()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class A1 {
|
||||
let b: B1
|
||||
public init(b:B1) {
|
||||
self.b = b;
|
||||
}
|
||||
public func run1() -> Int {
|
||||
return b.f1() + b.f2() + b.f3()
|
||||
}
|
||||
public func run2() -> Int {
|
||||
return b.run()
|
||||
}
|
||||
}
|
||||
|
||||
// B1 has 1 known subclass
|
||||
public class B1 {
|
||||
func f1() -> Int { return 0 }
|
||||
func f2() -> Int { return 0 }
|
||||
func f3() -> Int { return 0 }
|
||||
public func run() -> Int {
|
||||
return f1() + f2() + f3()
|
||||
}
|
||||
}
|
||||
|
||||
public class C1: B1 {
|
||||
let x: Int
|
||||
init(x:Int) {
|
||||
self.x = x
|
||||
}
|
||||
override public func f1() -> Int {
|
||||
return x + 2
|
||||
}
|
||||
override public func f2() -> Int {
|
||||
return x + 22
|
||||
}
|
||||
override public func f3() -> Int {
|
||||
return x + 222
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class A2 {
|
||||
let b:B2
|
||||
public init(b:B2) {
|
||||
self.b = b
|
||||
}
|
||||
public func run1() -> Int {
|
||||
return b.f1() + b.f2() + b.f3()
|
||||
}
|
||||
public func run2() -> Int {
|
||||
return b.run()
|
||||
}
|
||||
}
|
||||
|
||||
// B2 has 2 known subclasses
|
||||
public class B2 {
|
||||
func f1() -> Int { return 0 }
|
||||
func f2() -> Int { return 0 }
|
||||
func f3() -> Int { return 0 }
|
||||
public func run() -> Int {
|
||||
return f1() + f2() + f3()
|
||||
}
|
||||
}
|
||||
|
||||
public class C2 : B2 {
|
||||
let x: Int
|
||||
init(x:Int) {
|
||||
self.x = x
|
||||
}
|
||||
override public func f1() -> Int {
|
||||
return x + 3
|
||||
}
|
||||
override public func f2() -> Int {
|
||||
return x + 33
|
||||
}
|
||||
override public func f3() -> Int {
|
||||
return x + 333
|
||||
}
|
||||
}
|
||||
|
||||
public class D2 : B2 {
|
||||
let x: Int
|
||||
init(x:Int) {
|
||||
self.x = x
|
||||
}
|
||||
override public func f1() -> Int {
|
||||
return x + 4
|
||||
}
|
||||
override public func f2() -> Int {
|
||||
return x + 44
|
||||
}
|
||||
override public func f3() -> Int {
|
||||
return x + 444
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class A3 {
|
||||
let b : B3
|
||||
|
||||
public init(b:B3) {
|
||||
self.b = b
|
||||
}
|
||||
|
||||
public func run1() -> Int {
|
||||
return b.f1() + b.f2() + b.f3()
|
||||
}
|
||||
public func run2() -> Int {
|
||||
return b.run()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// B3 has 3 known subclasses
|
||||
public class B3 {
|
||||
func f1() -> Int { return 0 }
|
||||
func f2() -> Int { return 0 }
|
||||
func f3() -> Int { return 0 }
|
||||
public func run() -> Int {
|
||||
return f1() + f2() + f3()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class C3: B3 {
|
||||
let x: Int
|
||||
init(x:Int) {
|
||||
self.x = x
|
||||
}
|
||||
override public func f1() -> Int {
|
||||
return x + 5
|
||||
}
|
||||
override public func f2() -> Int {
|
||||
return x + 55
|
||||
}
|
||||
override public func f3() -> Int {
|
||||
return x + 555
|
||||
}
|
||||
}
|
||||
public class D3: B3 {
|
||||
let x: Int
|
||||
init(x:Int) {
|
||||
self.x = x
|
||||
}
|
||||
override public func f1() -> Int {
|
||||
return x + 6
|
||||
}
|
||||
override public func f2() -> Int {
|
||||
return x + 66
|
||||
}
|
||||
override public func f3() -> Int {
|
||||
return x + 666
|
||||
}
|
||||
}
|
||||
public class E3:B3 {
|
||||
let x: Int
|
||||
init(x:Int) {
|
||||
self.x = x
|
||||
}
|
||||
override public func f1() -> Int {
|
||||
return x + 7
|
||||
}
|
||||
override public func f2() -> Int {
|
||||
return x + 77
|
||||
}
|
||||
override public func f3() -> Int {
|
||||
return x + 777
|
||||
}
|
||||
}
|
||||
public class F3 : B3 {
|
||||
let x: Int
|
||||
init(x:Int) {
|
||||
self.x = x
|
||||
}
|
||||
override public func f1() -> Int {
|
||||
return x + 8
|
||||
}
|
||||
override public func f2() -> Int {
|
||||
return x + 88
|
||||
}
|
||||
override public func f3() -> Int {
|
||||
return x + 888
|
||||
}}
|
||||
|
||||
// Test the cost of polymorphic method invocation
|
||||
// on a class without any subclasses
|
||||
@inline(never)
|
||||
func test(a:A, _ UPTO: Int) -> Int64 {
|
||||
var cnt : Int64 = 0
|
||||
for _ in 0..<UPTO {
|
||||
cnt += a.run2()
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
// Test the cost of polymorphic method invocation
|
||||
// on a class with 1 subclass
|
||||
@inline(never)
|
||||
func test(a:A1, _ UPTO: Int) -> Int64 {
|
||||
var cnt : Int64 = 0
|
||||
for _ in 0..<UPTO {
|
||||
cnt += a.run2()
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
// Test the cost of polymorphic method invocation
|
||||
// on a class with 2 subclasses
|
||||
@inline(never)
|
||||
func test(a:A2, _ UPTO: Int) -> Int64 {
|
||||
var cnt : Int64 = 0
|
||||
for _ in 0..<UPTO {
|
||||
cnt += a.run2()
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
// Test the cost of polymorphic method invocation
|
||||
// on a class with 2 subclasses on objects
|
||||
// of different subclasses
|
||||
@inline(never)
|
||||
func test(a2_c2:A2, _ a2_d2:A2, _ UPTO: Int) -> Int64 {
|
||||
var cnt : Int64 = 0
|
||||
for _ in 0..<UPTO/2 {
|
||||
cnt += a2_c2.run2()
|
||||
cnt += a2_d2.run2()
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
// Test the cost of polymorphic method invocation
|
||||
// on a class with 4 subclasses on objects
|
||||
// of different subclasses
|
||||
@inline(never)
|
||||
func test(a3_c3: A3, _ a3_d3: A3, _ a3_e3: A3, _ a3_f3: A3, _ UPTO: Int) -> Int64 {
|
||||
var cnt : Int64 = 0
|
||||
for _ in 0..<UPTO/4 {
|
||||
cnt += a3_c3.run2()
|
||||
cnt += a3_d3.run2()
|
||||
cnt += a3_e3.run2()
|
||||
cnt += a3_f3.run2()
|
||||
}
|
||||
return cnt
|
||||
}
|
||||
|
||||
|
||||
|
||||
@inline(never)
|
||||
public func run_PolymorphicCalls(N:Int) {
|
||||
let UPTO = 10000 * N
|
||||
|
||||
let a = A(b:B(x:1))
|
||||
test(a, UPTO)
|
||||
|
||||
let a1 = A1(b:C1(x:1))
|
||||
|
||||
test(a1, UPTO)
|
||||
|
||||
let a2 = A2(b:C2(x:1))
|
||||
|
||||
test(a2, UPTO)
|
||||
|
||||
let a2_c2 = A2(b:C2(x:1))
|
||||
let a2_d2 = A2(b:D2(x:1))
|
||||
|
||||
test(a2_c2, a2_d2, UPTO)
|
||||
|
||||
let a3_c3 = A3(b:C3(x:1))
|
||||
let a3_d3 = A3(b:D3(x:1))
|
||||
let a3_e3 = A3(b:E3(x:1))
|
||||
let a3_f3 = A3(b:F3(x:1))
|
||||
|
||||
test(a3_c3, a3_d3, a3_e3, a3_f3, UPTO)
|
||||
}
|
||||
56
benchmark/single-source/PopFront.swift
Normal file
56
benchmark/single-source/PopFront.swift
Normal file
@@ -0,0 +1,56 @@
|
||||
//===--- PopFront.swift ---------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
let reps = 1
|
||||
let arrayCount = 1024
|
||||
|
||||
@inline(never)
|
||||
public func run_PopFrontArray(N: Int) {
|
||||
let orig = Array(count: arrayCount, repeatedValue: 1)
|
||||
var a = [Int]()
|
||||
for _ in 1...20*N {
|
||||
for _ in 1...reps {
|
||||
var result = 0
|
||||
a.appendContentsOf(orig)
|
||||
while a.count != 0 {
|
||||
result += a[0]
|
||||
a.removeAtIndex(0)
|
||||
}
|
||||
CheckResults(result == arrayCount, "IncorrectResults in StringInterpolation: \(result) != \(arrayCount)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_PopFrontUnsafePointer(N: Int) {
|
||||
var orig = Array(count: arrayCount, repeatedValue: 1)
|
||||
let a = UnsafeMutablePointer<Int>.alloc(arrayCount)
|
||||
for _ in 1...100*N {
|
||||
for _ in 1...reps {
|
||||
for i in 0..<arrayCount {
|
||||
a[i] = orig[i]
|
||||
}
|
||||
var result = 0
|
||||
var count = arrayCount
|
||||
while count != 0 {
|
||||
result += a[0]
|
||||
a.assignFrom(a + 1, count: count - 1)
|
||||
count -= 1
|
||||
}
|
||||
CheckResults(result == arrayCount, "IncorrectResults in StringInterpolation: \(result) != \(arrayCount)")
|
||||
}
|
||||
}
|
||||
a.dealloc(arrayCount)
|
||||
}
|
||||
|
||||
63
benchmark/single-source/PopFrontGeneric.swift
Normal file
63
benchmark/single-source/PopFrontGeneric.swift
Normal file
@@ -0,0 +1,63 @@
|
||||
//===--- PopFrontGeneric.swift --------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
let reps = 1
|
||||
let arrayCount = 1024
|
||||
|
||||
// This test case exposes rdar://17440222 which caused rdar://17974483 (popFront
|
||||
// being really slow).
|
||||
|
||||
func _arrayReplace<B: _ArrayBufferType, C: CollectionType
|
||||
where C.Generator.Element == B.Element, B.Index == Int
|
||||
>(
|
||||
inout target: B, _ subRange: Range<Int>, _ newValues: C
|
||||
) {
|
||||
_precondition(
|
||||
subRange.startIndex >= 0,
|
||||
"Array replace: subRange start is negative")
|
||||
|
||||
_precondition(
|
||||
subRange.endIndex <= target.endIndex,
|
||||
"Array replace: subRange extends past the end")
|
||||
|
||||
let oldCount = target.count
|
||||
let eraseCount = subRange.count
|
||||
let insertCount = numericCast(newValues.count) as Int
|
||||
let growth = insertCount - eraseCount
|
||||
|
||||
if target.requestUniqueMutableBackingBuffer(oldCount + growth) != nil {
|
||||
target.replace(subRange: subRange, with: insertCount, elementsOf: newValues)
|
||||
}
|
||||
else {
|
||||
_preconditionFailure("Should not get here?")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@inline(never)
|
||||
public func run_PopFrontArrayGeneric(N: Int) {
|
||||
let orig = Array(count: arrayCount, repeatedValue: 1)
|
||||
var a = [Int]()
|
||||
for _ in 1...20*N {
|
||||
for _ in 1...reps {
|
||||
var result = 0
|
||||
a.appendContentsOf(orig)
|
||||
while a.count != 0 {
|
||||
result += a[0]
|
||||
_arrayReplace(&a._buffer, 0..<1, EmptyCollection())
|
||||
}
|
||||
CheckResults(result == arrayCount, "IncorrectResults in StringInterpolation: \(result) != \(arrayCount)")
|
||||
}
|
||||
}
|
||||
}
|
||||
757
benchmark/single-source/Prims.swift
Normal file
757
benchmark/single-source/Prims.swift
Normal file
@@ -0,0 +1,757 @@
|
||||
//===--- Prims.swift ------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// The test implements Prim's algorithm for minimum spanning tree building.
|
||||
// http://en.wikipedia.org/wiki/Prim%27s_algorithm
|
||||
|
||||
// This class implements array-based heap (priority queue).
|
||||
// It is used to store edges from nodes in spanning tree to nodes outside of it.
|
||||
// We are interested only in the edges with the smallest costs, so if there are
|
||||
// several edges pointing to the same node, we keep only one from them. Thus,
|
||||
// it is enough to record this node instead.
|
||||
// We maintain a map (node index in graph)->(node index in heap) to be able to
|
||||
// update the heap fast when we add a new node to the tree.
|
||||
import TestsUtils
|
||||
|
||||
class PriorityQueue {
|
||||
final var heap : Array<EdgeCost>
|
||||
final var graphIndexToHeapIndexMap : Array<Int?>
|
||||
|
||||
// Create heap for graph with NUM nodes.
|
||||
init(Num: Int) {
|
||||
heap = Array<EdgeCost>()
|
||||
graphIndexToHeapIndexMap = Array<Int?>(count: Num, repeatedValue:nil)
|
||||
}
|
||||
|
||||
func isEmpty() -> Bool {
|
||||
return heap.isEmpty
|
||||
}
|
||||
|
||||
// Insert element N to heap, maintaining the heap property.
|
||||
func insert(n : EdgeCost) {
|
||||
let ind: Int = heap.count
|
||||
heap.append(n)
|
||||
graphIndexToHeapIndexMap[n.to] = heap.count - 1
|
||||
bubbleUp(ind)
|
||||
}
|
||||
|
||||
// Insert element N if in's not in the heap, or update its cost if the new
|
||||
// value is less than the existing one.
|
||||
func insertOrUpdate(n : EdgeCost) {
|
||||
let id = n.to
|
||||
let c = n.cost
|
||||
if let ind = graphIndexToHeapIndexMap[id] {
|
||||
if heap[ind].cost <= c {
|
||||
// We don't need an edge with a bigger cost
|
||||
return
|
||||
}
|
||||
heap[ind].cost = c
|
||||
heap[ind].from = n.from
|
||||
bubbleUp(ind)
|
||||
} else {
|
||||
insert(n)
|
||||
}
|
||||
}
|
||||
|
||||
// Restore heap property by moving element at index IND up.
|
||||
// This is needed after insertion, and after decreasing an element's cost.
|
||||
func bubbleUp(ind: Int) {
|
||||
var ind = ind
|
||||
let c = heap[ind].cost
|
||||
while (ind != 0) {
|
||||
let p = getParentIndex(ind)
|
||||
if heap[p].cost > c {
|
||||
Swap(p, with: ind)
|
||||
ind = p
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pop minimum element from heap and restore the heap property after that.
|
||||
func pop() -> EdgeCost? {
|
||||
if (heap.isEmpty) {
|
||||
return nil
|
||||
}
|
||||
Swap(0, with:heap.count-1)
|
||||
let r = heap.removeLast()
|
||||
graphIndexToHeapIndexMap[r.to] = nil
|
||||
bubbleDown(0)
|
||||
return r
|
||||
}
|
||||
|
||||
// Restore heap property by moving element at index IND down.
|
||||
// This is needed after removing an element, and after increasing an
|
||||
// element's cost.
|
||||
func bubbleDown(ind: Int) {
|
||||
var ind = ind
|
||||
let n = heap.count
|
||||
while (ind < n) {
|
||||
let l = getLeftChildIndex(ind)
|
||||
let r = getRightChildIndex(ind)
|
||||
if (l >= n) {
|
||||
break
|
||||
}
|
||||
var min: Int
|
||||
if (r < n && heap[r].cost < heap[l].cost) {
|
||||
min = r
|
||||
} else {
|
||||
min = l
|
||||
}
|
||||
if (heap[ind].cost <= heap[min].cost) {
|
||||
break
|
||||
}
|
||||
Swap(ind, with: min)
|
||||
ind = min
|
||||
}
|
||||
}
|
||||
|
||||
// Swaps elements I and J in the heap and correspondingly updates
|
||||
// graphIndexToHeapIndexMap.
|
||||
func Swap(i: Int, with j : Int) {
|
||||
if (i == j) {
|
||||
return
|
||||
}
|
||||
(heap[i], heap[j]) = (heap[j], heap[i])
|
||||
let (I, J) = (heap[i].to, heap[j].to)
|
||||
(graphIndexToHeapIndexMap[I], graphIndexToHeapIndexMap[J]) =
|
||||
(graphIndexToHeapIndexMap[J], graphIndexToHeapIndexMap[I])
|
||||
}
|
||||
|
||||
// Dumps the heap.
|
||||
func dump() {
|
||||
print("QUEUE")
|
||||
for nodeCost in heap {
|
||||
let to : Int = nodeCost.to
|
||||
let from : Int = nodeCost.from
|
||||
let cost : Double = nodeCost.cost
|
||||
print("(\(from)->\(to), \(cost))")
|
||||
}
|
||||
}
|
||||
|
||||
func getLeftChildIndex(index : Int) -> Int {
|
||||
return index*2 + 1
|
||||
}
|
||||
func getRightChildIndex(index : Int) -> Int {
|
||||
return (index + 1)*2
|
||||
}
|
||||
func getParentIndex(childIndex : Int) -> Int {
|
||||
return (childIndex - 1)/2
|
||||
}
|
||||
}
|
||||
|
||||
struct GraphNode {
|
||||
var id : Int
|
||||
var adjList : Array<Int>
|
||||
|
||||
init(i : Int) {
|
||||
id = i
|
||||
adjList = Array<Int>()
|
||||
}
|
||||
}
|
||||
|
||||
struct EdgeCost {
|
||||
var to : Int
|
||||
var cost : Double
|
||||
var from: Int
|
||||
}
|
||||
|
||||
struct Edge : Equatable {
|
||||
var start : Int
|
||||
var end : Int
|
||||
}
|
||||
|
||||
func ==(lhs: Edge, rhs: Edge) -> Bool {
|
||||
return lhs.start == rhs.start && lhs.end == rhs.end
|
||||
}
|
||||
|
||||
extension Edge : Hashable {
|
||||
var hashValue: Int {
|
||||
get {
|
||||
return start.hashValue ^ end.hashValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Prims(graph : Array<GraphNode>, _ fun : (Int,Int)->Double) -> Array<Int?> {
|
||||
var treeEdges = Array<Int?>(count:graph.count, repeatedValue:nil)
|
||||
|
||||
let queue = PriorityQueue(Num:graph.count)
|
||||
// Make the minimum spanning tree root its own parent for simplicity.
|
||||
queue.insert(EdgeCost(to: 0, cost: 0.0, from: 0))
|
||||
|
||||
// Take an element with the smallest cost from the queue and add its
|
||||
// neighbours to the queue if their cost was updated
|
||||
while !queue.isEmpty() {
|
||||
// Add an edge with minimum cost to the spanning tree
|
||||
let e = queue.pop()!
|
||||
let newnode = e.to
|
||||
// Add record about the edge newnode->e.from to treeEdges
|
||||
treeEdges[newnode] = e.from
|
||||
|
||||
// Check all adjacent nodes and add edges, ending outside the tree, to the
|
||||
// queue. If the queue already contains an edge to an adjacent node, we
|
||||
// replace existing one with the new one in case the new one costs less.
|
||||
for adjNodeIndex in graph[newnode].adjList {
|
||||
if treeEdges[adjNodeIndex] != nil {
|
||||
continue
|
||||
}
|
||||
let newcost = fun(newnode, graph[adjNodeIndex].id)
|
||||
queue.insertOrUpdate(EdgeCost(to: adjNodeIndex, cost: newcost, from: newnode))
|
||||
}
|
||||
}
|
||||
return treeEdges
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_Prims(N: Int) {
|
||||
for _ in 1...5*N {
|
||||
let nodes : [Int] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
|
||||
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
|
||||
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
|
||||
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
|
||||
77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
|
||||
93, 94, 95, 96, 97, 98, 99 ]
|
||||
|
||||
// Prim's algorithm is designed for undirected graphs.
|
||||
// Due to that, in our set all the edges are paired, i.e. for any
|
||||
// edge (start,end,C) there is also an edge (end,start,C).
|
||||
let edges : [(Int, Int, Double)] = [
|
||||
(26, 47, 921),
|
||||
(20, 25, 971),
|
||||
(92, 59, 250),
|
||||
(33, 55, 1391),
|
||||
(78, 39, 313),
|
||||
(7, 25, 637),
|
||||
(18, 19, 1817),
|
||||
(33, 41, 993),
|
||||
(64, 41, 926),
|
||||
(88, 86, 574),
|
||||
(93, 15, 1462),
|
||||
(86, 33, 1649),
|
||||
(37, 35, 841),
|
||||
(98, 51, 1160),
|
||||
(15, 30, 1125),
|
||||
(65, 78, 1052),
|
||||
(58, 12, 1273),
|
||||
(12, 17, 285),
|
||||
(45, 61, 1608),
|
||||
(75, 53, 545),
|
||||
(99, 48, 410),
|
||||
(97, 0, 1303),
|
||||
(48, 17, 1807),
|
||||
(1, 54, 1491),
|
||||
(15, 34, 807),
|
||||
(94, 98, 646),
|
||||
(12, 69, 136),
|
||||
(65, 11, 983),
|
||||
(63, 83, 1604),
|
||||
(78, 89, 1828),
|
||||
(61, 63, 845),
|
||||
(18, 36, 1626),
|
||||
(68, 52, 1324),
|
||||
(14, 50, 690),
|
||||
(3, 11, 943),
|
||||
(21, 68, 914),
|
||||
(19, 44, 1762),
|
||||
(85, 80, 270),
|
||||
(59, 92, 250),
|
||||
(86, 84, 1431),
|
||||
(19, 18, 1817),
|
||||
(52, 68, 1324),
|
||||
(16, 29, 1108),
|
||||
(36, 80, 395),
|
||||
(67, 18, 803),
|
||||
(63, 88, 1717),
|
||||
(68, 21, 914),
|
||||
(75, 82, 306),
|
||||
(49, 82, 1292),
|
||||
(73, 45, 1876),
|
||||
(89, 82, 409),
|
||||
(45, 47, 272),
|
||||
(22, 83, 597),
|
||||
(61, 12, 1791),
|
||||
(44, 68, 1229),
|
||||
(50, 51, 917),
|
||||
(14, 53, 355),
|
||||
(77, 41, 138),
|
||||
(54, 21, 1870),
|
||||
(93, 70, 1582),
|
||||
(76, 2, 1658),
|
||||
(83, 73, 1162),
|
||||
(6, 1, 482),
|
||||
(11, 65, 983),
|
||||
(81, 90, 1024),
|
||||
(19, 1, 970),
|
||||
(8, 58, 1131),
|
||||
(60, 42, 477),
|
||||
(86, 29, 258),
|
||||
(69, 59, 903),
|
||||
(34, 15, 807),
|
||||
(37, 2, 1451),
|
||||
(7, 73, 754),
|
||||
(47, 86, 184),
|
||||
(67, 17, 449),
|
||||
(18, 67, 803),
|
||||
(25, 4, 595),
|
||||
(3, 31, 1337),
|
||||
(64, 31, 1928),
|
||||
(9, 43, 237),
|
||||
(83, 63, 1604),
|
||||
(47, 45, 272),
|
||||
(86, 88, 574),
|
||||
(87, 74, 934),
|
||||
(98, 94, 646),
|
||||
(20, 1, 642),
|
||||
(26, 92, 1344),
|
||||
(18, 17, 565),
|
||||
(47, 11, 595),
|
||||
(10, 59, 1558),
|
||||
(2, 76, 1658),
|
||||
(77, 74, 1277),
|
||||
(42, 60, 477),
|
||||
(80, 36, 395),
|
||||
(35, 23, 589),
|
||||
(50, 37, 203),
|
||||
(6, 96, 481),
|
||||
(78, 65, 1052),
|
||||
(1, 52, 127),
|
||||
(65, 23, 1932),
|
||||
(46, 51, 213),
|
||||
(59, 89, 89),
|
||||
(15, 93, 1462),
|
||||
(69, 3, 1305),
|
||||
(17, 37, 1177),
|
||||
(30, 3, 193),
|
||||
(9, 15, 818),
|
||||
(75, 95, 977),
|
||||
(86, 47, 184),
|
||||
(10, 12, 1736),
|
||||
(80, 27, 1010),
|
||||
(12, 10, 1736),
|
||||
(86, 1, 1958),
|
||||
(60, 12, 1240),
|
||||
(43, 71, 683),
|
||||
(91, 65, 1519),
|
||||
(33, 86, 1649),
|
||||
(62, 26, 1773),
|
||||
(1, 13, 1187),
|
||||
(2, 10, 1018),
|
||||
(91, 29, 351),
|
||||
(69, 12, 136),
|
||||
(43, 9, 237),
|
||||
(29, 86, 258),
|
||||
(17, 48, 1807),
|
||||
(31, 64, 1928),
|
||||
(68, 61, 1936),
|
||||
(76, 38, 1724),
|
||||
(1, 6, 482),
|
||||
(53, 14, 355),
|
||||
(51, 50, 917),
|
||||
(54, 13, 815),
|
||||
(19, 29, 883),
|
||||
(35, 87, 974),
|
||||
(70, 96, 511),
|
||||
(23, 35, 589),
|
||||
(39, 69, 1588),
|
||||
(93, 73, 1093),
|
||||
(13, 73, 435),
|
||||
(5, 60, 1619),
|
||||
(42, 41, 1523),
|
||||
(66, 58, 1596),
|
||||
(1, 67, 431),
|
||||
(17, 67, 449),
|
||||
(30, 95, 906),
|
||||
(71, 43, 683),
|
||||
(5, 87, 190),
|
||||
(12, 78, 891),
|
||||
(30, 97, 402),
|
||||
(28, 17, 1131),
|
||||
(7, 97, 1356),
|
||||
(58, 66, 1596),
|
||||
(20, 37, 1294),
|
||||
(73, 76, 514),
|
||||
(54, 8, 613),
|
||||
(68, 35, 1252),
|
||||
(92, 32, 701),
|
||||
(3, 90, 652),
|
||||
(99, 46, 1576),
|
||||
(13, 54, 815),
|
||||
(20, 87, 1390),
|
||||
(36, 18, 1626),
|
||||
(51, 26, 1146),
|
||||
(2, 23, 581),
|
||||
(29, 7, 1558),
|
||||
(88, 59, 173),
|
||||
(17, 1, 1071),
|
||||
(37, 49, 1011),
|
||||
(18, 6, 696),
|
||||
(88, 33, 225),
|
||||
(58, 38, 802),
|
||||
(87, 50, 1744),
|
||||
(29, 91, 351),
|
||||
(6, 71, 1053),
|
||||
(45, 24, 1720),
|
||||
(65, 91, 1519),
|
||||
(37, 50, 203),
|
||||
(11, 3, 943),
|
||||
(72, 65, 1330),
|
||||
(45, 50, 339),
|
||||
(25, 20, 971),
|
||||
(15, 9, 818),
|
||||
(14, 54, 1353),
|
||||
(69, 95, 393),
|
||||
(8, 66, 1213),
|
||||
(52, 2, 1608),
|
||||
(50, 14, 690),
|
||||
(50, 45, 339),
|
||||
(1, 37, 1273),
|
||||
(45, 93, 1650),
|
||||
(39, 78, 313),
|
||||
(1, 86, 1958),
|
||||
(17, 28, 1131),
|
||||
(35, 33, 1667),
|
||||
(23, 2, 581),
|
||||
(51, 66, 245),
|
||||
(17, 54, 924),
|
||||
(41, 49, 1629),
|
||||
(60, 5, 1619),
|
||||
(56, 93, 1110),
|
||||
(96, 13, 461),
|
||||
(25, 7, 637),
|
||||
(11, 69, 370),
|
||||
(90, 3, 652),
|
||||
(39, 71, 1485),
|
||||
(65, 51, 1529),
|
||||
(20, 6, 1414),
|
||||
(80, 85, 270),
|
||||
(73, 83, 1162),
|
||||
(0, 97, 1303),
|
||||
(13, 33, 826),
|
||||
(29, 71, 1788),
|
||||
(33, 12, 461),
|
||||
(12, 58, 1273),
|
||||
(69, 39, 1588),
|
||||
(67, 75, 1504),
|
||||
(87, 20, 1390),
|
||||
(88, 97, 526),
|
||||
(33, 88, 225),
|
||||
(95, 69, 393),
|
||||
(2, 52, 1608),
|
||||
(5, 25, 719),
|
||||
(34, 78, 510),
|
||||
(53, 99, 1074),
|
||||
(33, 35, 1667),
|
||||
(57, 30, 361),
|
||||
(87, 58, 1574),
|
||||
(13, 90, 1030),
|
||||
(79, 74, 91),
|
||||
(4, 86, 1107),
|
||||
(64, 94, 1609),
|
||||
(11, 12, 167),
|
||||
(30, 45, 272),
|
||||
(47, 91, 561),
|
||||
(37, 17, 1177),
|
||||
(77, 49, 883),
|
||||
(88, 23, 1747),
|
||||
(70, 80, 995),
|
||||
(62, 77, 907),
|
||||
(18, 4, 371),
|
||||
(73, 93, 1093),
|
||||
(11, 47, 595),
|
||||
(44, 23, 1990),
|
||||
(20, 0, 512),
|
||||
(3, 69, 1305),
|
||||
(82, 3, 1815),
|
||||
(20, 88, 368),
|
||||
(44, 45, 364),
|
||||
(26, 51, 1146),
|
||||
(7, 65, 349),
|
||||
(71, 39, 1485),
|
||||
(56, 88, 1954),
|
||||
(94, 69, 1397),
|
||||
(12, 28, 544),
|
||||
(95, 75, 977),
|
||||
(32, 90, 789),
|
||||
(53, 1, 772),
|
||||
(54, 14, 1353),
|
||||
(49, 77, 883),
|
||||
(92, 26, 1344),
|
||||
(17, 18, 565),
|
||||
(97, 88, 526),
|
||||
(48, 80, 1203),
|
||||
(90, 32, 789),
|
||||
(71, 6, 1053),
|
||||
(87, 35, 974),
|
||||
(55, 90, 1808),
|
||||
(12, 61, 1791),
|
||||
(1, 96, 328),
|
||||
(63, 10, 1681),
|
||||
(76, 34, 871),
|
||||
(41, 64, 926),
|
||||
(42, 97, 482),
|
||||
(25, 5, 719),
|
||||
(23, 65, 1932),
|
||||
(54, 1, 1491),
|
||||
(28, 12, 544),
|
||||
(89, 10, 108),
|
||||
(27, 33, 143),
|
||||
(67, 1, 431),
|
||||
(32, 45, 52),
|
||||
(79, 33, 1871),
|
||||
(6, 55, 717),
|
||||
(10, 58, 459),
|
||||
(67, 39, 393),
|
||||
(10, 4, 1808),
|
||||
(96, 6, 481),
|
||||
(1, 19, 970),
|
||||
(97, 7, 1356),
|
||||
(29, 16, 1108),
|
||||
(1, 53, 772),
|
||||
(30, 15, 1125),
|
||||
(4, 6, 634),
|
||||
(6, 20, 1414),
|
||||
(88, 56, 1954),
|
||||
(87, 64, 1950),
|
||||
(34, 76, 871),
|
||||
(17, 12, 285),
|
||||
(55, 59, 321),
|
||||
(61, 68, 1936),
|
||||
(50, 87, 1744),
|
||||
(84, 44, 952),
|
||||
(41, 33, 993),
|
||||
(59, 18, 1352),
|
||||
(33, 27, 143),
|
||||
(38, 32, 1210),
|
||||
(55, 70, 1264),
|
||||
(38, 58, 802),
|
||||
(1, 20, 642),
|
||||
(73, 13, 435),
|
||||
(80, 48, 1203),
|
||||
(94, 64, 1609),
|
||||
(38, 28, 414),
|
||||
(73, 23, 1113),
|
||||
(78, 12, 891),
|
||||
(26, 62, 1773),
|
||||
(87, 43, 579),
|
||||
(53, 6, 95),
|
||||
(59, 95, 285),
|
||||
(88, 63, 1717),
|
||||
(17, 5, 633),
|
||||
(66, 8, 1213),
|
||||
(41, 42, 1523),
|
||||
(83, 22, 597),
|
||||
(95, 30, 906),
|
||||
(51, 65, 1529),
|
||||
(17, 49, 1727),
|
||||
(64, 87, 1950),
|
||||
(86, 4, 1107),
|
||||
(37, 98, 1102),
|
||||
(32, 92, 701),
|
||||
(60, 94, 198),
|
||||
(73, 98, 1749),
|
||||
(4, 18, 371),
|
||||
(96, 70, 511),
|
||||
(7, 29, 1558),
|
||||
(35, 37, 841),
|
||||
(27, 64, 384),
|
||||
(12, 33, 461),
|
||||
(36, 38, 529),
|
||||
(69, 16, 1183),
|
||||
(91, 47, 561),
|
||||
(85, 29, 1676),
|
||||
(3, 82, 1815),
|
||||
(69, 58, 1579),
|
||||
(93, 45, 1650),
|
||||
(97, 42, 482),
|
||||
(37, 1, 1273),
|
||||
(61, 4, 543),
|
||||
(96, 1, 328),
|
||||
(26, 0, 1993),
|
||||
(70, 64, 878),
|
||||
(3, 30, 193),
|
||||
(58, 69, 1579),
|
||||
(4, 25, 595),
|
||||
(31, 3, 1337),
|
||||
(55, 6, 717),
|
||||
(39, 67, 393),
|
||||
(78, 34, 510),
|
||||
(75, 67, 1504),
|
||||
(6, 53, 95),
|
||||
(51, 79, 175),
|
||||
(28, 91, 1040),
|
||||
(89, 78, 1828),
|
||||
(74, 93, 1587),
|
||||
(45, 32, 52),
|
||||
(10, 2, 1018),
|
||||
(49, 37, 1011),
|
||||
(63, 61, 845),
|
||||
(0, 20, 512),
|
||||
(1, 17, 1071),
|
||||
(99, 53, 1074),
|
||||
(37, 20, 1294),
|
||||
(10, 89, 108),
|
||||
(33, 92, 946),
|
||||
(23, 73, 1113),
|
||||
(23, 88, 1747),
|
||||
(49, 17, 1727),
|
||||
(88, 20, 368),
|
||||
(21, 54, 1870),
|
||||
(70, 93, 1582),
|
||||
(59, 88, 173),
|
||||
(32, 38, 1210),
|
||||
(89, 59, 89),
|
||||
(23, 44, 1990),
|
||||
(38, 76, 1724),
|
||||
(30, 57, 361),
|
||||
(94, 60, 198),
|
||||
(59, 10, 1558),
|
||||
(55, 64, 1996),
|
||||
(12, 11, 167),
|
||||
(36, 24, 1801),
|
||||
(97, 30, 402),
|
||||
(52, 1, 127),
|
||||
(58, 87, 1574),
|
||||
(54, 17, 924),
|
||||
(93, 74, 1587),
|
||||
(24, 36, 1801),
|
||||
(2, 37, 1451),
|
||||
(91, 28, 1040),
|
||||
(59, 55, 321),
|
||||
(69, 11, 370),
|
||||
(8, 54, 613),
|
||||
(29, 85, 1676),
|
||||
(44, 19, 1762),
|
||||
(74, 79, 91),
|
||||
(93, 56, 1110),
|
||||
(58, 10, 459),
|
||||
(41, 50, 1559),
|
||||
(66, 51, 245),
|
||||
(80, 19, 1838),
|
||||
(33, 79, 1871),
|
||||
(76, 73, 514),
|
||||
(98, 37, 1102),
|
||||
(45, 44, 364),
|
||||
(16, 69, 1183),
|
||||
(49, 41, 1629),
|
||||
(19, 80, 1838),
|
||||
(71, 57, 500),
|
||||
(6, 4, 634),
|
||||
(64, 27, 384),
|
||||
(84, 86, 1431),
|
||||
(5, 17, 633),
|
||||
(96, 88, 334),
|
||||
(87, 5, 190),
|
||||
(70, 21, 1619),
|
||||
(55, 33, 1391),
|
||||
(10, 63, 1681),
|
||||
(11, 62, 1339),
|
||||
(33, 13, 826),
|
||||
(64, 70, 878),
|
||||
(65, 72, 1330),
|
||||
(70, 55, 1264),
|
||||
(64, 55, 1996),
|
||||
(50, 41, 1559),
|
||||
(46, 99, 1576),
|
||||
(88, 96, 334),
|
||||
(51, 20, 868),
|
||||
(73, 7, 754),
|
||||
(80, 70, 995),
|
||||
(44, 84, 952),
|
||||
(29, 19, 883),
|
||||
(59, 69, 903),
|
||||
(57, 53, 1575),
|
||||
(90, 13, 1030),
|
||||
(28, 38, 414),
|
||||
(12, 60, 1240),
|
||||
(85, 58, 573),
|
||||
(90, 55, 1808),
|
||||
(4, 10, 1808),
|
||||
(68, 44, 1229),
|
||||
(92, 33, 946),
|
||||
(90, 81, 1024),
|
||||
(53, 75, 545),
|
||||
(45, 30, 272),
|
||||
(41, 77, 138),
|
||||
(21, 70, 1619),
|
||||
(45, 73, 1876),
|
||||
(35, 68, 1252),
|
||||
(13, 96, 461),
|
||||
(53, 57, 1575),
|
||||
(82, 89, 409),
|
||||
(28, 61, 449),
|
||||
(58, 61, 78),
|
||||
(27, 80, 1010),
|
||||
(61, 58, 78),
|
||||
(38, 36, 529),
|
||||
(80, 30, 397),
|
||||
(18, 59, 1352),
|
||||
(62, 11, 1339),
|
||||
(95, 59, 285),
|
||||
(51, 98, 1160),
|
||||
(6, 18, 696),
|
||||
(30, 80, 397),
|
||||
(69, 94, 1397),
|
||||
(58, 85, 573),
|
||||
(48, 99, 410),
|
||||
(51, 46, 213),
|
||||
(57, 71, 500),
|
||||
(91, 30, 104),
|
||||
(65, 7, 349),
|
||||
(79, 51, 175),
|
||||
(47, 26, 921),
|
||||
(4, 61, 543),
|
||||
(98, 73, 1749),
|
||||
(74, 77, 1277),
|
||||
(61, 28, 449),
|
||||
(58, 8, 1131),
|
||||
(61, 45, 1608),
|
||||
(74, 87, 934),
|
||||
(71, 29, 1788),
|
||||
(30, 91, 104),
|
||||
(13, 1, 1187),
|
||||
(0, 26, 1993),
|
||||
(82, 49, 1292),
|
||||
(43, 87, 579),
|
||||
(24, 45, 1720),
|
||||
(20, 51, 868),
|
||||
(77, 62, 907),
|
||||
(82, 75, 306),
|
||||
]
|
||||
|
||||
// Prepare graph and edge->cost map
|
||||
var graph = Array<GraphNode>()
|
||||
for n in nodes {
|
||||
graph.append(GraphNode(i: n))
|
||||
}
|
||||
var map = Dictionary<Edge, Double>()
|
||||
for tup in edges {
|
||||
map[Edge(start: tup.0, end: tup.1)] = tup.2
|
||||
graph[tup.0].adjList.append(tup.1)
|
||||
}
|
||||
|
||||
// Find spanning tree
|
||||
let treeEdges = Prims(graph, { (start: Int, end: Int) in
|
||||
return map[Edge(start: start, end: end)]!
|
||||
})
|
||||
|
||||
// Compute its cost in order to check results
|
||||
var cost = 0.0
|
||||
for i in 1..<treeEdges.count {
|
||||
if let n = treeEdges[i] { cost += map[Edge(start: n, end: i)]! }
|
||||
}
|
||||
CheckResults(Int(cost) == 49324,
|
||||
"Incorrect results in Prims: \(Int(cost)) != 49324.")
|
||||
}
|
||||
}
|
||||
24
benchmark/single-source/ProtocolDispatch.swift
Normal file
24
benchmark/single-source/ProtocolDispatch.swift
Normal file
@@ -0,0 +1,24 @@
|
||||
//===--- ProtocolDispatch.swift -------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_ProtocolDispatch(N: Int) {
|
||||
|
||||
let x = someProtocolFactory()
|
||||
|
||||
for _ in 0...1000000 * N {
|
||||
x.getValue()
|
||||
}
|
||||
}
|
||||
|
||||
104
benchmark/single-source/RC4.swift
Normal file
104
benchmark/single-source/RC4.swift
Normal file
@@ -0,0 +1,104 @@
|
||||
//===--- RC4.swift --------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test is based on util/benchmarks/RC4, with modifications
|
||||
// for performance measuring.
|
||||
import TestsUtils
|
||||
|
||||
struct RC4 {
|
||||
var State : [UInt8]
|
||||
var I : UInt8 = 0
|
||||
var J : UInt8 = 0
|
||||
|
||||
init() {
|
||||
State = [UInt8](count: 256, repeatedValue: 0)
|
||||
}
|
||||
|
||||
mutating
|
||||
func initialize(Key: [UInt8]) {
|
||||
for i in 0..<256 {
|
||||
State[i] = UInt8(i)
|
||||
}
|
||||
|
||||
var j : UInt8 = 0
|
||||
for i in 0..<256 {
|
||||
let K : UInt8 = Key[i % Key.count]
|
||||
let S : UInt8 = State[i]
|
||||
j = j &+ S &+ K
|
||||
swapByIndex(i, y: Int(j))
|
||||
}
|
||||
}
|
||||
|
||||
mutating
|
||||
func swapByIndex(x: Int, y: Int) {
|
||||
let T1 : UInt8 = State[x]
|
||||
let T2 : UInt8 = State[y]
|
||||
State[x] = T2
|
||||
State[y] = T1
|
||||
}
|
||||
|
||||
mutating
|
||||
func next() -> UInt8 {
|
||||
I = I &+ 1
|
||||
J = J &+ State[Int(I)]
|
||||
swapByIndex(Int(I), y: Int(J))
|
||||
return State[Int(State[Int(I)] &+ State[Int(J)]) & 0xFF]
|
||||
}
|
||||
|
||||
mutating
|
||||
func encrypt(inout Data: [UInt8]) {
|
||||
let cnt = Data.count
|
||||
for i in 0..<cnt {
|
||||
Data[i] = Data[i] ^ next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let RefResults : [UInt8] = [245, 62, 245, 202, 138, 120, 186, 107, 255, 189,
|
||||
184, 223, 65, 77, 112, 201, 238, 161, 74, 192, 145,
|
||||
21, 43, 41, 91, 136, 182, 176, 237, 155, 208, 16,
|
||||
17, 139, 33, 195, 24, 136, 79, 183, 211, 21, 56,
|
||||
202, 235, 65, 201, 184, 68, 29, 110, 218, 112, 122,
|
||||
194, 77, 41, 230, 147, 84, 0, 233, 168, 6, 55, 131,
|
||||
70, 119, 41, 119, 234, 131, 87, 24, 51, 130, 28,
|
||||
66, 172, 105, 33, 97, 179, 48, 81, 229, 114, 216,
|
||||
208, 119, 39, 31, 47, 109, 172, 215, 246, 210, 48,
|
||||
203]
|
||||
|
||||
|
||||
@inline(never)
|
||||
public func run_RC4(N: Int) {
|
||||
let messageLen = 100
|
||||
let iterations = 500
|
||||
let Secret = "This is my secret message"
|
||||
let Key = "This is my key"
|
||||
let SecretData : [UInt8] = Array(Secret.utf8)
|
||||
let KeyData : [UInt8] = Array(Key.utf8)
|
||||
|
||||
var LongData : [UInt8] = [UInt8](count: messageLen, repeatedValue: 0)
|
||||
|
||||
for _ in 1...N {
|
||||
// Generate a long message.
|
||||
for i in 0..<messageLen {
|
||||
LongData[i] = SecretData[i % SecretData.count]
|
||||
}
|
||||
|
||||
var Enc = RC4()
|
||||
Enc.initialize(KeyData)
|
||||
|
||||
for _ in 1...iterations {
|
||||
Enc.encrypt(&LongData)
|
||||
}
|
||||
|
||||
CheckResults(LongData == RefResults, "Incorrect result in RC4")
|
||||
}
|
||||
}
|
||||
112
benchmark/single-source/RGBHistogram.swift
Normal file
112
benchmark/single-source/RGBHistogram.swift
Normal file
@@ -0,0 +1,112 @@
|
||||
//===--- RGBHistogram.swift -----------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Performance benchmark for creating RGB histograms
|
||||
// rdar://problem/18539486
|
||||
//
|
||||
// Description:
|
||||
// Create a sorted sparse RGB histogram from an array of 300 RGB values.
|
||||
import Foundation
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_RGBHistogram(N: Int) {
|
||||
var histogram = [(rrggbb_t, Int)]()
|
||||
for _ in 1...100*N {
|
||||
histogram = createSortedSparseRGBHistogram(samples)
|
||||
if !isCorrectHistogram(histogram) {
|
||||
break
|
||||
}
|
||||
}
|
||||
CheckResults(isCorrectHistogram(histogram),
|
||||
"Incorrect results in histogram")
|
||||
}
|
||||
|
||||
typealias rrggbb_t = UInt32
|
||||
|
||||
let samples: [rrggbb_t] = [
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0x00FF0000, 0x00FF0000, 0x000000FF, 0x000000FF, 0x000000FF, 0x000000FF,
|
||||
0x00000000, 0x00555555, 0x00AAAAAA, 0x00FFFFFF, 0x00AAAAAA, 0x00FFFFFF,
|
||||
0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080, 0x00808080,
|
||||
0xCCD45FBC, 0xA56F39E4, 0x8C08DBA7, 0xDA4413D7, 0x43926C6B, 0x592975FE,
|
||||
0xC77E47ED, 0xB28F427D, 0x90D7C464, 0x805A003A, 0xAB79B390, 0x49D859B3,
|
||||
0x2419213A, 0x69E8C61D, 0xC4BE948F, 0x896CC6D0, 0xE4F3DFF1, 0x466B68FA,
|
||||
0xC8084E2A, 0x3FC1F2C4, 0x0E0D47F4, 0xB268BFE6, 0x9F990E6A, 0x7389F2F8,
|
||||
0x0720FD81, 0x65388005, 0xD8307612, 0xEC75B9B0, 0xB0C51360, 0x29647EB4,
|
||||
0x6E8B02E6, 0xEFE9F0F4, 0xFEF0EB89, 0x41BBD587, 0xCD19E510, 0x6A710BBD,
|
||||
0xFF146228, 0xFB34AD0C, 0x2AEB5588, 0x71993821, 0x9FC8CA5C, 0xF99E969B,
|
||||
0x8DF78241, 0x21ADFB7C, 0x4DE5E465, 0x0C171D2F, 0x2C08CECF, 0x3318440A,
|
||||
0xEC8F8D1C, 0x6CAFD68E, 0xCA35F571, 0x68A37E1A, 0x3047F87F, 0x50CC39DE,
|
||||
0x776CF5CB, 0x75DC4595, 0x77E32288, 0x14899C0D, 0x14835CF6, 0x0A732F76,
|
||||
0xA4B05790, 0x34CBED42, 0x5A6964CE, 0xEA4CA5F7, 0x3DECB0F1, 0x5015D419,
|
||||
0x84EBC299, 0xC656B381, 0xFA2840C5, 0x618D754E, 0x003B8D96, 0xCE91AA8E,
|
||||
0xBD9784DB, 0x9372E919, 0xC138BEA6, 0xF0B3E3AD, 0x4E4F60BF, 0xC1598ABE,
|
||||
0x930873DB, 0x0F029E3A, 0xBEFC0125, 0x10645D6D, 0x1FF93547, 0xA7069CB5,
|
||||
0xCF0B7E06, 0xE33EDC17, 0x8C5E1F48, 0x2FB345E1, 0x3B0070E0, 0x0421E568,
|
||||
0xB39A42A0, 0xB935DA8B, 0x281C30F0, 0xB2E48677, 0x277A9A45, 0x52AF9FC6,
|
||||
0xBBDF4048, 0xC668137A, 0xF39020D1, 0x71BEE810, 0x5F2B3825, 0x25C863FB,
|
||||
0x876144E8, 0x9B4108C3, 0xF735CB08, 0x8B77DEEC, 0x0185A067, 0xB964F42B,
|
||||
0xA2EC236B, 0x3C08646F, 0xB514C4BE, 0x37EE9689, 0xACF97317, 0x1EA4F7C6,
|
||||
0x453A6F13, 0x01C25E42, 0xA052BB3B, 0x71A699CB, 0xC728AE88, 0x128A656F,
|
||||
0x78F64E55, 0x045967E0, 0xC5DC4125, 0xDA39F6FE, 0x873785B9, 0xB6BB446A,
|
||||
0xF4F5093F, 0xAF05A4EC, 0xB5DB854B, 0x7ADA6A37, 0x9EA218E3, 0xCCCC9316,
|
||||
0x86A133F8, 0x8AF47795, 0xCBA235D4, 0xBB9101CC, 0xBCC8C8A3, 0x02BAC911,
|
||||
0x45C17A8C, 0x896C81FC, 0x4974FA22, 0xEA7CD629, 0x103ED364, 0x4C644503,
|
||||
0x607F4D9F, 0x9733E55E, 0xA360439D, 0x1DB568FD, 0xB7A5C3A1, 0xBE84492D
|
||||
]
|
||||
|
||||
func isCorrectHistogram(histogram: [(rrggbb_t, Int)]) -> Bool {
|
||||
return histogram.count == 157 &&
|
||||
histogram[0].0 == 0x00808080 && histogram[0].1 == 54 &&
|
||||
histogram[156].0 == 0x003B8D96 && histogram[156].1 == 1
|
||||
}
|
||||
|
||||
func createSortedSparseRGBHistogram
|
||||
<S: SequenceType where S.Generator.Element == rrggbb_t>
|
||||
(samples: S) -> [(rrggbb_t, Int)] {
|
||||
var histogram = Dictionary<rrggbb_t, Int>()
|
||||
|
||||
for sample in samples {
|
||||
let i = histogram.indexForKey(sample)
|
||||
histogram[sample] = ((i != nil) ? histogram[i!].1 : 0) + 1
|
||||
}
|
||||
|
||||
return histogram.sort() {
|
||||
if $0.1 == $1.1 {
|
||||
return $0.0 > $1.0
|
||||
} else {
|
||||
return $0.1 > $1.1
|
||||
}
|
||||
}
|
||||
}
|
||||
27
benchmark/single-source/RangeAssignment.swift
Normal file
27
benchmark/single-source/RangeAssignment.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
//===--- RangeAssignment.swift --------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_RangeAssignment(scale: Int) {
|
||||
let range = 100..<200
|
||||
var vector = [Double](count: 5000, repeatedValue: 0.0 )
|
||||
let alfa = 1.0
|
||||
let N = 500*scale
|
||||
for _ in 1...N {
|
||||
vector[range] = ArraySlice(vector[range].map { $0 + alfa })
|
||||
}
|
||||
|
||||
CheckResults(vector[100] == Double(N),
|
||||
"IncorrectResults in RangeAssignment: \(vector[100]) != \(N).")
|
||||
}
|
||||
57
benchmark/single-source/RecursiveOwnedParameter.swift
Normal file
57
benchmark/single-source/RecursiveOwnedParameter.swift
Normal file
@@ -0,0 +1,57 @@
|
||||
//===--- RecursiveOwnedParameter.swift ------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
// This test recursively visits each element of an array in a class and compares
|
||||
// it with every value in a different array stored in a different class. The
|
||||
// idea is to make sure that we can get rid of the overhead from gauranteed
|
||||
// parameters.
|
||||
|
||||
// We use final since we are not interesting in devirtualization for the
|
||||
// purposes of this test.
|
||||
final
|
||||
class ArrayWrapper {
|
||||
var data: [Int]
|
||||
|
||||
init(_ count: Int, _ initialValue: Int) {
|
||||
data = [Int](count: count, repeatedValue: initialValue)
|
||||
}
|
||||
|
||||
func compare(b: ArrayWrapper, _ iteration: Int, _ stopIteration: Int) -> Bool {
|
||||
// We will never return true here by design. We want to test the full effect
|
||||
// every time of retaining, releasing.
|
||||
if iteration == stopIteration || data[iteration] == b.data[iteration] {
|
||||
return true
|
||||
}
|
||||
|
||||
return compare(b, iteration &+ 1, stopIteration)
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_RecursiveOwnedParameter(N: Int) {
|
||||
let numElts = 1_000
|
||||
|
||||
let a = ArrayWrapper(numElts, 0)
|
||||
let b = ArrayWrapper(numElts, 1)
|
||||
|
||||
var result = 0
|
||||
for _ in 0..<100*N {
|
||||
if a.compare(b, 0, numElts) {
|
||||
result += 1
|
||||
}
|
||||
}
|
||||
let refResult = 100*N
|
||||
CheckResults(result == refResult,
|
||||
"IncorrectResults in RecursiveOwnedParameter: \(result) != \(refResult)")
|
||||
}
|
||||
105
benchmark/single-source/SetTests.swift
Normal file
105
benchmark/single-source/SetTests.swift
Normal file
@@ -0,0 +1,105 @@
|
||||
//===--- SetTests.swift ---------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_SetIsSubsetOf(N: Int) {
|
||||
let size = 200
|
||||
|
||||
SRand()
|
||||
|
||||
var set = Set<Int>(minimumCapacity: size)
|
||||
var otherSet = Set<Int>(minimumCapacity: size)
|
||||
|
||||
for _ in 0 ..< size {
|
||||
set.insert(Int(truncatingBitPattern: Random()))
|
||||
otherSet.insert(Int(truncatingBitPattern: Random()))
|
||||
}
|
||||
|
||||
var isSubset = false;
|
||||
for _ in 0 ..< N * 5000 {
|
||||
isSubset = set.isSubsetOf(otherSet)
|
||||
if isSubset {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
CheckResults(!isSubset, "Incorrect results in SetIsSubsetOf")
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func sink(inout s: Set<Int>) {
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_SetExclusiveOr(N: Int) {
|
||||
let size = 400
|
||||
|
||||
SRand()
|
||||
|
||||
var set = Set<Int>(minimumCapacity: size)
|
||||
var otherSet = Set<Int>(minimumCapacity: size)
|
||||
|
||||
for _ in 0 ..< size {
|
||||
set.insert(Int(truncatingBitPattern: Random()))
|
||||
otherSet.insert(Int(truncatingBitPattern: Random()))
|
||||
}
|
||||
|
||||
var xor = Set<Int>()
|
||||
for _ in 0 ..< N * 100 {
|
||||
xor = set.exclusiveOr(otherSet)
|
||||
}
|
||||
sink(&xor)
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_SetUnion(N: Int) {
|
||||
let size = 400
|
||||
|
||||
SRand()
|
||||
|
||||
var set = Set<Int>(minimumCapacity: size)
|
||||
var otherSet = Set<Int>(minimumCapacity: size)
|
||||
|
||||
for _ in 0 ..< size {
|
||||
set.insert(Int(truncatingBitPattern: Random()))
|
||||
otherSet.insert(Int(truncatingBitPattern: Random()))
|
||||
}
|
||||
|
||||
var or = Set<Int>()
|
||||
for _ in 0 ..< N * 100 {
|
||||
or = set.union(otherSet)
|
||||
}
|
||||
sink(&or)
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_SetIntersect(N: Int) {
|
||||
let size = 400
|
||||
|
||||
SRand()
|
||||
|
||||
var set = Set<Int>(minimumCapacity: size)
|
||||
var otherSet = Set<Int>(minimumCapacity: size)
|
||||
|
||||
for _ in 0 ..< size {
|
||||
set.insert(Int(truncatingBitPattern: Random()))
|
||||
otherSet.insert(Int(truncatingBitPattern: Random()))
|
||||
}
|
||||
|
||||
var and = Set<Int>()
|
||||
for _ in 0 ..< N * 100 {
|
||||
and = set.intersect(otherSet)
|
||||
}
|
||||
sink(&and)
|
||||
}
|
||||
36
benchmark/single-source/SevenBoom.swift
Normal file
36
benchmark/single-source/SevenBoom.swift
Normal file
@@ -0,0 +1,36 @@
|
||||
//===--- SevenBoom.swift --------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
import Foundation
|
||||
|
||||
@inline(never)
|
||||
func filter_seven(input : Int) throws {
|
||||
guard case 7 = input else {
|
||||
throw NSError(domain: "AnDomain", code: 42, userInfo: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_SevenBoom(N: Int) {
|
||||
var c = 0
|
||||
for i in 1...N*5000 {
|
||||
do {
|
||||
try filter_seven(i)
|
||||
c += 1
|
||||
}
|
||||
catch _ {
|
||||
}
|
||||
}
|
||||
CheckResults(c == 1, "IncorrectResults in SevenBoom")
|
||||
}
|
||||
|
||||
42
benchmark/single-source/Sim2DArray.swift
Normal file
42
benchmark/single-source/Sim2DArray.swift
Normal file
@@ -0,0 +1,42 @@
|
||||
//===--- Sim2DArray.swift -------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
struct Array2D {
|
||||
var storage : [Int]
|
||||
let rows : Int
|
||||
let cols: Int
|
||||
|
||||
init(numRows: Int, numCols: Int) {
|
||||
storage = [Int](count: numRows * numCols, repeatedValue: 0)
|
||||
rows = numRows
|
||||
cols = numCols
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
func workload_2DArrayTest(inout A: Array2D) {
|
||||
for _ in 0 ..< 10 {
|
||||
for r in 0 ..< A.rows {
|
||||
for c in 0 ..< A.cols {
|
||||
A.storage[r*A.cols+c] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_Sim2DArray(N : Int) {
|
||||
for _ in 0 ..< N {
|
||||
var A = Array2D(numRows:2048, numCols:32)
|
||||
workload_2DArrayTest(&A)
|
||||
}
|
||||
}
|
||||
46
benchmark/single-source/SortLettersInPlace.swift
Normal file
46
benchmark/single-source/SortLettersInPlace.swift
Normal file
@@ -0,0 +1,46 @@
|
||||
//===--- SortLettersInPlace.swift -----------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test checks performance and correctness of Swift sortInPlace on an
|
||||
// array of letters.
|
||||
import Foundation
|
||||
import TestsUtils
|
||||
|
||||
class Letter {
|
||||
let value: String
|
||||
init(_ value: String) {
|
||||
self.value = value
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_SortLettersInPlace(N: Int) {
|
||||
for _ in 1...100*N {
|
||||
var letters = [
|
||||
Letter("k"), Letter("a"), Letter("x"), Letter("i"), Letter("f"), Letter("l"),
|
||||
Letter("o"), Letter("w"), Letter("h"), Letter("p"), Letter("b"), Letter("u"),
|
||||
Letter("n"), Letter("c"), Letter("j"), Letter("t"), Letter("y"), Letter("s"),
|
||||
Letter("d"), Letter("v"), Letter("r"), Letter("e"), Letter("q"), Letter("m"),
|
||||
Letter("z"), Letter("g")
|
||||
]
|
||||
|
||||
// Sort the letters in place.
|
||||
letters.sortInPlace {
|
||||
return $0.value < $1.value
|
||||
}
|
||||
|
||||
// Check whether letters are sorted.
|
||||
CheckResults(letters[0].value <= letters[letters.count/2].value,
|
||||
"Incorrect results in SortLetterInPlace.")
|
||||
}
|
||||
}
|
||||
|
||||
1031
benchmark/single-source/SortStrings.swift
Normal file
1031
benchmark/single-source/SortStrings.swift
Normal file
File diff suppressed because it is too large
Load Diff
27
benchmark/single-source/StrComplexWalk.swift
Normal file
27
benchmark/single-source/StrComplexWalk.swift
Normal file
@@ -0,0 +1,27 @@
|
||||
//===--- StrComplexWalk.swift ---------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_StrComplexWalk(N: Int) {
|
||||
var s = "निरन्तरान्धकारिता-दिगन्तर-कन्दलदमन्द-सुधारस-बिन्दु-सान्द्रतर-घनाघन-वृन्द-सन्देहकर-स्यन्दमान-मकरन्द-बिन्दु-बन्धुरतर-माकन्द-तरु-कुल-तल्प-कल्प-मृदुल-सिकता-जाल-जटिल-मूल-तल-मरुवक-मिलदलघु-लघु-लय-कलित-रमणीय-पानीय-शालिका-बालिका-करार-विन्द-गलन्तिका-गलदेला-लवङ्ग-पाटल-घनसार-कस्तूरिकातिसौरभ-मेदुर-लघुतर-मधुर-शीतलतर-सलिलधारा-निराकरिष्णु-तदीय-विमल-विलोचन-मयूख-रेखापसारित-पिपासायास-पथिक-लोकान्"
|
||||
let ref_result = 379
|
||||
for _ in 1...2000*N {
|
||||
var count = 0
|
||||
for _ in s.unicodeScalars {
|
||||
count += 1
|
||||
}
|
||||
CheckResults(count == ref_result, "Incorrect results in StrComplexWalk: \(count) != \(ref_result)")
|
||||
}
|
||||
}
|
||||
|
||||
47
benchmark/single-source/StrToInt.swift
Normal file
47
benchmark/single-source/StrToInt.swift
Normal file
@@ -0,0 +1,47 @@
|
||||
//===--- StrToInt.swift ---------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test checks performance of String to Int conversion.
|
||||
// It is reported to be very slow: <rdar://problem/17255477>
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_StrToInt(N: Int) {
|
||||
// 64 numbers from -500_000 to 500_000 generated randomly
|
||||
let input = ["-237392", "293715", "126809", "333779", "-362824", "144198",
|
||||
"-394973", "-163669", "-7236", "376965", "-400783", "-118670",
|
||||
"454728", "-38915", "136285", "-448481", "-499684", "68298",
|
||||
"382671", "105432", "-38385", "39422", "-267849", "-439886",
|
||||
"292690", "87017", "404692", "27692", "486408", "336482",
|
||||
"-67850", "56414", "-340902", "-391782", "414778", "-494338",
|
||||
"-413017", "-377452", "-300681", "170194", "428941", "-291665",
|
||||
"89331", "329496", "-364449", "272843", "-10688", "142542",
|
||||
"-417439", "167337", "96598", "-264104", "-186029", "98480",
|
||||
"-316727", "483808", "300149", "-405877", "-98938", "283685",
|
||||
"-247856", "-46975", "346060", "160085",]
|
||||
let ref_result = 517492
|
||||
func DoOneIter(arr: [String]) -> Int {
|
||||
var r = 0
|
||||
for n in arr {
|
||||
r += Int(n)!
|
||||
}
|
||||
if r < 0 {
|
||||
r = -r
|
||||
}
|
||||
return r
|
||||
}
|
||||
var res = Int.max
|
||||
for _ in 1...1000*N {
|
||||
res = res & DoOneIter(input)
|
||||
}
|
||||
CheckResults(res == ref_result, "IncorrectResults in StrToInt: \(res) != \(ref_result)")
|
||||
}
|
||||
30
benchmark/single-source/StringBuilder.swift
Normal file
30
benchmark/single-source/StringBuilder.swift
Normal file
@@ -0,0 +1,30 @@
|
||||
//===--- StringBuilder.swift ----------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
func buildString() -> String {
|
||||
var sb = "a"
|
||||
for str in ["b","c","d","pizza"] {
|
||||
sb += str
|
||||
}
|
||||
return sb
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_StringBuilder(N: Int) {
|
||||
for _ in 1...5000*N {
|
||||
buildString()
|
||||
}
|
||||
}
|
||||
|
||||
41
benchmark/single-source/StringInterpolation.swift
Normal file
41
benchmark/single-source/StringInterpolation.swift
Normal file
@@ -0,0 +1,41 @@
|
||||
//===--- StringInterpolation.swift ----------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
class RefTypePrintable : CustomStringConvertible {
|
||||
var description: String {
|
||||
return "01234567890123456789012345678901234567890123456789"
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_StringInterpolation(N: Int) {
|
||||
let reps = 100
|
||||
let refResult = reps
|
||||
let anInt: Int64 = 0x1234567812345678
|
||||
let aRefCountedObject = RefTypePrintable()
|
||||
|
||||
for _ in 1...100*N {
|
||||
var result = 0
|
||||
for _ in 1...reps {
|
||||
let s = "\(anInt) abcdefdhijklmn \(aRefCountedObject) abcdefdhijklmn \u{01}"
|
||||
|
||||
// FIXME: if String is not stored as UTF-16 on this platform, then the
|
||||
// following operation has a non-trivial cost and needs to be replaced
|
||||
// with an operation on the native storage type.
|
||||
result = result &+ Int(s.utf16[s.utf16.endIndex.predecessor()])
|
||||
}
|
||||
CheckResults(result == refResult, "IncorrectResults in StringInterpolation: \(result) != \(refResult)")
|
||||
}
|
||||
}
|
||||
|
||||
18
benchmark/single-source/StringTests.swift
Normal file
18
benchmark/single-source/StringTests.swift
Normal file
@@ -0,0 +1,18 @@
|
||||
//===--- StringTests.swift ------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
public func run_StringWithCString(N: Int) {
|
||||
let str = String(count:100 * (1 << 16), repeatedValue:"x" as UnicodeScalar)
|
||||
for _ in 0 ..< N {
|
||||
str.withCString { _ in }
|
||||
}
|
||||
}
|
||||
38
benchmark/single-source/StringWalk.swift
Normal file
38
benchmark/single-source/StringWalk.swift
Normal file
@@ -0,0 +1,38 @@
|
||||
//===--- StringWalk.swift -------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Test String subscript performance.
|
||||
//
|
||||
// Subscript has a slow path that initializes a global variable:
|
||||
// Swift._cocoaStringSubscript.addressor. Global optimization would
|
||||
// normally hoist the initializer outside the inner loop (over
|
||||
// unicodeScalars), forcing the initializer to be called on each
|
||||
// lap. However, no that the cocoa code is properly marked "slowPath",
|
||||
// no hoisting should occur.
|
||||
import TestsUtils
|
||||
|
||||
var count: Int = 0
|
||||
|
||||
@inline(never) func countChars(s: String) {
|
||||
for _ in s.unicodeScalars {
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_StringWalk(N: Int) {
|
||||
let s = "siebenhundertsiebenundsiebzigtausendsiebenhundertsiebenundsiebzig"
|
||||
|
||||
for _ in 1...50000*N {
|
||||
countChars(s)
|
||||
}
|
||||
}
|
||||
42
benchmark/single-source/SuperChars.swift
Normal file
42
benchmark/single-source/SuperChars.swift
Normal file
@@ -0,0 +1,42 @@
|
||||
//===--- SuperChars.swift -------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test tests the performance of ASCII Character comparison.
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_SuperChars(N: Int) {
|
||||
// Permute some characters.
|
||||
let alphabet: [Character] = [
|
||||
"A", "B", "C", "D", "E", "F", "G",
|
||||
"«", // throw in some unicode to make it slower
|
||||
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
|
||||
"á", "お",
|
||||
"S", "T", "U",
|
||||
"🇯🇵",
|
||||
"V", "W", "X", "Y", "Z", "/", "f", "Z", "z", "6", "7", "C", "j", "f", "9",
|
||||
"🇯🇵🇺🇸", "🇯🇵🇺🇸🇨🇳", "🇯🇵🇺🇸🇨🇳🇩🇪",
|
||||
"g", "g", "I", "J", "K", "c", "x", "i", ".",
|
||||
"🇯🇵🇺🇸🇨🇳🇩🇪", "🇯🇵🇺🇸", "🇯🇵🇺🇸🇨🇳",
|
||||
"2", "a", "t", "i", "o", "e", "q", "n", "X", "Y", "Z", "?", "m", "Z", ","
|
||||
]
|
||||
|
||||
for _ in 0...N {
|
||||
for firstChar in alphabet {
|
||||
for middleChar in alphabet {
|
||||
for lastChar in alphabet {
|
||||
_ = ((firstChar == middleChar) != (middleChar < lastChar))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
benchmark/single-source/TwoSum.swift
Normal file
79
benchmark/single-source/TwoSum.swift
Normal file
@@ -0,0 +1,79 @@
|
||||
//===--- TwoSum.swift -----------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// This test is solves 2SUM problem:
|
||||
// Given an array and a number C, find elements A and B such that A+B = C
|
||||
import TestsUtils
|
||||
|
||||
let array = [
|
||||
959, 81, 670, 727, 416, 171, 401, 398, 707, 596, 200, 9, 414, 98, 43,
|
||||
352, 752, 158, 593, 418, 240, 912, 542, 445, 429, 456, 993, 618, 52, 649,
|
||||
759, 190, 126, 306, 966, 37, 787, 981, 606, 372, 597, 901, 158, 284, 809,
|
||||
820, 173, 538, 644, 428, 932, 967, 962, 959, 233, 467, 220, 8, 729, 889,
|
||||
277, 494, 554, 670, 91, 657, 606, 248, 644, 8, 366, 815, 567, 993, 696,
|
||||
763, 800, 531, 301, 863, 680, 703, 279, 388, 871, 124, 302, 617, 410, 366,
|
||||
813, 599, 543, 508, 336, 312, 212, 86, 524, 64, 641, 533, 207, 893, 146,
|
||||
534, 104, 888, 534, 464, 423, 583, 365, 420, 642, 514, 336, 974, 846, 437,
|
||||
604, 121, 180, 794, 278, 467, 818, 603, 537, 167, 169, 704, 9, 843, 555,
|
||||
154, 598, 566, 676, 682, 828, 128, 875, 445, 918, 505, 393, 571, 3, 406,
|
||||
719, 165, 505, 750, 396, 726, 404, 391, 532, 403, 728, 240, 89, 917, 665,
|
||||
561, 282, 302, 438, 714, 6, 290, 939, 200, 788, 128, 773, 900, 934, 772,
|
||||
130, 884, 60, 870, 812, 750, 349, 35, 155, 905, 595, 806, 771, 443, 304,
|
||||
283, 404, 905, 861, 820, 338, 380, 709, 927, 42, 478, 789, 656, 106, 218,
|
||||
412, 453, 262, 864, 701, 686, 770, 34, 624, 597, 843, 913, 966, 230, 942,
|
||||
112, 991, 299, 669, 399, 630, 943, 934, 448, 62, 745, 917, 397, 440, 286,
|
||||
875, 22, 989, 235, 732, 906, 923, 643, 853, 68, 48, 524, 86, 89, 688,
|
||||
224, 546, 73, 963, 755, 413, 524, 680, 472, 19, 996, 81, 100, 338, 626,
|
||||
911, 358, 887, 242, 159, 731, 494, 985, 83, 597, 98, 270, 909, 828, 988,
|
||||
684, 622, 499, 932, 299, 449, 888, 533, 801, 844, 940, 642, 501, 513, 735,
|
||||
674, 211, 394, 635, 372, 213, 618, 280, 792, 487, 605, 755, 584, 163, 358,
|
||||
249, 784, 153, 166, 685, 264, 457, 677, 824, 391, 830, 310, 629, 591, 62,
|
||||
265, 373, 195, 803, 756, 601, 592, 843, 184, 220, 155, 396, 828, 303, 553,
|
||||
778, 477, 735, 430, 93, 464, 306, 579, 828, 759, 809, 916, 759, 336, 926,
|
||||
776, 111, 746, 217, 585, 441, 928, 236, 959, 417, 268, 200, 231, 181, 228,
|
||||
627, 675, 814, 534, 90, 665, 1, 604, 479, 598, 109, 370, 719, 786, 700,
|
||||
591, 536, 7, 147, 648, 864, 162, 404, 536, 768, 175, 517, 394, 14, 945,
|
||||
865, 490, 630, 963, 49, 904, 277, 16, 349, 301, 840, 817, 590, 738, 357,
|
||||
199, 581, 601, 33, 659, 951, 640, 126, 302, 632, 265, 894, 892, 587, 274,
|
||||
487, 499, 789, 954, 652, 825, 512, 170, 882, 269, 471, 571, 185, 364, 217,
|
||||
427, 38, 715, 950, 808, 270, 746, 830, 501, 264, 581, 211, 466, 970, 395,
|
||||
610, 930, 885, 696, 568, 920, 487, 764, 896, 903, 241, 894, 773, 896, 341,
|
||||
126, 22, 420, 959, 691, 207, 745, 126, 873, 341, 166, 127, 108, 426, 497,
|
||||
681, 796, 430, 367, 363
|
||||
]
|
||||
|
||||
@inline(never)
|
||||
public func run_TwoSum(N: Int) {
|
||||
var i1: Int?
|
||||
var i2: Int?
|
||||
var Dict: Dictionary<Int, Int> = [:]
|
||||
for _ in 1...2*N {
|
||||
for Sum in 500..<600 {
|
||||
Dict = [:]
|
||||
i1 = nil
|
||||
i2 = nil
|
||||
for n in 0..<array.count {
|
||||
if let m = Dict[Sum-array[n]] {
|
||||
i1 = m
|
||||
i2 = n
|
||||
break
|
||||
}
|
||||
Dict[array[n]] = n
|
||||
}
|
||||
CheckResults(i1 != nil && i2 != nil,
|
||||
"Incorrect results in TwoSum: i1 or i2 wasn't found.")
|
||||
CheckResults(Sum == array[i1!] + array[i2!],
|
||||
"Incorrect results in TwoSum: Sum: \(Sum), " +
|
||||
"array[i1]: \(array[i1!]), array[i2]: \(array[i2!]).")
|
||||
}
|
||||
}
|
||||
}
|
||||
83
benchmark/single-source/Walsh.swift
Normal file
83
benchmark/single-source/Walsh.swift
Normal file
@@ -0,0 +1,83 @@
|
||||
//===--- Walsh.swift ------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
import Darwin
|
||||
|
||||
func IsPowerOfTwo(x: Int) -> Bool { return (x & (x - 1)) == 0 }
|
||||
|
||||
//Fast Walsh Hadamard Transform
|
||||
func WalshTransform(inout data: [Double]) {
|
||||
assert(IsPowerOfTwo(data.count), "Not a power of two")
|
||||
var temp = [Double](count: data.count, repeatedValue: 0)
|
||||
var ret = WalshImpl(&data, &temp, 0, data.count)
|
||||
for i in 0..<data.count {
|
||||
data[i] = ret[i]
|
||||
}
|
||||
}
|
||||
|
||||
func Scale(inout data : [Double], _ scalar : Double) {
|
||||
for i in 0..<data.count {
|
||||
data[i] = data[i] * scalar
|
||||
}
|
||||
}
|
||||
|
||||
func InverseWalshTransform(inout data: [Double]) {
|
||||
WalshTransform(&data)
|
||||
Scale(&data, Double(1)/Double(data.count))
|
||||
}
|
||||
|
||||
func WalshImpl(inout data: [Double], inout _ temp: [Double], _ start: Int, _ size: Int) -> [Double] {
|
||||
if (size == 1) { return data }
|
||||
|
||||
let stride = size/2
|
||||
for i in 0..<stride {
|
||||
temp[start + i] = data[start + i + stride] + data[start + i]
|
||||
temp[start + i + stride] = data[start + i] - data[start + i + stride]
|
||||
}
|
||||
|
||||
WalshImpl(&temp, &data, start, stride)
|
||||
return WalshImpl(&temp, &data, start + stride, stride)
|
||||
}
|
||||
|
||||
func checkCorrectness() {
|
||||
var In : [Double] = [1,0,1,0,0,1,1,0]
|
||||
var Out : [Double] = [4,2,0,-2,0,2,0,2]
|
||||
var data : [Double] = In
|
||||
WalshTransform(&data)
|
||||
var mid = data
|
||||
InverseWalshTransform(&data)
|
||||
for i in 0..<In.count {
|
||||
// Check encode.
|
||||
CheckResults(abs(data[i] - In[i]) < 0.0001, "Incorrect results in Walsh.")
|
||||
// Check decode.
|
||||
CheckResults(abs(mid[i] - Out[i]) < 0.0001, "Incorrect results in Walsh.")
|
||||
}
|
||||
}
|
||||
|
||||
@inline(never)
|
||||
public func run_Walsh(N : Int) {
|
||||
checkCorrectness()
|
||||
|
||||
// Generate data.
|
||||
var data2 : [Double] = []
|
||||
for i in 0..<1024 {
|
||||
data2.append(Double(sin(Float(i))))
|
||||
}
|
||||
|
||||
// Transform back and forth.
|
||||
for _ in 1...10*N {
|
||||
WalshTransform(&data2)
|
||||
InverseWalshTransform(&data2)
|
||||
}
|
||||
}
|
||||
|
||||
28
benchmark/single-source/XorLoop.swift
Normal file
28
benchmark/single-source/XorLoop.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
//===--- XorLoop.swift ----------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import TestsUtils
|
||||
|
||||
@inline(never)
|
||||
public func run_XorLoop(N: Int) {
|
||||
for _ in 1...5*N {
|
||||
let size = 100000
|
||||
let ref_result = 47813324
|
||||
var x = [Int](count: size, repeatedValue: 0xA05FD)
|
||||
for i in 0..<size {
|
||||
x[i] = x[i] ^ 12345678
|
||||
}
|
||||
let res = x[10]+x[100]+x[1000]+x[10000]
|
||||
CheckResults(res == ref_result,
|
||||
"Incorrect results in XorLoop: \(res) != \(ref_result)")
|
||||
}
|
||||
}
|
||||
78
benchmark/utils/ArgParse.swift
Normal file
78
benchmark/utils/ArgParse.swift
Normal file
@@ -0,0 +1,78 @@
|
||||
//===--- ArgParse.swift ---------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Arguments {
|
||||
public var progName: String
|
||||
public var positionalArgs: [String]
|
||||
public var optionalArgsMap: [String : String]
|
||||
|
||||
init(_ pName: String, _ posArgs: [String], _ optArgsMap: [String : String]) {
|
||||
progName = pName
|
||||
positionalArgs = posArgs
|
||||
optionalArgsMap = optArgsMap
|
||||
}
|
||||
}
|
||||
|
||||
/// Using Process.arguments, returns an Arguments struct describing
|
||||
/// the arguments to this program. If we fail to parse arguments, we
|
||||
/// return .None.
|
||||
///
|
||||
/// We assume that optional switch args are of the form:
|
||||
///
|
||||
/// --opt-name[=opt-value]
|
||||
/// -opt-name[=opt-value]
|
||||
///
|
||||
/// with opt-name and opt-value not containing any '=' signs. Any
|
||||
/// other option passed in is assumed to be a positional argument.
|
||||
public func parseArgs(validOptions: [String]? = .None)
|
||||
-> Arguments? {
|
||||
let progName = Process.arguments[0]
|
||||
var positionalArgs = [String]()
|
||||
var optionalArgsMap = [String : String]()
|
||||
|
||||
// For each argument we are passed...
|
||||
var passThroughArgs = false
|
||||
for arg in Process.arguments[1..<Process.arguments.count] {
|
||||
// If the argument doesn't match the optional argument pattern. Add
|
||||
// it to the positional argument list and continue...
|
||||
if passThroughArgs || !arg.characters.startsWith("-".characters) {
|
||||
positionalArgs.append(arg)
|
||||
continue
|
||||
}
|
||||
if arg == "--" {
|
||||
passThroughArgs = true
|
||||
continue
|
||||
}
|
||||
// Attempt to split it into two components separated by an equals sign.
|
||||
let components = arg.componentsSeparatedByString("=")
|
||||
let optionName = components[0]
|
||||
if validOptions != nil && !validOptions!.contains(optionName) {
|
||||
print("Invalid option: \(arg)")
|
||||
return .None
|
||||
}
|
||||
var optionVal : String
|
||||
switch components.count {
|
||||
case 1: optionVal = ""
|
||||
case 2: optionVal = components[1]
|
||||
default:
|
||||
// If we do not have two components at this point, we can not have
|
||||
// an option switch. This is an invalid argument. Bail!
|
||||
print("Invalid option: \(arg)")
|
||||
return .None
|
||||
}
|
||||
optionalArgsMap[optionName] = optionVal
|
||||
}
|
||||
|
||||
return .Some(Arguments(progName, positionalArgs, optionalArgsMap))
|
||||
}
|
||||
366
benchmark/utils/DriverUtils.swift
Normal file
366
benchmark/utils/DriverUtils.swift
Normal file
@@ -0,0 +1,366 @@
|
||||
//===--- DriverUtils.swift ------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Darwin
|
||||
|
||||
struct BenchResults {
|
||||
var delim: String = ","
|
||||
var sampleCount: UInt64 = 0
|
||||
var min: UInt64 = 0
|
||||
var max: UInt64 = 0
|
||||
var mean: UInt64 = 0
|
||||
var sd: UInt64 = 0
|
||||
var median: UInt64 = 0
|
||||
init() {}
|
||||
init(delim: String, sampleCount: UInt64, min: UInt64, max: UInt64, mean: UInt64, sd: UInt64, median: UInt64) {
|
||||
self.delim = delim
|
||||
self.sampleCount = sampleCount
|
||||
self.min = min
|
||||
self.max = max
|
||||
self.mean = mean
|
||||
self.sd = sd
|
||||
self.median = median
|
||||
}
|
||||
}
|
||||
|
||||
extension BenchResults : CustomStringConvertible {
|
||||
var description: String {
|
||||
return "\(sampleCount)\(delim)\(min)\(delim)\(max)\(delim)\(mean)\(delim)\(sd)\(delim)\(median)"
|
||||
}
|
||||
}
|
||||
|
||||
struct Test {
|
||||
let name: String
|
||||
let index: Int
|
||||
let f: (Int)->()
|
||||
var run: Bool
|
||||
init(name: String, n: Int, f: (Int)->()) {
|
||||
self.name = name
|
||||
self.index = n
|
||||
self.f = f
|
||||
run = true
|
||||
}
|
||||
}
|
||||
|
||||
public var precommitTests: [String : (Int)->()] = [:]
|
||||
public var otherTests: [String : (Int)->()] = [:]
|
||||
|
||||
enum TestAction {
|
||||
case Run
|
||||
case ListTests
|
||||
case Fail(String)
|
||||
}
|
||||
|
||||
struct TestConfig {
|
||||
/// The delimiter to use when printing output.
|
||||
var delim: String = ","
|
||||
|
||||
/// The filters applied to our test names.
|
||||
var filters = [String]()
|
||||
|
||||
/// The scalar multiple of the amount of times a test should be run. This
|
||||
/// enables one to cause tests to run for N iterations longer than they
|
||||
/// normally would. This is useful when one wishes for a test to run for a
|
||||
/// longer amount of time to perform performance analysis on the test in
|
||||
/// instruments.
|
||||
var iterationScale: Int = 1
|
||||
|
||||
/// If we are asked to have a fixed number of iterations, the number of fixed
|
||||
/// iterations.
|
||||
var fixedNumIters: UInt = 0
|
||||
|
||||
/// The number of samples we should take of each test.
|
||||
var numSamples: Int = 1
|
||||
|
||||
/// Is verbose output enabled?
|
||||
var verbose: Bool = false
|
||||
|
||||
/// Should we only run the "pre-commit" tests?
|
||||
var onlyPrecommit: Bool = true
|
||||
|
||||
/// After we run the tests, should the harness sleep to allow for utilities
|
||||
/// like leaks that require a PID to run on the test harness.
|
||||
var afterRunSleep: Int? = .None
|
||||
|
||||
/// The list of tests to run.
|
||||
var tests = [Test]()
|
||||
|
||||
mutating func processArguments() -> TestAction {
|
||||
let validOptions=["--iter-scale", "--num-samples", "--num-iters",
|
||||
"--verbose", "--delim", "--run-all", "--list", "--sleep"]
|
||||
let maybeBenchArgs: Arguments? = parseArgs(.Some(validOptions))
|
||||
if maybeBenchArgs == nil {
|
||||
return .Fail("Failed to parse arguments")
|
||||
}
|
||||
let benchArgs = maybeBenchArgs!
|
||||
|
||||
if let _ = benchArgs.optionalArgsMap["--list"] {
|
||||
return .ListTests
|
||||
}
|
||||
|
||||
if let x = benchArgs.optionalArgsMap["--iter-scale"] {
|
||||
if x.isEmpty { return .Fail("--iter-scale requires a value") }
|
||||
iterationScale = Int(x)!
|
||||
}
|
||||
|
||||
if let x = benchArgs.optionalArgsMap["--num-iters"] {
|
||||
if x.isEmpty { return .Fail("--num-iters requires a value") }
|
||||
fixedNumIters = numericCast(Int(x)!)
|
||||
}
|
||||
|
||||
if let x = benchArgs.optionalArgsMap["--num-samples"] {
|
||||
if x.isEmpty { return .Fail("--num-samples requires a value") }
|
||||
numSamples = Int(x)!
|
||||
}
|
||||
|
||||
if let _ = benchArgs.optionalArgsMap["--verbose"] {
|
||||
verbose = true
|
||||
print("Verbose")
|
||||
}
|
||||
|
||||
if let x = benchArgs.optionalArgsMap["--delim"] {
|
||||
if x.isEmpty { return .Fail("--delim requires a value") }
|
||||
delim = x
|
||||
}
|
||||
|
||||
if let _ = benchArgs.optionalArgsMap["--run-all"] {
|
||||
onlyPrecommit = false
|
||||
}
|
||||
|
||||
if let x = benchArgs.optionalArgsMap["--sleep"] {
|
||||
if x.isEmpty {
|
||||
return .Fail("--sleep requires a non-empty integer value")
|
||||
}
|
||||
let v: Int? = Int(x)
|
||||
if v == nil {
|
||||
return .Fail("--sleep requires a non-empty integer value")
|
||||
}
|
||||
afterRunSleep = v!
|
||||
}
|
||||
|
||||
filters = benchArgs.positionalArgs
|
||||
|
||||
return .Run
|
||||
}
|
||||
|
||||
mutating func findTestsToRun() {
|
||||
var i = 1
|
||||
for benchName in precommitTests.keys.sort() {
|
||||
tests.append(Test(name: benchName, n: i, f: precommitTests[benchName]!))
|
||||
i += 1
|
||||
}
|
||||
for benchName in otherTests.keys.sort() {
|
||||
tests.append(Test(name: benchName, n: i, f: otherTests[benchName]!))
|
||||
i += 1
|
||||
}
|
||||
for i in 0..<tests.count {
|
||||
if onlyPrecommit && precommitTests[tests[i].name] == nil {
|
||||
tests[i].run = false
|
||||
}
|
||||
if !filters.isEmpty &&
|
||||
!filters.contains(String(tests[i].index)) &&
|
||||
!filters.contains(tests[i].name) {
|
||||
tests[i].run = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func internalMeanSD(inputs: [UInt64]) -> (UInt64, UInt64) {
|
||||
// If we are empty, return 0, 0.
|
||||
if inputs.isEmpty {
|
||||
return (0, 0)
|
||||
}
|
||||
|
||||
// If we have one element, return elt, 0.
|
||||
if inputs.count == 1 {
|
||||
return (inputs[0], 0)
|
||||
}
|
||||
|
||||
// Ok, we have 2 elements.
|
||||
|
||||
var sum1: UInt64 = 0
|
||||
var sum2: UInt64 = 0
|
||||
|
||||
for i in inputs {
|
||||
sum1 += i
|
||||
}
|
||||
|
||||
let mean: UInt64 = sum1 / UInt64(inputs.count)
|
||||
|
||||
for i in inputs {
|
||||
sum2 = sum2 &+ UInt64((Int64(i) &- Int64(mean))&*(Int64(i) &- Int64(mean)))
|
||||
}
|
||||
|
||||
return (mean, UInt64(sqrt(Double(sum2)/(Double(inputs.count) - 1))))
|
||||
}
|
||||
|
||||
func internalMedian(inputs: [UInt64]) -> UInt64 {
|
||||
return inputs.sort()[inputs.count / 2]
|
||||
}
|
||||
|
||||
#if SWIFT_RUNTIME_ENABLE_LEAK_CHECKER
|
||||
|
||||
@_silgen_name("swift_leaks_startTrackingObjects")
|
||||
func startTrackingObjects(_: UnsafeMutablePointer<Void>) -> ()
|
||||
@_silgen_name("swift_leaks_stopTrackingObjects")
|
||||
func stopTrackingObjects(_: UnsafeMutablePointer<Void>) -> Int
|
||||
|
||||
#endif
|
||||
|
||||
class SampleRunner {
|
||||
var info = mach_timebase_info_data_t(numer: 0, denom: 0)
|
||||
init() {
|
||||
mach_timebase_info(&info)
|
||||
}
|
||||
func run(name: String, fn: (Int) -> Void, num_iters: UInt) -> UInt64 {
|
||||
// Start the timer.
|
||||
#if SWIFT_RUNTIME_ENABLE_LEAK_CHECKER
|
||||
var str = name
|
||||
startTrackingObjects(UnsafeMutablePointer<Void>(str._core.startASCII))
|
||||
#endif
|
||||
let start_ticks = mach_absolute_time()
|
||||
fn(Int(num_iters))
|
||||
// Stop the timer.
|
||||
let end_ticks = mach_absolute_time()
|
||||
#if SWIFT_RUNTIME_ENABLE_LEAK_CHECKER
|
||||
stopTrackingObjects(UnsafeMutablePointer<Void>(str._core.startASCII))
|
||||
#endif
|
||||
|
||||
// Compute the spent time and the scaling factor.
|
||||
let elapsed_ticks = end_ticks - start_ticks
|
||||
return elapsed_ticks * UInt64(info.numer) / UInt64(info.denom)
|
||||
}
|
||||
}
|
||||
|
||||
/// Invoke the benchmark entry point and return the run time in miliseconds.
|
||||
func runBench(name: String, _ fn: (Int) -> Void, _ c: TestConfig) -> BenchResults {
|
||||
|
||||
var samples = [UInt64](count: c.numSamples, repeatedValue: 0)
|
||||
|
||||
if c.verbose {
|
||||
print("Running \(name) for \(c.numSamples) samples.")
|
||||
}
|
||||
|
||||
let sampler = SampleRunner()
|
||||
for s in 0..<c.numSamples {
|
||||
let time_per_sample: UInt64 = 1_000_000_000 * UInt64(c.iterationScale)
|
||||
|
||||
var scale : UInt
|
||||
var elapsed_time : UInt64 = 0
|
||||
if c.fixedNumIters == 0 {
|
||||
elapsed_time = sampler.run(name, fn: fn, num_iters: 1)
|
||||
scale = UInt(time_per_sample / elapsed_time)
|
||||
} else {
|
||||
// Compute the scaling factor if a fixed c.fixedNumIters is not specified.
|
||||
scale = c.fixedNumIters
|
||||
}
|
||||
|
||||
// Rerun the test with the computed scale factor.
|
||||
if scale > 1 {
|
||||
if c.verbose {
|
||||
print(" Measuring with scale \(scale).")
|
||||
}
|
||||
elapsed_time = sampler.run(name, fn: fn, num_iters: scale)
|
||||
} else {
|
||||
scale = 1
|
||||
}
|
||||
// save result in microseconds or k-ticks
|
||||
samples[s] = elapsed_time / UInt64(scale) / 1000
|
||||
if c.verbose {
|
||||
print(" Sample \(s),\(samples[s])")
|
||||
}
|
||||
}
|
||||
|
||||
let (mean, sd) = internalMeanSD(samples)
|
||||
|
||||
// Return our benchmark results.
|
||||
return BenchResults(delim: c.delim, sampleCount: UInt64(samples.count),
|
||||
min: samples.minElement()!, max: samples.maxElement()!,
|
||||
mean: mean, sd: sd, median: internalMedian(samples))
|
||||
}
|
||||
|
||||
func printRunInfo(c: TestConfig) {
|
||||
if c.verbose {
|
||||
print("--- CONFIG ---")
|
||||
print("NumSamples: \(c.numSamples)")
|
||||
print("Verbose: \(c.verbose)")
|
||||
print("IterScale: \(c.iterationScale)")
|
||||
if c.fixedNumIters != 0 {
|
||||
print("FixedIters: \(c.fixedNumIters)")
|
||||
}
|
||||
print("Tests Filter: \(c.filters)")
|
||||
print("Tests to run: ", terminator: "")
|
||||
for t in c.tests {
|
||||
if t.run {
|
||||
print("\(t.name), ", terminator: "")
|
||||
}
|
||||
}
|
||||
print("")
|
||||
print("")
|
||||
print("--- DATA ---")
|
||||
}
|
||||
}
|
||||
|
||||
func runBenchmarks(c: TestConfig) {
|
||||
let units = "us"
|
||||
print("#\(c.delim)TEST\(c.delim)SAMPLES\(c.delim)MIN(\(units))\(c.delim)MAX(\(units))\(c.delim)MEAN(\(units))\(c.delim)SD(\(units))\(c.delim)MEDIAN(\(units))")
|
||||
var SumBenchResults = BenchResults()
|
||||
SumBenchResults.sampleCount = 0
|
||||
|
||||
for t in c.tests {
|
||||
if !t.run {
|
||||
continue
|
||||
}
|
||||
let BenchIndex = t.index
|
||||
let BenchName = t.name
|
||||
let BenchFunc = t.f
|
||||
let results = runBench(BenchName, BenchFunc, c)
|
||||
print("\(BenchIndex)\(c.delim)\(BenchName)\(c.delim)\(results.description)")
|
||||
fflush(stdout)
|
||||
|
||||
SumBenchResults.min += results.min
|
||||
SumBenchResults.max += results.max
|
||||
SumBenchResults.mean += results.mean
|
||||
SumBenchResults.sampleCount += 1
|
||||
// Don't accumulate SD and Median, as simple sum isn't valid for them.
|
||||
// TODO: Compute SD and Median for total results as well.
|
||||
// SumBenchResults.sd += results.sd
|
||||
// SumBenchResults.median += results.median
|
||||
}
|
||||
|
||||
print("")
|
||||
print("Totals\(c.delim)\(SumBenchResults.description)")
|
||||
}
|
||||
|
||||
public func main() {
|
||||
var config = TestConfig()
|
||||
|
||||
switch (config.processArguments()) {
|
||||
case let .Fail(msg):
|
||||
// We do this since we need an autoclosure...
|
||||
fatalError("\(msg)")
|
||||
case .ListTests:
|
||||
config.findTestsToRun()
|
||||
print("Enabled Tests:")
|
||||
for t in config.tests {
|
||||
print(" \(t.name)")
|
||||
}
|
||||
case .Run:
|
||||
config.findTestsToRun()
|
||||
printRunInfo(config)
|
||||
runBenchmarks(config)
|
||||
if let x = config.afterRunSleep {
|
||||
sleep(UInt32(x))
|
||||
}
|
||||
}
|
||||
}
|
||||
65
benchmark/utils/TestsUtils.swift
Normal file
65
benchmark/utils/TestsUtils.swift
Normal file
@@ -0,0 +1,65 @@
|
||||
//===--- TestsUtils.swift -------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
import Darwin
|
||||
|
||||
// Linear function shift register.
|
||||
//
|
||||
// This is just to drive benchmarks. I don't make any claim about its
|
||||
// strength. According to Wikipedia, it has the maximal period for a
|
||||
// 32-bit register.
|
||||
struct LFSR {
|
||||
// Set the register to some seed that I pulled out of a hat.
|
||||
var lfsr : UInt32 = 0xb78978e7
|
||||
|
||||
mutating func shift() {
|
||||
lfsr = (lfsr >> 1) ^ (UInt32(bitPattern: -Int32((lfsr & 1))) & 0xD0000001)
|
||||
}
|
||||
mutating func randInt() -> Int64 {
|
||||
var result : UInt32 = 0
|
||||
for _ in 0..<32 {
|
||||
result = (result << 1) | (lfsr & 1)
|
||||
shift()
|
||||
}
|
||||
return Int64(bitPattern: UInt64(result))
|
||||
}
|
||||
}
|
||||
|
||||
var lfsrRandomGenerator = LFSR()
|
||||
|
||||
// Start the generator from the beginning
|
||||
public func SRand() {
|
||||
lfsrRandomGenerator = LFSR()
|
||||
}
|
||||
|
||||
public func Random() -> Int64 {
|
||||
return lfsrRandomGenerator.randInt()
|
||||
}
|
||||
|
||||
public func CheckResults(res: Bool, _ message: String = "") {
|
||||
if res {
|
||||
return
|
||||
}
|
||||
print(message)
|
||||
abort()
|
||||
}
|
||||
|
||||
public func False() -> Bool { return false }
|
||||
|
||||
/// This is a dummy protocol to test the speed of our protocol dispatch.
|
||||
public protocol SomeProtocol { func getValue() -> Int }
|
||||
struct MyStruct : SomeProtocol {
|
||||
init() {}
|
||||
func getValue() -> Int { return 1 }
|
||||
}
|
||||
public func someProtocolFactory() -> SomeProtocol { return MyStruct() }
|
||||
|
||||
108
benchmark/utils/convertToJSON.py
Normal file
108
benchmark/utils/convertToJSON.py
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# ===--- convertToJSON.py -------------------------------------------------===//
|
||||
#
|
||||
# This source file is part of the Swift.org open source project
|
||||
#
|
||||
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
# Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
#
|
||||
# See http://swift.org/LICENSE.txt for license information
|
||||
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
#
|
||||
# ===----------------------------------------------------------------------===//
|
||||
|
||||
# This script converts results from pre-commit benchmark tests to JSON.
|
||||
# Usage: PrecommitBench_O | convertToJSON.py
|
||||
#
|
||||
# Input example:
|
||||
# #,TEST,SAMPLES,MIN(ms),MAX(ms),MEAN(ms),SD(ms),MEDIAN(ms)
|
||||
# 1,2Sum,1,1318,1318,1318,0,1318
|
||||
# 2,Ackermann,1,805,805,805,0,805
|
||||
#
|
||||
# Totals,2,2123,2123,2123,0,0
|
||||
#
|
||||
# Output for this input:
|
||||
# {
|
||||
# "Machine": {},
|
||||
# "Run": {},
|
||||
# "Tests": [
|
||||
# {
|
||||
# "Data": [
|
||||
# 1318
|
||||
# ],
|
||||
# "Info": {},
|
||||
# "Name": [
|
||||
# "2Sum"
|
||||
# ]
|
||||
# },
|
||||
# {
|
||||
# "Data": [
|
||||
# 805
|
||||
# ],
|
||||
# "Info": {},
|
||||
# "Name": [
|
||||
# "Ackermann"
|
||||
# ]
|
||||
# },
|
||||
# {
|
||||
# "Data": [
|
||||
# 2123
|
||||
# ],
|
||||
# "Info": {},
|
||||
# "Name": [
|
||||
# "Totals"
|
||||
# ]
|
||||
# }
|
||||
# ]
|
||||
# }
|
||||
|
||||
import sys
|
||||
import json
|
||||
import re
|
||||
# Parse lines like this
|
||||
# #,TEST,SAMPLES,MIN(ms),MAX(ms),MEAN(ms),SD(ms),MEDIAN(ms)
|
||||
SCORERE=re.compile(r"(\d+),[ \t]*(\w+),[ \t]*([\d.]+),[ \t]*([\d.]+)")
|
||||
|
||||
# The Totals line would be parsed like this.
|
||||
TOTALRE=re.compile(r"()(Totals),[ \t]*([\d.]+),[ \t]*([\d.]+)")
|
||||
KEYGROUP=2
|
||||
VALGROUP=4
|
||||
|
||||
def getScores(fname):
|
||||
scores = {}
|
||||
runs = 0
|
||||
f = open(fname)
|
||||
try:
|
||||
for line in f:
|
||||
if VERBOSE: print "Parsing", line,
|
||||
m = SCORERE.match(line)
|
||||
if not m:
|
||||
continue
|
||||
|
||||
if not m.group(KEYGROUP) in scores:
|
||||
scores[m.group(KEYGROUP)] = []
|
||||
scores[m.group(KEYGROUP)].append(parseFloat(m.group(VALGROUP)))
|
||||
if len(scores[m.group(KEYGROUP)]) > runs:
|
||||
runs = len(scores[m.group(KEYGROUP)])
|
||||
finally:
|
||||
f.close()
|
||||
return scores, runs
|
||||
|
||||
if __name__ == "__main__":
|
||||
data = {}
|
||||
data['Tests'] = []
|
||||
data['Machine'] = {}
|
||||
data['Run'] = {}
|
||||
for line in sys.stdin:
|
||||
m = SCORERE.match(line)
|
||||
if not m:
|
||||
m = TOTALRE.match(line)
|
||||
if not m:
|
||||
continue
|
||||
test = {}
|
||||
test['Data'] = [int(m.group(VALGROUP))]
|
||||
test['Info'] = {}
|
||||
test['Name'] = [m.group(KEYGROUP)]
|
||||
data['Tests'].append(test)
|
||||
print(json.dumps(data, sort_keys=True, indent=4))
|
||||
176
benchmark/utils/main.swift
Normal file
176
benchmark/utils/main.swift
Normal file
@@ -0,0 +1,176 @@
|
||||
//===--- main.swift -------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See http://swift.org/LICENSE.txt for license information
|
||||
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// WARNING: This file is automatically generated from templates and should not
|
||||
// be directly modified. Instead, make changes to
|
||||
// scripts/generate_harness/main.swift_template and run
|
||||
// scripts/generate_harness/generate_harness.py to regenerate this file.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is just a driver for performance overview tests.
|
||||
import TestsUtils
|
||||
import DriverUtils
|
||||
import Ackermann
|
||||
import AngryPhonebook
|
||||
import Array2D
|
||||
import ArrayAppend
|
||||
import ArrayInClass
|
||||
import ArrayLiteral
|
||||
import ArrayOfGenericPOD
|
||||
import ArrayOfGenericRef
|
||||
import ArrayOfPOD
|
||||
import ArrayOfRef
|
||||
import ArraySubscript
|
||||
import BitCount
|
||||
import ByteSwap
|
||||
import Calculator
|
||||
import CaptureProp
|
||||
import Chars
|
||||
import ClassArrayGetter
|
||||
import DeadArray
|
||||
import DictTest
|
||||
import DictTest2
|
||||
import DictTest3
|
||||
import DictionaryBridge
|
||||
import DictionaryLiteral
|
||||
import DictionaryRemove
|
||||
import DictionarySwap
|
||||
import ErrorHandling
|
||||
import Fibonacci
|
||||
import GlobalClass
|
||||
import Hanoi
|
||||
import Hash
|
||||
import Histogram
|
||||
import Join
|
||||
import LinkedList
|
||||
import MapReduce
|
||||
import Memset
|
||||
import MonteCarloE
|
||||
import MonteCarloPi
|
||||
import NSDictionaryCastToSwift
|
||||
import NSError
|
||||
import NSStringConversion
|
||||
import NopDeinit
|
||||
import ObjectAllocation
|
||||
import OpenClose
|
||||
import Phonebook
|
||||
import PolymorphicCalls
|
||||
import PopFront
|
||||
import PopFrontGeneric
|
||||
import Prims
|
||||
import ProtocolDispatch
|
||||
import RC4
|
||||
import RGBHistogram
|
||||
import RangeAssignment
|
||||
import RecursiveOwnedParameter
|
||||
import SetTests
|
||||
import SevenBoom
|
||||
import Sim2DArray
|
||||
import SortLettersInPlace
|
||||
import SortStrings
|
||||
import StrComplexWalk
|
||||
import StrToInt
|
||||
import StringBuilder
|
||||
import StringInterpolation
|
||||
import StringTests
|
||||
import StringWalk
|
||||
import SuperChars
|
||||
import TwoSum
|
||||
import Walsh
|
||||
import XorLoop
|
||||
|
||||
precommitTests = [
|
||||
"AngryPhonebook": run_AngryPhonebook,
|
||||
"Array2D": run_Array2D,
|
||||
"ArrayAppend": run_ArrayAppend,
|
||||
"ArrayAppendReserved": run_ArrayAppendReserved,
|
||||
"ArrayInClass": run_ArrayInClass,
|
||||
"ArrayLiteral": run_ArrayLiteral,
|
||||
"ArrayOfGenericPOD": run_ArrayOfGenericPOD,
|
||||
"ArrayOfGenericRef": run_ArrayOfGenericRef,
|
||||
"ArrayOfPOD": run_ArrayOfPOD,
|
||||
"ArrayOfRef": run_ArrayOfRef,
|
||||
"ArraySubscript": run_ArraySubscript,
|
||||
"ArrayValueProp": run_ArrayValueProp,
|
||||
"ArrayValueProp2": run_ArrayValueProp2,
|
||||
"ArrayValueProp3": run_ArrayValueProp3,
|
||||
"ArrayValueProp4": run_ArrayValueProp4,
|
||||
"BitCount": run_BitCount,
|
||||
"ByteSwap": run_ByteSwap,
|
||||
"Calculator": run_Calculator,
|
||||
"CaptureProp": run_CaptureProp,
|
||||
"Chars": run_Chars,
|
||||
"ClassArrayGetter": run_ClassArrayGetter,
|
||||
"DeadArray": run_DeadArray,
|
||||
"Dictionary": run_Dictionary,
|
||||
"Dictionary2": run_Dictionary2,
|
||||
"Dictionary3": run_Dictionary3,
|
||||
"DictionaryBridge": run_DictionaryBridge,
|
||||
"DictionaryLiteral": run_DictionaryLiteral,
|
||||
"DictionaryRemove": run_DictionaryRemove,
|
||||
"DictionarySwap": run_DictionarySwap,
|
||||
"ErrorHandling": run_ErrorHandling,
|
||||
"GlobalClass": run_GlobalClass,
|
||||
"Hanoi": run_Hanoi,
|
||||
"HashTest": run_HashTest,
|
||||
"Histogram": run_Histogram,
|
||||
"Join": run_Join,
|
||||
"LinkedList": run_LinkedList,
|
||||
"MapReduce": run_MapReduce,
|
||||
"Memset": run_Memset,
|
||||
"MonteCarloE": run_MonteCarloE,
|
||||
"MonteCarloPi": run_MonteCarloPi,
|
||||
"NSDictionaryCastToSwift": run_NSDictionaryCastToSwift,
|
||||
"NSError": run_NSError,
|
||||
"NSStringConversion": run_NSStringConversion,
|
||||
"NopDeinit": run_NopDeinit,
|
||||
"ObjectAllocation": run_ObjectAllocation,
|
||||
"OpenClose": run_OpenClose,
|
||||
"Phonebook": run_Phonebook,
|
||||
"PolymorphicCalls": run_PolymorphicCalls,
|
||||
"PopFrontArray": run_PopFrontArray,
|
||||
"PopFrontArrayGeneric": run_PopFrontArrayGeneric,
|
||||
"PopFrontUnsafePointer": run_PopFrontUnsafePointer,
|
||||
"Prims": run_Prims,
|
||||
"ProtocolDispatch": run_ProtocolDispatch,
|
||||
"RC4": run_RC4,
|
||||
"RGBHistogram": run_RGBHistogram,
|
||||
"RangeAssignment": run_RangeAssignment,
|
||||
"RecursiveOwnedParameter": run_RecursiveOwnedParameter,
|
||||
"SetExclusiveOr": run_SetExclusiveOr,
|
||||
"SetIntersect": run_SetIntersect,
|
||||
"SetIsSubsetOf": run_SetIsSubsetOf,
|
||||
"SetUnion": run_SetUnion,
|
||||
"SevenBoom": run_SevenBoom,
|
||||
"Sim2DArray": run_Sim2DArray,
|
||||
"SortLettersInPlace": run_SortLettersInPlace,
|
||||
"SortStrings": run_SortStrings,
|
||||
"StrComplexWalk": run_StrComplexWalk,
|
||||
"StrToInt": run_StrToInt,
|
||||
"StringBuilder": run_StringBuilder,
|
||||
"StringInterpolation": run_StringInterpolation,
|
||||
"StringWalk": run_StringWalk,
|
||||
"StringWithCString": run_StringWithCString,
|
||||
"SuperChars": run_SuperChars,
|
||||
"TwoSum": run_TwoSum,
|
||||
"Walsh": run_Walsh,
|
||||
"XorLoop": run_XorLoop,
|
||||
]
|
||||
|
||||
otherTests = [
|
||||
"Ackermann": run_Ackermann,
|
||||
"Fibonacci": run_Fibonacci,
|
||||
]
|
||||
|
||||
|
||||
main()
|
||||
@@ -623,7 +623,7 @@ darwin-toolchain-alias=%(darwin_toolchain_alias)s
|
||||
|
||||
[preset: LLDB_Nested]
|
||||
dash-dash
|
||||
build-swift-perf-testsuite=0
|
||||
skip-build-benchmarks=1
|
||||
install-destdir=%(swift_install_destdir)s
|
||||
|
||||
[preset: LLDB_Swift_DebugAssert]
|
||||
|
||||
@@ -485,6 +485,9 @@ build the Debug variant of the Swift standard library and SDK overlay""",
|
||||
run_tests_group.add_argument("-T", "--validation-test",
|
||||
help="run the validation test suite (implies --test)",
|
||||
action="store_true")
|
||||
run_tests_group.add_argument("-B", "--benchmark",
|
||||
help="run the Swift Benchmark Suite after building",
|
||||
action="store_true")
|
||||
|
||||
parser.add_argument("-o", "--test-optimized",
|
||||
help="run the test suite in optimized mode too (implies --test)",
|
||||
@@ -496,6 +499,10 @@ build the Debug variant of the Swift standard library and SDK overlay""",
|
||||
help="generate build directory only without building",
|
||||
action="store_true")
|
||||
|
||||
run_build_group.add_argument("--skip-build-benchmarks",
|
||||
help="skip building Swift Benchmark Suite",
|
||||
action="store_true")
|
||||
|
||||
parser.add_argument("-i", "--ios",
|
||||
help="""
|
||||
also build for iOS, but disallow tests that require an iOS device""",
|
||||
@@ -654,6 +661,11 @@ the number of parallel build jobs to use""",
|
||||
"--skip-test-validation"
|
||||
]
|
||||
|
||||
if not args.benchmark:
|
||||
build_script_impl_inferred_args += [
|
||||
"--skip-test-benchmarks"
|
||||
]
|
||||
|
||||
if not args.test_optimized:
|
||||
build_script_impl_inferred_args += [
|
||||
"--skip-test-optimized"
|
||||
@@ -707,6 +719,11 @@ the number of parallel build jobs to use""",
|
||||
"--skip-build-libdispatch"
|
||||
]
|
||||
|
||||
if args.skip_build_benchmarks:
|
||||
build_script_impl_inferred_args += [
|
||||
"--skip-build-benchmarks"
|
||||
]
|
||||
|
||||
if args.skip_build:
|
||||
build_script_impl_inferred_args += [
|
||||
"--skip-build"
|
||||
|
||||
@@ -120,6 +120,7 @@ KNOWN_SETTINGS=(
|
||||
skip-build-xctest "" "set to skip building xctest"
|
||||
skip-build-foundation "" "set to skip building foundation"
|
||||
skip-build-libdispatch "" "set to skip building libdispatch"
|
||||
skip-build-benchmarks "" "set to skip building Swift Benchmark Suite"
|
||||
skip-test-cmark "" "set to skip testing CommonMark"
|
||||
skip-test-lldb "" "set to skip testing lldb"
|
||||
skip-test-swift "" "set to skip testing Swift"
|
||||
@@ -139,6 +140,7 @@ KNOWN_SETTINGS=(
|
||||
skip-test-watchos-simulator "" "set to skip testing Swift stdlibs for Apple watchOS simulators (i.e. test devices only)"
|
||||
skip-test-watchos-host "" "set to skip testing the host parts of the watchOS toolchain"
|
||||
skip-test-validation "" "set to skip validation test suite"
|
||||
skip-test-benchmarks "" "set to skip running Swift Benchmark Suite"
|
||||
skip-test-optimized "" "set to skip testing the test suite in optimized mode"
|
||||
stress-test-sourcekit "" "set to run the stress-SourceKit target"
|
||||
xcode-ide-only "" "set to configure Xcode project for IDE use only, not building"
|
||||
@@ -151,7 +153,6 @@ KNOWN_SETTINGS=(
|
||||
build-swift-sdk-overlay "1" "set to 1 to build the Swift SDK overlay"
|
||||
build-swift-static-stdlib "0" "set to 1 to build static versions of the Swift standard library and SDK overlay"
|
||||
build-swift-examples "1" "set to 1 to build examples"
|
||||
build-swift-perf-testsuite "0" "set to 1 to build perf test suite"
|
||||
build-serialized-stdlib-unittest "0" "set to 1 to build the StdlibUnittest module with -sil-serialize-all"
|
||||
source-tree-includes-tests "1" "set to 0 to allow the build to proceed when 'test' directory is missing (required for B&I builds)"
|
||||
native-llvm-tools-path "" "directory that contains LLVM tools that are executable on the build machine"
|
||||
@@ -557,6 +558,7 @@ if [[ "${SKIP_BUILD}" ]]; then
|
||||
SKIP_BUILD_XCTEST=1
|
||||
SKIP_BUILD_FOUNDATION=1
|
||||
SKIP_BUILD_LIBDISPATCH=1
|
||||
SKIP_BUILD_BENCHMARKS=1
|
||||
fi
|
||||
|
||||
if [[ "${SKIP_IOS}" ]] ; then
|
||||
@@ -729,7 +731,7 @@ function not() {
|
||||
|
||||
function true_false() {
|
||||
case "$1" in
|
||||
false | FALSE | 0)
|
||||
false | FALSE | 0 | "")
|
||||
echo "FALSE"
|
||||
;;
|
||||
true | TRUE | 1)
|
||||
@@ -932,13 +934,15 @@ if [[ ! "${SKIP_BUILD_LIBDISPATCH}" ]] ; then
|
||||
fi
|
||||
|
||||
SWIFT_STDLIB_TARGETS=()
|
||||
SWIFT_PERFTEST_TARGETS=()
|
||||
SWIFT_BENCHMARK_TARGETS=()
|
||||
SWIFT_RUN_BENCHMARK_TARGETS=()
|
||||
SWIFT_TEST_TARGETS=()
|
||||
for deployment_target in "${STDLIB_DEPLOYMENT_TARGETS[@]}"; do
|
||||
build_for_this_target=1
|
||||
perftest_this_target=
|
||||
test_this_target=1
|
||||
test_host_only=
|
||||
build_benchmark_this_target=
|
||||
test_benchmark_this_target=
|
||||
case ${deployment_target} in
|
||||
linux-*)
|
||||
build_for_this_target=1
|
||||
@@ -950,17 +954,18 @@ for deployment_target in "${STDLIB_DEPLOYMENT_TARGETS[@]}"; do
|
||||
;;
|
||||
macosx-*)
|
||||
build_for_this_target=$(not ${SKIP_BUILD_OSX})
|
||||
perftest_this_target=$(not ${SKIP_BUILD_OSX})
|
||||
test_this_target=$(not ${SKIP_TEST_OSX})
|
||||
build_benchmark_this_target=$(not ${SKIP_BUILD_OSX})
|
||||
test_benchmark_this_target=$(not ${SKIP_BUILD_OSX})
|
||||
;;
|
||||
iphoneos-*)
|
||||
build_for_this_target=$(not ${SKIP_BUILD_IOS_DEVICE})
|
||||
perftest_this_target=$(not ${SKIP_BUILD_IOS_DEVICE})
|
||||
if [[ ! "${SKIP_TEST_IOS_HOST}" ]] ; then
|
||||
test_host_only=1
|
||||
else
|
||||
test_this_target=
|
||||
fi
|
||||
build_benchmark_this_target=$(not ${SKIP_BUILD_IOS_DEVICE})
|
||||
;;
|
||||
iphonesimulator-*)
|
||||
build_for_this_target=$(not ${SKIP_BUILD_IOS_SIMULATOR})
|
||||
@@ -968,12 +973,12 @@ for deployment_target in "${STDLIB_DEPLOYMENT_TARGETS[@]}"; do
|
||||
;;
|
||||
appletvos-*)
|
||||
build_for_this_target=$(not ${SKIP_BUILD_TVOS_DEVICE})
|
||||
perftest_this_target=$(not ${SKIP_BUILD_TVOS_DEVICE})
|
||||
if [[ ! "${SKIP_TEST_TVOS_HOST}" ]] ; then
|
||||
test_host_only=1
|
||||
else
|
||||
test_this_target=
|
||||
fi
|
||||
build_benchmark_this_target=$(not ${SKIP_BUILD_TVOS_DEVICE})
|
||||
;;
|
||||
appletvsimulator-*)
|
||||
build_for_this_target=$(not ${SKIP_BUILD_TVOS_SIMULATOR})
|
||||
@@ -981,12 +986,12 @@ for deployment_target in "${STDLIB_DEPLOYMENT_TARGETS[@]}"; do
|
||||
;;
|
||||
watchos-*)
|
||||
build_for_this_target=$(not ${SKIP_BUILD_WATCHOS_DEVICE})
|
||||
perftest_this_target=$(not ${SKIP_BUILD_WATCHOS_DEVICE})
|
||||
if [[ ! "${SKIP_TEST_WATCHOS_HOST}" ]] ; then
|
||||
test_host_only=1
|
||||
else
|
||||
test_this_target=
|
||||
fi
|
||||
build_benchmark_this_target=$(not ${SKIP_BUILD_WATCHOS_DEVICE})
|
||||
;;
|
||||
watchsimulator-*)
|
||||
build_for_this_target=$(not ${SKIP_BUILD_WATCHOS_SIMULATOR})
|
||||
@@ -1011,9 +1016,13 @@ for deployment_target in "${STDLIB_DEPLOYMENT_TARGETS[@]}"; do
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [[ "${perftest_this_target}" ]] ; then
|
||||
SWIFT_PERFTEST_TARGETS=(
|
||||
"${SWIFT_PERFTEST_TARGETS[@]}" "swift-perftest-${deployment_target}")
|
||||
if [[ "${build_benchmark_this_target}" ]] ; then
|
||||
SWIFT_BENCHMARK_TARGETS=(
|
||||
"${SWIFT_BENCHMARK_TARGETS[@]}" "swift-benchmark-${deployment_target}")
|
||||
if [[ $(not ${SKIP_TEST_BENCHMARK}) ]] ; then
|
||||
SWIFT_RUN_BENCHMARK_TARGETS=(
|
||||
"${SWIFT_RUN_BENCHMARK_TARGETS[@]}" "check-swift-benchmark-${deployment_target}")
|
||||
fi
|
||||
fi
|
||||
if [[ "${test_this_target}" ]] ; then
|
||||
if [[ -n "${test_host_only}" ]] ; then
|
||||
@@ -1041,6 +1050,11 @@ echo "Building the standard library for: ${SWIFT_STDLIB_TARGETS[@]}"
|
||||
if [[ "${SWIFT_TEST_TARGETS[@]}" ]] && ! [[ "${SKIP_TEST_SWIFT}" ]]; then
|
||||
echo "Running Swift tests for: ${SWIFT_TEST_TARGETS[@]}"
|
||||
fi
|
||||
if ! [[ "${SKIP_TEST_BENCHMARKS}" ]] &&
|
||||
[[ "${SWIFT_RUN_BENCHMARK_TARGETS[@]}" ]] &&
|
||||
! [[ "${SKIP_TEST_BENCHMARK}" ]]; then
|
||||
echo "Running Swift benchmarks for: ${SWIFT_RUN_BENCHMARK_TARGETS[@]}"
|
||||
fi
|
||||
echo
|
||||
|
||||
# CMake options used for all targets, including LLVM/Clang
|
||||
@@ -1591,7 +1605,7 @@ for deployment_target in "${HOST_TARGET}" "${CROSS_TOOLS_DEPLOYMENT_TARGETS[@]}"
|
||||
-DLLVM_MAIN_SRC_DIR:PATH="${LLVM_SOURCE_DIR}"
|
||||
)
|
||||
else
|
||||
build_perf_testsuite_this_time=$(true_false "${BUILD_SWIFT_PERF_TESTSUITE}")
|
||||
build_perf_testsuite_this_time=$(true_false "$(not ${SKIP_BUILD_BENCHMARKS})")
|
||||
build_tests_this_time=${SOURCE_TREE_INCLUDES_TESTS}
|
||||
fi
|
||||
|
||||
@@ -1665,11 +1679,10 @@ for deployment_target in "${HOST_TARGET}" "${CROSS_TOOLS_DEPLOYMENT_TARGETS[@]}"
|
||||
-DSWIFT_EXEC:STRING="${native_swift_tools_path}/swiftc"
|
||||
)
|
||||
build_targets=("${build_targets[@]}"
|
||||
"${SWIFT_PERFTEST_TARGETS[@]}")
|
||||
"${SWIFT_BENCHMARK_TARGETS[@]}")
|
||||
fi
|
||||
skip_build=${SKIP_BUILD_SWIFT}
|
||||
;;
|
||||
|
||||
lldb)
|
||||
if [ ! -d "${LLDB_SOURCE_DIR}" ]; then
|
||||
echo "error: lldb not found in ${LLDB_SOURCE_DIR}"
|
||||
@@ -1946,17 +1959,27 @@ for deployment_target in "${STDLIB_DEPLOYMENT_TARGETS[@]}"; do
|
||||
continue # We don't test LLVM
|
||||
;;
|
||||
swift)
|
||||
if [[ "${SKIP_TEST_SWIFT}" ]]; then
|
||||
continue
|
||||
executable_target=
|
||||
results_targets=
|
||||
if ! [[ "${SKIP_TEST_SWIFT}" ]]; then
|
||||
executable_target=SwiftUnitTests
|
||||
results_targets=("${SWIFT_TEST_TARGETS[@]}")
|
||||
if [[ "${STRESS_TEST_SOURCEKIT}" ]]; then
|
||||
results_targets=(
|
||||
"${results_targets[@]}"
|
||||
stress-SourceKit
|
||||
)
|
||||
fi
|
||||
fi
|
||||
executable_target=SwiftUnitTests
|
||||
results_targets=("${SWIFT_TEST_TARGETS[@]}")
|
||||
if [[ "${STRESS_TEST_SOURCEKIT}" ]]; then
|
||||
if ! [[ "${SKIP_TEST_BENCHMARKS}" ]]; then
|
||||
results_targets=(
|
||||
"${results_targets[@]}"
|
||||
stress-SourceKit
|
||||
"${SWIFT_RUN_BENCHMARK_TARGETS[@]}"
|
||||
)
|
||||
fi
|
||||
if [[ -z "${results_targets[@]}" ]]; then
|
||||
continue
|
||||
fi
|
||||
;;
|
||||
lldb)
|
||||
if [[ "${SKIP_TEST_LLDB}" ]]; then
|
||||
@@ -2073,22 +2096,24 @@ for deployment_target in "${STDLIB_DEPLOYMENT_TARGETS[@]}"; do
|
||||
|
||||
echo "--- Running tests for ${product} ---"
|
||||
for target in "${results_targets[@]}"; do
|
||||
echo "--- ${target} ---"
|
||||
trap "tests_busted ${product} '(${target})'" ERR
|
||||
if [[ "${CMAKE_GENERATOR}" == Ninja ]] && !( "${build_cmd[@]}" --version 2>&1 | grep -i -q llbuild ); then
|
||||
# Ninja buffers command output to avoid scrambling the output
|
||||
# of parallel jobs, which is awesome... except that it
|
||||
# interferes with the progress meter when testing. Instead of
|
||||
# executing ninja directly, have it dump the commands it would
|
||||
# run, strip Ninja's progress prefix with sed, and tell the
|
||||
# shell to execute that.
|
||||
sh -c "set -x && $("${build_cmd[@]}" -n -v ${target} | sed -e 's/[^]]*] //')"
|
||||
else
|
||||
set -x
|
||||
"${build_cmd[@]}" ${BUILD_TARGET_FLAG} ${target}
|
||||
{ set +x; } 2>/dev/null
|
||||
if [[ "${target}" != "" ]]; then
|
||||
echo "--- ${target} ---"
|
||||
trap "tests_busted ${product} '(${target})'" ERR
|
||||
if [[ "${CMAKE_GENERATOR}" == Ninja ]] && !( "${build_cmd[@]}" --version 2>&1 | grep -i -q llbuild ); then
|
||||
# Ninja buffers command output to avoid scrambling the output
|
||||
# of parallel jobs, which is awesome... except that it
|
||||
# interferes with the progress meter when testing. Instead of
|
||||
# executing ninja directly, have it dump the commands it would
|
||||
# run, strip Ninja's progress prefix with sed, and tell the
|
||||
# shell to execute that.
|
||||
sh -c "set -x && $("${build_cmd[@]}" -n -v ${target} | sed -e 's/[^]]*] //')"
|
||||
else
|
||||
set -x
|
||||
"${build_cmd[@]}" ${BUILD_TARGET_FLAG} ${target}
|
||||
{ set +x; } 2>/dev/null
|
||||
fi
|
||||
echo "-- ${target} finished --"
|
||||
fi
|
||||
echo "-- ${target} finished --"
|
||||
done
|
||||
|
||||
trap - ERR
|
||||
|
||||
@@ -104,8 +104,6 @@ By default, updates your checkouts of Swift, SourceKit, LLDB, and SwiftPM.""")
|
||||
update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "clang"), branch)
|
||||
|
||||
update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "swift"), branch)
|
||||
update_working_copy(
|
||||
os.path.join(SWIFT_SOURCE_ROOT, "swift", "benchmark", "PerfTestSuite"), branch)
|
||||
update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "SourceKit"), branch)
|
||||
update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "cmark"), branch)
|
||||
update_working_copy(os.path.join(SWIFT_SOURCE_ROOT, "lldb"), branch)
|
||||
|
||||
Reference in New Issue
Block a user