Add Swift Benchmark Suite

This commit is contained in:
Luke Larson
2016-02-08 10:47:58 -08:00
parent 03c1ac4593
commit 0356ec8ec3
91 changed files with 8940 additions and 50 deletions

3
.gitignore vendored
View File

@@ -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

View File

@@ -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)

View File

@@ -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
View 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
}
```

View 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()

View 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())

View 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)

View 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)

View 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)

View 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])

View 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)

View 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)
)

View 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()

View 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

View 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]).")
}

View 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)
}
}
}
}

View 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
}
}
}
}

View 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)
}
}
}
}

View 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)
}

View 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)")
}

View 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()
}
}

View 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()
}
}

View 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()
}
}

View 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()
}
}

View 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.")
}

View 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.")
}
}

View 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.")
}
}

View 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")
}

View 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)
}
}

View 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))
}
}
}
}
}

View 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)
}
}

View 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")
}

View 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).")
}

View 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)")
}

View 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)")
}

View 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()
}
}

View 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()
}
}

View 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.")
}

View 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)
}

View 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 _ {
}
}
}

View 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)")
}

View 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)
}
}

View 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")
}
}

View 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.")
}
}

View 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);
}

View 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(" ")
}

View 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)")
}

View 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")
}

View 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.")
}

View 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)")
}

View 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)")
}

View 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")
}

View 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
}
}
}

View 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
}
}

View 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.")
}
}

View 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")
}

View 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")
}

View 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()
}
}

View 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)
}

View 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)
}

View 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)")
}
}
}

View 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.")
}
}

View 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()
}
}

View 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")
}
}

View 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
}
}
}

View 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).")
}

View 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)")
}

View 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)
}

View 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")
}

View 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)
}
}

View 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.")
}
}

File diff suppressed because it is too large Load Diff

View 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)")
}
}

View 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)")
}

View 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()
}
}

View 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)")
}
}

View 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 }
}
}

View 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)
}
}

View 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))
}
}
}
}
}

View 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!]).")
}
}
}

View 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)
}
}

View 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)")
}
}

View 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))
}

View 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))
}
}
}

View 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() }

View 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
View 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()

View File

@@ -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]

View File

@@ -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"

View File

@@ -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

View File

@@ -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)