Adding benchmarking infrastructure.

This commit is contained in:
Krunoslav Zaher 2015-09-27 02:25:41 +02:00
parent 2c5cc42d94
commit cee58007b1
5 changed files with 386 additions and 6 deletions

View File

@ -0,0 +1,76 @@
//
// main.swift
// Benchmark
//
// Created by Krunoslav Zaher on 9/26/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
import Foundation
let NumberOfIterations = 1000
func approxValuePerIteration(total: Int) -> UInt64 {
return UInt64(round(Double(total) / Double(NumberOfIterations)))
}
func approxValuePerIteration(total: UInt64) -> UInt64 {
return UInt64(round(Double(total) / Double(NumberOfIterations)))
}
func measureTime(@noescape work: () -> ()) -> UInt64 {
var timebaseInfo: mach_timebase_info = mach_timebase_info()
let res = mach_timebase_info(&timebaseInfo)
assert(res == 0)
let start = mach_absolute_time()
for _ in 0 ..< NumberOfIterations {
work()
}
let timeInNano = (mach_absolute_time() - start) * UInt64(timebaseInfo.numer) / UInt64(timebaseInfo.denom)
return approxValuePerIteration(timeInNano) / 1000
}
func measureMemoryUsage(@noescape work: () -> ()) -> (bytesAllocated: UInt64, allocations: UInt64) {
let (bytes, allocations) = getMemoryInfo()
for _ in 0 ..< NumberOfIterations {
work()
}
let (bytesAfter, allocationsAfter) = getMemoryInfo()
return (approxValuePerIteration(bytesAfter - bytes), approxValuePerIteration(allocationsAfter - allocations))
}
func compareTwoImplementations(@noescape first first: () -> (), @noescape second: () -> ()) {
// first warm up to keep it fair
first()
second()
let time1 = measureTime(first)
let time2 = measureTime(second)
registerMallocHooks()
let memory1 = measureMemoryUsage(first)
let memory2 = measureMemoryUsage(second)
// this is good enough
print(String(format: "#1 implementation %8d bytes %4d allocations %5d useconds", arguments: [
memory1.bytesAllocated,
memory1.allocations,
time1
]))
print(String(format: "#2 implementation %8d bytes %4d allocations %5d useconds", arguments: [
memory2.bytesAllocated,
memory2.allocations,
time2
]))
}
compareTwoImplementations(first: {
}, second: {
})

View File

@ -11,6 +11,9 @@ import XCTest
import RxSwift
class BagTest : RxTest {
override var accumulateStatistics: Bool {
return false
}
}
extension BagTest {

View File

@ -69,13 +69,29 @@ class RxTest: XCTestCase {
}
private var startResourceCount: Int32 = 0
var accumulateStatistics: Bool {
get {
return true
}
}
#if TRACE_RESOURCES
static var totalNumberOfAllocations: Int64 = 0
static var totalNumberOfAllocatedBytes: Int64 = 0
var startNumberOfAllocations: Int64 = 0
var startNumberOfAllocatedBytes: Int64 = 0
#endif
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
#if TRACE_RESOURCES
self.startResourceCount = resourceCount
registerMallocHooks()
(startNumberOfAllocatedBytes, startNumberOfAllocations) = getMemoryInfo()
#endif
}
@ -85,6 +101,15 @@ class RxTest: XCTestCase {
#if TRACE_RESOURCES
XCTAssertEqual(self.startResourceCount, resourceCount)
let (endNumberOfAllocatedBytes, endNumberOfAllocations) = getMemoryInfo()
let (newBytes, newAllocations) = (endNumberOfAllocatedBytes - startNumberOfAllocatedBytes, endNumberOfAllocations - startNumberOfAllocations)
if accumulateStatistics {
RxTest.totalNumberOfAllocations += newAllocations
RxTest.totalNumberOfAllocatedBytes += newBytes
}
print("allocatedBytes = \(newBytes), allocations = \(newAllocations) (totalBytes = \(RxTest.totalNumberOfAllocatedBytes), totalAllocations = \(RxTest.totalNumberOfAllocations))")
#endif
}

View File

@ -50,8 +50,12 @@
C85F4E441B7F70EA00A866C7 /* CompositeObserverTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C85F4E421B7F70EA00A866C7 /* CompositeObserverTest.swift */; };
C8633AE51B0A9FF300375D60 /* KVOObservableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8633AE41B0A9FF300375D60 /* KVOObservableTests.swift */; };
C8633AE61B0AA0ED00375D60 /* KVOObservableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8633AE41B0A9FF300375D60 /* KVOObservableTests.swift */; };
C868D0F01BB75EA1003D1474 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = C868D0EF1BB75EA1003D1474 /* main.swift */; };
C868D0F71BB75EAE003D1474 /* RxTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C811084C1AF50E2A001C13E4 /* RxTest.swift */; settings = {ASSET_TAGS = (); }; };
C868D0F91BB76A29003D1474 /* PerformanceTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = C868D0F81BB76A29003D1474 /* PerformanceTools.swift */; settings = {ASSET_TAGS = (); }; };
C868D0FA1BB76A29003D1474 /* PerformanceTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = C868D0F81BB76A29003D1474 /* PerformanceTools.swift */; settings = {ASSET_TAGS = (); }; };
C868D0FB1BB76A29003D1474 /* PerformanceTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = C868D0F81BB76A29003D1474 /* PerformanceTools.swift */; settings = {ASSET_TAGS = (); }; };
C88BB8911B07E64B0064D411 /* Observable+ConcurrencyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8B787F91AF55CDE00206D02 /* Observable+ConcurrencyTest.swift */; };
C88BB8921B07E64B0064D411 /* RxTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C811084C1AF50E2A001C13E4 /* RxTest.swift */; };
C88BB8941B07E64B0064D411 /* Observable+TimeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C811084A1AF50E2A001C13E4 /* Observable+TimeTest.swift */; };
C88BB8951B07E64B0064D411 /* TestObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C81108361AF50E2A001C13E4 /* TestObservable.swift */; };
C88BB8961B07E64B0064D411 /* Subscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = C811083D1AF50E2A001C13E4 /* Subscription.swift */; };
@ -105,6 +109,18 @@
C8FDC5F91B2B5B7E0065F8D9 /* ElementIndexPair.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8FDC5F71B2B5B7E0065F8D9 /* ElementIndexPair.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
C868D0EB1BB75EA1003D1474 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
5E5D10BA1B48355200432B25 /* UIControl+RxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIControl+RxTests.swift"; sourceTree = "<group>"; };
C69B64FF1BA88FAC00A7FA73 /* ObserverTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObserverTests.swift; sourceTree = "<group>"; };
@ -145,6 +161,9 @@
C84B8FC11B89D0D500C9CCCF /* BagTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BagTest.swift; sourceTree = "<group>"; };
C85F4E421B7F70EA00A866C7 /* CompositeObserverTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompositeObserverTest.swift; sourceTree = "<group>"; };
C8633AE41B0A9FF300375D60 /* KVOObservableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KVOObservableTests.swift; sourceTree = "<group>"; };
C868D0ED1BB75EA1003D1474 /* PerformanceTests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = PerformanceTests; sourceTree = BUILT_PRODUCTS_DIR; };
C868D0EF1BB75EA1003D1474 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
C868D0F81BB76A29003D1474 /* PerformanceTools.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PerformanceTools.swift; sourceTree = "<group>"; };
C88BB8B71B07E64B0064D411 /* RxTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RxTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C897EC3A1B10E000009C2CB0 /* BehaviorSubjectTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BehaviorSubjectTest.swift; sourceTree = "<group>"; };
C897EC461B112070009C2CB0 /* Observable+MultipleTest+Zip.tt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Observable+MultipleTest+Zip.tt"; sourceTree = "<group>"; };
@ -173,6 +192,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
C868D0EA1BB75EA1003D1474 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
C88BB8AF1B07E64B0064D411 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -193,6 +219,7 @@
C8A468CC1B8A897800BF917B /* RxCocoa.framework */,
C836EA001B8A76A900AB941D /* RxSwift.framework */,
C81108221AF50E11001C13E4 /* Tests */,
C868D0EE1BB75EA1003D1474 /* PerformanceTests */,
C81108211AF50E11001C13E4 /* Products */,
);
sourceTree = "<group>";
@ -202,6 +229,7 @@
children = (
C81108201AF50E11001C13E4 /* RxTests.xctest */,
C88BB8B71B07E64B0064D411 /* RxTests.xctest */,
C868D0ED1BB75EA1003D1474 /* PerformanceTests */,
);
name = Products;
sourceTree = "<group>";
@ -213,6 +241,7 @@
C811082D1AF50E2A001C13E4 /* RxSwiftTests */,
C811084C1AF50E2A001C13E4 /* RxTest.swift */,
C81108231AF50E11001C13E4 /* Supporting Files */,
C868D0F81BB76A29003D1474 /* PerformanceTools.swift */,
);
path = Tests;
sourceTree = "<group>";
@ -318,6 +347,14 @@
path = Tests;
sourceTree = "<group>";
};
C868D0EE1BB75EA1003D1474 /* PerformanceTests */ = {
isa = PBXGroup;
children = (
C868D0EF1BB75EA1003D1474 /* main.swift */,
);
path = PerformanceTests;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -338,6 +375,23 @@
productReference = C81108201AF50E11001C13E4 /* RxTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
C868D0EC1BB75EA1003D1474 /* PerformanceTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = C868D0F11BB75EA1003D1474 /* Build configuration list for PBXNativeTarget "PerformanceTests" */;
buildPhases = (
C868D0E91BB75EA1003D1474 /* Sources */,
C868D0EA1BB75EA1003D1474 /* Frameworks */,
C868D0EB1BB75EA1003D1474 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = PerformanceTests;
productName = PerformanceTests;
productReference = C868D0ED1BB75EA1003D1474 /* PerformanceTests */;
productType = "com.apple.product-type.tool";
};
C88BB88F1B07E64B0064D411 /* RxTests-OSX */ = {
isa = PBXNativeTarget;
buildConfigurationList = C88BB8B41B07E64B0064D411 /* Build configuration list for PBXNativeTarget "RxTests-OSX" */;
@ -367,6 +421,9 @@
C811081F1AF50E11001C13E4 = {
CreatedOnToolsVersion = 6.3;
};
C868D0EC1BB75EA1003D1474 = {
CreatedOnToolsVersion = 7.0;
};
};
};
buildConfigurationList = C81108191AF50DDA001C13E4 /* Build configuration list for PBXProject "RxTests" */;
@ -383,6 +440,7 @@
targets = (
C811081F1AF50E11001C13E4 /* RxTests-iOS */,
C88BB88F1B07E64B0064D411 /* RxTests-OSX */,
C868D0EC1BB75EA1003D1474 /* PerformanceTests */,
);
};
/* End PBXProject section */
@ -412,6 +470,7 @@
C8B787FA1AF55CDE00206D02 /* Observable+ConcurrencyTest.swift in Sources */,
C81108691AF50E2A001C13E4 /* RxTest.swift in Sources */,
C81108671AF50E2A001C13E4 /* Observable+TimeTest.swift in Sources */,
C868D0F91BB76A29003D1474 /* PerformanceTools.swift in Sources */,
C81108551AF50E2A001C13E4 /* TestObservable.swift in Sources */,
C8E3812B1B2083C2008CDC33 /* PrimitiveMockObserver.swift in Sources */,
C811085B1AF50E2A001C13E4 /* Subscription.swift in Sources */,
@ -458,17 +517,26 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
C868D0E91BB75EA1003D1474 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C868D0FB1BB76A29003D1474 /* PerformanceTools.swift in Sources */,
C868D0F01BB75EA1003D1474 /* main.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
C88BB8901B07E64B0064D411 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C88BB8911B07E64B0064D411 /* Observable+ConcurrencyTest.swift in Sources */,
C88BB8921B07E64B0064D411 /* RxTest.swift in Sources */,
C88BB8941B07E64B0064D411 /* Observable+TimeTest.swift in Sources */,
C88BB8951B07E64B0064D411 /* TestObservable.swift in Sources */,
C8CDD7D51B52BEC40043F0C5 /* Observable+BlockingTest.swift in Sources */,
C88BB8961B07E64B0064D411 /* Subscription.swift in Sources */,
C8E381291B207D03008CDC33 /* PrimitiveHotObservable.swift in Sources */,
C868D0FA1BB76A29003D1474 /* PerformanceTools.swift in Sources */,
C88BB8971B07E64B0064D411 /* MySubject.swift in Sources */,
C88BB8981B07E64B0064D411 /* UI+RxTests.swift in Sources */,
C88BB8991B07E64B0064D411 /* Observable+BindingTest.swift in Sources */,
@ -488,6 +556,7 @@
C88BB8A31B07E64B0064D411 /* HotObservable.swift in Sources */,
C8FDC5F91B2B5B7E0065F8D9 /* ElementIndexPair.swift in Sources */,
C88BB8A41B07E64B0064D411 /* Observable.Extensions.swift in Sources */,
C868D0F71BB75EAE003D1474 /* RxTest.swift in Sources */,
C84B8FC31B89D0D500C9CCCF /* BagTest.swift in Sources */,
C897EC3C1B10E000009C2CB0 /* BehaviorSubjectTest.swift in Sources */,
C88BB8A51B07E64B0064D411 /* QueueTests.swift in Sources */,
@ -515,7 +584,6 @@
C811081A1AF50DDA001C13E4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
ENABLE_TESTABILITY = YES;
INFOPLIST_FILE = Tests/Info.plist;
ONLY_ACTIVE_ARCH = YES;
@ -531,7 +599,6 @@
C811081B1AF50DDA001C13E4 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
INFOPLIST_FILE = Tests/Info.plist;
OTHER_LDFLAGS = (
"-framework",
@ -628,7 +695,6 @@
C8633A9D1B09019D00375D60 /* Release-Tests */ = {
isa = XCBuildConfiguration;
buildSettings = {
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
INFOPLIST_FILE = Tests/Info.plist;
OTHER_LDFLAGS = (
"-framework",
@ -716,6 +782,123 @@
};
name = "Release-Tests";
};
C868D0F21BB75EA1003D1474 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
C868D0F31BB75EA1003D1474 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
};
name = Release;
};
C868D0F41BB75EA1003D1474 /* Release-Tests */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
};
name = "Release-Tests";
};
C88BB8B51B07E64B0064D411 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -823,6 +1006,16 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C868D0F11BB75EA1003D1474 /* Build configuration list for PBXNativeTarget "PerformanceTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
C868D0F21BB75EA1003D1474 /* Debug */,
C868D0F31BB75EA1003D1474 /* Release */,
C868D0F41BB75EA1003D1474 /* Release-Tests */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
C88BB8B41B07E64B0064D411 /* Build configuration list for PBXNativeTarget "RxTests-OSX" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -0,0 +1,83 @@
//
// PerformanceTools.swift
// RxTests
//
// Created by Krunoslav Zaher on 9/27/15.
//
//
import Foundation
var mallocFunctions: [(@convention(c) (UnsafeMutablePointer<_malloc_zone_t>, Int) -> UnsafeMutablePointer<Void>)] = []
var allocCalls: Int64 = 0
var bytesAllocated: Int64 = 0
func call0(p: UnsafeMutablePointer<_malloc_zone_t>, size: Int) -> UnsafeMutablePointer<Void> {
OSAtomicIncrement64(&allocCalls)
OSAtomicAdd64(Int64(size), &bytesAllocated)
return mallocFunctions[0](p, size)
}
func call1(p: UnsafeMutablePointer<_malloc_zone_t>, size: Int) -> UnsafeMutablePointer<Void> {
OSAtomicIncrement64(&allocCalls)
OSAtomicAdd64(Int64(size), &bytesAllocated)
return mallocFunctions[1](p, size)
}
var proxies: [(@convention(c) (UnsafeMutablePointer<_malloc_zone_t>, Int) -> UnsafeMutablePointer<Void>)] = [call0, call1]
func getMemoryInfo() -> (bytes: Int64, allocations: Int64) {
return (bytesAllocated, allocCalls)
}
var registeredMallocHooks = false
func registerMallocHooks() {
if registeredMallocHooks {
return
}
registeredMallocHooks = true
var _zones: UnsafeMutablePointer<vm_address_t> = UnsafeMutablePointer(nil)
var count: UInt32 = 0
// malloc_zone_print(nil, 1)
let res = malloc_get_all_zones(mach_task_self_, nil, &_zones, &count)
assert(res == 0)
let zones = UnsafeMutablePointer<UnsafeMutablePointer<malloc_zone_t>>(_zones)
assert(Int(count) <= proxies.count)
let defaultZone = malloc_default_zone()
for i in 0 ..< Int(count) {
let zoneArray = zones.advancedBy(i)
let name = malloc_get_zone_name(zoneArray.memory)
var zone = zoneArray.memory.memory
//print(String.fromCString(name))
assert(name != nil)
mallocFunctions.append(zone.malloc)
zone.malloc = proxies[i]
let protectSize = vm_size_t(sizeof(malloc_zone_t)) * vm_size_t(count)
if zone.version >= 8 {
let addressPointer = UnsafeMutablePointer<vm_address_t>(zoneArray)
let res = vm_protect(mach_task_self_, addressPointer.memory, protectSize, 0, PROT_READ | PROT_WRITE)
assert(res == 0)
}
zoneArray.memory.memory = zone
if defaultZone.memory.version == 8 {
let res = vm_protect(mach_task_self_, _zones.memory, protectSize, 0, PROT_READ)
assert(res == 0)
}
}
}