├── PerformanceTest iOS
├── Info.plist
└── main.m
├── PerformanceTest.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcuserdata
│ └── mikeash.xcuserdatad
│ └── xcschemes
│ ├── PerformanceTest iOS.xcscheme
│ ├── PerformanceTest.xcscheme
│ └── xcschememanagement.plist
├── PerformanceTest
└── main.m
├── perf.h
└── perf.mm
/PerformanceTest iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/PerformanceTest iOS/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // PerformanceTest iOS
4 | //
5 | // Created by Mike Ash on 4/10/16.
6 | // Copyright © 2016 mikeash. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "perf.h"
12 |
13 | int main(int argc, char * argv[]) {
14 | @autoreleasepool {
15 | Test();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/PerformanceTest.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | C25FC3E51CBAE4A800894F64 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C25FC3E41CBAE4A800894F64 /* main.m */; };
11 | C25FC3F31CBAE4C700894F64 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C25FC3F21CBAE4C700894F64 /* main.m */; };
12 | C2E5584B1CBC6E1300F6943C /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C2E5584A1CBC6E1300F6943C /* Cocoa.framework */; };
13 | C2F597731CBAE5760051D0F0 /* perf.mm in Sources */ = {isa = PBXBuildFile; fileRef = C2F597721CBAE5760051D0F0 /* perf.mm */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
14 | C2F597741CBAE5760051D0F0 /* perf.mm in Sources */ = {isa = PBXBuildFile; fileRef = C2F597721CBAE5760051D0F0 /* perf.mm */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXCopyFilesBuildPhase section */
18 | C25FC3DF1CBAE4A700894F64 /* CopyFiles */ = {
19 | isa = PBXCopyFilesBuildPhase;
20 | buildActionMask = 2147483647;
21 | dstPath = /usr/share/man/man1/;
22 | dstSubfolderSpec = 0;
23 | files = (
24 | );
25 | runOnlyForDeploymentPostprocessing = 1;
26 | };
27 | /* End PBXCopyFilesBuildPhase section */
28 |
29 | /* Begin PBXFileReference section */
30 | C25FC3E11CBAE4A800894F64 /* PerformanceTest Mac */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "PerformanceTest Mac"; sourceTree = BUILT_PRODUCTS_DIR; };
31 | C25FC3E41CBAE4A800894F64 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
32 | C25FC3EF1CBAE4C700894F64 /* PerformanceTest iOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "PerformanceTest iOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
33 | C25FC3F21CBAE4C700894F64 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
34 | C25FC4021CBAE4C700894F64 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
35 | C2E5584A1CBC6E1300F6943C /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
36 | C2F597721CBAE5760051D0F0 /* perf.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = perf.mm; sourceTree = ""; };
37 | C2F597751CBAE57D0051D0F0 /* perf.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = perf.h; sourceTree = ""; };
38 | /* End PBXFileReference section */
39 |
40 | /* Begin PBXFrameworksBuildPhase section */
41 | C25FC3DE1CBAE4A700894F64 /* Frameworks */ = {
42 | isa = PBXFrameworksBuildPhase;
43 | buildActionMask = 2147483647;
44 | files = (
45 | C2E5584B1CBC6E1300F6943C /* Cocoa.framework in Frameworks */,
46 | );
47 | runOnlyForDeploymentPostprocessing = 0;
48 | };
49 | C25FC3EC1CBAE4C700894F64 /* Frameworks */ = {
50 | isa = PBXFrameworksBuildPhase;
51 | buildActionMask = 2147483647;
52 | files = (
53 | );
54 | runOnlyForDeploymentPostprocessing = 0;
55 | };
56 | /* End PBXFrameworksBuildPhase section */
57 |
58 | /* Begin PBXGroup section */
59 | C25FC3D81CBAE4A700894F64 = {
60 | isa = PBXGroup;
61 | children = (
62 | C2E5584A1CBC6E1300F6943C /* Cocoa.framework */,
63 | C2F597711CBAE56A0051D0F0 /* Shared */,
64 | C25FC3E31CBAE4A800894F64 /* PerformanceTest */,
65 | C25FC3F01CBAE4C700894F64 /* PerformanceTest iOS */,
66 | C25FC3E21CBAE4A800894F64 /* Products */,
67 | );
68 | sourceTree = "";
69 | };
70 | C25FC3E21CBAE4A800894F64 /* Products */ = {
71 | isa = PBXGroup;
72 | children = (
73 | C25FC3E11CBAE4A800894F64 /* PerformanceTest Mac */,
74 | C25FC3EF1CBAE4C700894F64 /* PerformanceTest iOS.app */,
75 | );
76 | name = Products;
77 | sourceTree = "";
78 | };
79 | C25FC3E31CBAE4A800894F64 /* PerformanceTest */ = {
80 | isa = PBXGroup;
81 | children = (
82 | C25FC3E41CBAE4A800894F64 /* main.m */,
83 | );
84 | path = PerformanceTest;
85 | sourceTree = "";
86 | };
87 | C25FC3F01CBAE4C700894F64 /* PerformanceTest iOS */ = {
88 | isa = PBXGroup;
89 | children = (
90 | C25FC3F21CBAE4C700894F64 /* main.m */,
91 | C25FC4021CBAE4C700894F64 /* Info.plist */,
92 | );
93 | path = "PerformanceTest iOS";
94 | sourceTree = "";
95 | };
96 | C2F597711CBAE56A0051D0F0 /* Shared */ = {
97 | isa = PBXGroup;
98 | children = (
99 | C2F597751CBAE57D0051D0F0 /* perf.h */,
100 | C2F597721CBAE5760051D0F0 /* perf.mm */,
101 | );
102 | name = Shared;
103 | sourceTree = "";
104 | };
105 | /* End PBXGroup section */
106 |
107 | /* Begin PBXNativeTarget section */
108 | C25FC3E01CBAE4A700894F64 /* PerformanceTest Mac */ = {
109 | isa = PBXNativeTarget;
110 | buildConfigurationList = C25FC3E81CBAE4A800894F64 /* Build configuration list for PBXNativeTarget "PerformanceTest Mac" */;
111 | buildPhases = (
112 | C25FC3DD1CBAE4A700894F64 /* Sources */,
113 | C25FC3DE1CBAE4A700894F64 /* Frameworks */,
114 | C25FC3DF1CBAE4A700894F64 /* CopyFiles */,
115 | );
116 | buildRules = (
117 | );
118 | dependencies = (
119 | );
120 | name = "PerformanceTest Mac";
121 | productName = PerformanceTest;
122 | productReference = C25FC3E11CBAE4A800894F64 /* PerformanceTest Mac */;
123 | productType = "com.apple.product-type.tool";
124 | };
125 | C25FC3EE1CBAE4C700894F64 /* PerformanceTest iOS */ = {
126 | isa = PBXNativeTarget;
127 | buildConfigurationList = C25FC4031CBAE4C700894F64 /* Build configuration list for PBXNativeTarget "PerformanceTest iOS" */;
128 | buildPhases = (
129 | C25FC3EB1CBAE4C700894F64 /* Sources */,
130 | C25FC3EC1CBAE4C700894F64 /* Frameworks */,
131 | C25FC3ED1CBAE4C700894F64 /* Resources */,
132 | );
133 | buildRules = (
134 | );
135 | dependencies = (
136 | );
137 | name = "PerformanceTest iOS";
138 | productName = "PerformanceTest iOS";
139 | productReference = C25FC3EF1CBAE4C700894F64 /* PerformanceTest iOS.app */;
140 | productType = "com.apple.product-type.application";
141 | };
142 | /* End PBXNativeTarget section */
143 |
144 | /* Begin PBXProject section */
145 | C25FC3D91CBAE4A700894F64 /* Project object */ = {
146 | isa = PBXProject;
147 | attributes = {
148 | LastUpgradeCheck = 0730;
149 | ORGANIZATIONNAME = mikeash;
150 | TargetAttributes = {
151 | C25FC3E01CBAE4A700894F64 = {
152 | CreatedOnToolsVersion = 7.3;
153 | };
154 | C25FC3EE1CBAE4C700894F64 = {
155 | CreatedOnToolsVersion = 7.3;
156 | };
157 | };
158 | };
159 | buildConfigurationList = C25FC3DC1CBAE4A700894F64 /* Build configuration list for PBXProject "PerformanceTest" */;
160 | compatibilityVersion = "Xcode 3.2";
161 | developmentRegion = English;
162 | hasScannedForEncodings = 0;
163 | knownRegions = (
164 | en,
165 | Base,
166 | );
167 | mainGroup = C25FC3D81CBAE4A700894F64;
168 | productRefGroup = C25FC3E21CBAE4A800894F64 /* Products */;
169 | projectDirPath = "";
170 | projectRoot = "";
171 | targets = (
172 | C25FC3E01CBAE4A700894F64 /* PerformanceTest Mac */,
173 | C25FC3EE1CBAE4C700894F64 /* PerformanceTest iOS */,
174 | );
175 | };
176 | /* End PBXProject section */
177 |
178 | /* Begin PBXResourcesBuildPhase section */
179 | C25FC3ED1CBAE4C700894F64 /* Resources */ = {
180 | isa = PBXResourcesBuildPhase;
181 | buildActionMask = 2147483647;
182 | files = (
183 | );
184 | runOnlyForDeploymentPostprocessing = 0;
185 | };
186 | /* End PBXResourcesBuildPhase section */
187 |
188 | /* Begin PBXSourcesBuildPhase section */
189 | C25FC3DD1CBAE4A700894F64 /* Sources */ = {
190 | isa = PBXSourcesBuildPhase;
191 | buildActionMask = 2147483647;
192 | files = (
193 | C25FC3E51CBAE4A800894F64 /* main.m in Sources */,
194 | C2F597731CBAE5760051D0F0 /* perf.mm in Sources */,
195 | );
196 | runOnlyForDeploymentPostprocessing = 0;
197 | };
198 | C25FC3EB1CBAE4C700894F64 /* Sources */ = {
199 | isa = PBXSourcesBuildPhase;
200 | buildActionMask = 2147483647;
201 | files = (
202 | C25FC3F31CBAE4C700894F64 /* main.m in Sources */,
203 | C2F597741CBAE5760051D0F0 /* perf.mm in Sources */,
204 | );
205 | runOnlyForDeploymentPostprocessing = 0;
206 | };
207 | /* End PBXSourcesBuildPhase section */
208 |
209 | /* Begin XCBuildConfiguration section */
210 | C25FC3E61CBAE4A800894F64 /* Debug */ = {
211 | isa = XCBuildConfiguration;
212 | buildSettings = {
213 | ALWAYS_SEARCH_USER_PATHS = NO;
214 | CLANG_ANALYZER_NONNULL = YES;
215 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
216 | CLANG_CXX_LIBRARY = "libc++";
217 | CLANG_ENABLE_MODULES = YES;
218 | CLANG_ENABLE_OBJC_ARC = YES;
219 | CLANG_WARN_BOOL_CONVERSION = YES;
220 | CLANG_WARN_CONSTANT_CONVERSION = YES;
221 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
222 | CLANG_WARN_EMPTY_BODY = YES;
223 | CLANG_WARN_ENUM_CONVERSION = YES;
224 | CLANG_WARN_INT_CONVERSION = YES;
225 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
226 | CLANG_WARN_UNREACHABLE_CODE = YES;
227 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
228 | CODE_SIGN_IDENTITY = "-";
229 | COPY_PHASE_STRIP = NO;
230 | DEBUG_INFORMATION_FORMAT = dwarf;
231 | ENABLE_STRICT_OBJC_MSGSEND = YES;
232 | ENABLE_TESTABILITY = YES;
233 | GCC_C_LANGUAGE_STANDARD = gnu99;
234 | GCC_DYNAMIC_NO_PIC = NO;
235 | GCC_NO_COMMON_BLOCKS = YES;
236 | GCC_OPTIMIZATION_LEVEL = 0;
237 | GCC_PREPROCESSOR_DEFINITIONS = (
238 | "DEBUG=1",
239 | "$(inherited)",
240 | );
241 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
242 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
243 | GCC_WARN_UNDECLARED_SELECTOR = YES;
244 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
245 | GCC_WARN_UNUSED_FUNCTION = YES;
246 | GCC_WARN_UNUSED_VARIABLE = YES;
247 | MACOSX_DEPLOYMENT_TARGET = 10.11;
248 | MTL_ENABLE_DEBUG_INFO = YES;
249 | ONLY_ACTIVE_ARCH = YES;
250 | SDKROOT = macosx;
251 | };
252 | name = Debug;
253 | };
254 | C25FC3E71CBAE4A800894F64 /* Release */ = {
255 | isa = XCBuildConfiguration;
256 | buildSettings = {
257 | ALWAYS_SEARCH_USER_PATHS = NO;
258 | CLANG_ANALYZER_NONNULL = YES;
259 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
260 | CLANG_CXX_LIBRARY = "libc++";
261 | CLANG_ENABLE_MODULES = YES;
262 | CLANG_ENABLE_OBJC_ARC = YES;
263 | CLANG_WARN_BOOL_CONVERSION = YES;
264 | CLANG_WARN_CONSTANT_CONVERSION = YES;
265 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
266 | CLANG_WARN_EMPTY_BODY = YES;
267 | CLANG_WARN_ENUM_CONVERSION = YES;
268 | CLANG_WARN_INT_CONVERSION = YES;
269 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
270 | CLANG_WARN_UNREACHABLE_CODE = YES;
271 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
272 | CODE_SIGN_IDENTITY = "-";
273 | COPY_PHASE_STRIP = NO;
274 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
275 | ENABLE_NS_ASSERTIONS = NO;
276 | ENABLE_STRICT_OBJC_MSGSEND = YES;
277 | GCC_C_LANGUAGE_STANDARD = gnu99;
278 | GCC_NO_COMMON_BLOCKS = YES;
279 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
280 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
281 | GCC_WARN_UNDECLARED_SELECTOR = YES;
282 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
283 | GCC_WARN_UNUSED_FUNCTION = YES;
284 | GCC_WARN_UNUSED_VARIABLE = YES;
285 | MACOSX_DEPLOYMENT_TARGET = 10.11;
286 | MTL_ENABLE_DEBUG_INFO = NO;
287 | SDKROOT = macosx;
288 | };
289 | name = Release;
290 | };
291 | C25FC3E91CBAE4A800894F64 /* Debug */ = {
292 | isa = XCBuildConfiguration;
293 | buildSettings = {
294 | PRODUCT_NAME = "$(TARGET_NAME)";
295 | };
296 | name = Debug;
297 | };
298 | C25FC3EA1CBAE4A800894F64 /* Release */ = {
299 | isa = XCBuildConfiguration;
300 | buildSettings = {
301 | PRODUCT_NAME = "$(TARGET_NAME)";
302 | };
303 | name = Release;
304 | };
305 | C25FC4041CBAE4C700894F64 /* Debug */ = {
306 | isa = XCBuildConfiguration;
307 | buildSettings = {
308 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
309 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
310 | INFOPLIST_FILE = "PerformanceTest iOS/Info.plist";
311 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
312 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
313 | PRODUCT_BUNDLE_IDENTIFIER = "com.mikeash.PerformanceTest-iOS";
314 | PRODUCT_NAME = "$(TARGET_NAME)";
315 | SDKROOT = iphoneos;
316 | TARGETED_DEVICE_FAMILY = "1,2";
317 | };
318 | name = Debug;
319 | };
320 | C25FC4051CBAE4C700894F64 /* Release */ = {
321 | isa = XCBuildConfiguration;
322 | buildSettings = {
323 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
324 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
325 | INFOPLIST_FILE = "PerformanceTest iOS/Info.plist";
326 | IPHONEOS_DEPLOYMENT_TARGET = 9.3;
327 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
328 | PRODUCT_BUNDLE_IDENTIFIER = "com.mikeash.PerformanceTest-iOS";
329 | PRODUCT_NAME = "$(TARGET_NAME)";
330 | SDKROOT = iphoneos;
331 | TARGETED_DEVICE_FAMILY = "1,2";
332 | VALIDATE_PRODUCT = YES;
333 | };
334 | name = Release;
335 | };
336 | /* End XCBuildConfiguration section */
337 |
338 | /* Begin XCConfigurationList section */
339 | C25FC3DC1CBAE4A700894F64 /* Build configuration list for PBXProject "PerformanceTest" */ = {
340 | isa = XCConfigurationList;
341 | buildConfigurations = (
342 | C25FC3E61CBAE4A800894F64 /* Debug */,
343 | C25FC3E71CBAE4A800894F64 /* Release */,
344 | );
345 | defaultConfigurationIsVisible = 0;
346 | defaultConfigurationName = Release;
347 | };
348 | C25FC3E81CBAE4A800894F64 /* Build configuration list for PBXNativeTarget "PerformanceTest Mac" */ = {
349 | isa = XCConfigurationList;
350 | buildConfigurations = (
351 | C25FC3E91CBAE4A800894F64 /* Debug */,
352 | C25FC3EA1CBAE4A800894F64 /* Release */,
353 | );
354 | defaultConfigurationIsVisible = 0;
355 | defaultConfigurationName = Release;
356 | };
357 | C25FC4031CBAE4C700894F64 /* Build configuration list for PBXNativeTarget "PerformanceTest iOS" */ = {
358 | isa = XCConfigurationList;
359 | buildConfigurations = (
360 | C25FC4041CBAE4C700894F64 /* Debug */,
361 | C25FC4051CBAE4C700894F64 /* Release */,
362 | );
363 | defaultConfigurationIsVisible = 0;
364 | defaultConfigurationName = Release;
365 | };
366 | /* End XCConfigurationList section */
367 | };
368 | rootObject = C25FC3D91CBAE4A700894F64 /* Project object */;
369 | }
370 |
--------------------------------------------------------------------------------
/PerformanceTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/PerformanceTest.xcodeproj/xcuserdata/mikeash.xcuserdatad/xcschemes/PerformanceTest iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/PerformanceTest.xcodeproj/xcuserdata/mikeash.xcuserdatad/xcschemes/PerformanceTest.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/PerformanceTest.xcodeproj/xcuserdata/mikeash.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | PerformanceTest iOS.xcscheme
8 |
9 | orderHint
10 | 1
11 |
12 | PerformanceTest.xcscheme
13 |
14 | orderHint
15 | 0
16 |
17 |
18 | SuppressBuildableAutocreation
19 |
20 | C25FC3E01CBAE4A700894F64
21 |
22 | primary
23 |
24 |
25 | C25FC3EE1CBAE4C700894F64
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/PerformanceTest/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // PerformanceTest
4 | //
5 | // Created by Mike Ash on 4/10/16.
6 | // Copyright © 2016 mikeash. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "perf.h"
12 |
13 |
14 | int main(int argc, const char * argv[]) {
15 | @autoreleasepool {
16 | Test();
17 | }
18 | return 0;
19 | }
20 |
--------------------------------------------------------------------------------
/perf.h:
--------------------------------------------------------------------------------
1 | //
2 | // perf_iphone.h
3 | // PerformanceTest
4 | //
5 | // Created by Michael Ash on 4/5/16.
6 | // Copyright © 2016 mikeash. All rights reserved.
7 | //
8 |
9 | #ifdef __cplusplus
10 | extern "C"
11 | #endif
12 | void Test(void);
13 |
--------------------------------------------------------------------------------
/perf.mm:
--------------------------------------------------------------------------------
1 | #import
2 | #if TARGET_OS_IOS
3 | #import
4 | #else
5 | #import
6 | #endif
7 |
8 | #import
9 | #import
10 | #import "perf.h"
11 |
12 | #include
13 | #include
14 |
15 | #include
16 | #include
17 |
18 |
19 | struct RawTestResult {
20 | uint64_t iterations;
21 | uint64_t testsPerIteration;
22 | uint64_t startTime;
23 | uint64_t endTime;
24 | };
25 |
26 | struct TestResult {
27 | const char *name;
28 | uint64_t iterations;
29 | NSTimeInterval total;
30 | NSTimeInterval each;
31 | };
32 |
33 | struct TestInfo {
34 | const char *name;
35 | RawTestResult (*fptr)(void);
36 | };
37 |
38 | static std::vector AllTests;
39 | TestInfo EmptyLoopTest;
40 | TestInfo *RunOnlyTest;
41 |
42 | void Test(void) {
43 | struct mach_timebase_info tbinfo;
44 | mach_timebase_info( &tbinfo );
45 | auto absToNanos = [&](uint64_t abs) { return abs * tbinfo.numer / tbinfo.denom; };
46 |
47 | auto overheadResult = EmptyLoopTest.fptr();
48 | NSTimeInterval totalOverhead = absToNanos(overheadResult.endTime - overheadResult.startTime);
49 | NSTimeInterval overheadPerIteration = totalOverhead / overheadResult.iterations;
50 |
51 | if(RunOnlyTest != NULL) {
52 | AllTests.clear();
53 | AllTests.push_back(*RunOnlyTest);
54 | }
55 |
56 | std::vector results;
57 |
58 | // size_t i = AllTests.size();
59 | // while(i --> 0) {
60 | // auto info = AllTests[i];
61 | for(auto info : AllTests) {
62 | @autoreleasepool {
63 | NSLog(@"Beginning test %s", info.name);
64 | auto rawResult = info.fptr();
65 | NSTimeInterval totalTime = absToNanos(rawResult.endTime - rawResult.startTime);
66 | NSTimeInterval totalMinusOverhead = totalTime - rawResult.iterations * overheadPerIteration;
67 | NSTimeInterval timePerIteration = totalMinusOverhead / (rawResult.iterations * rawResult.testsPerIteration);
68 | NSLog(@"Completed test %s in %f seconds total, %fns each", info.name, totalMinusOverhead / NSEC_PER_SEC, timePerIteration);
69 |
70 | TestResult result;
71 | result.name = info.name;
72 | result.iterations = rawResult.iterations * rawResult.testsPerIteration;
73 | result.total = totalMinusOverhead / NSEC_PER_SEC;
74 | result.each = timePerIteration;
75 | results.push_back(result);
76 | }
77 | }
78 |
79 | printf("Name | Iterations | Total time (sec) | Time per (ns) |
\n");
80 |
81 | std::sort(results.begin(), results.end(), [](TestResult &a, TestResult &b) { return a.each < b.each; });
82 | for(auto result : results) {
83 | printf("%s | %" PRIu64 " | %.1f | %.1f |
\n", result.name, result.iterations, result.total, result.each);
84 | }
85 |
86 | printf("
\n");
87 | }
88 |
89 | struct RegisterTest {
90 | TestInfo info;
91 |
92 | RegisterTest(const char *name, RawTestResult (*fptr)(void)) {
93 | info.name = name;
94 | info.fptr = fptr;
95 |
96 | if(strcmp(name, "Empty loop") == 0) {
97 | EmptyLoopTest = info;
98 | } else {
99 | AllTests.push_back(info);
100 | }
101 | }
102 |
103 | /// Add a call to this after DECLARE_TEST to make this the only performance test that runs,
104 | /// so you don't have to wait through the whole test cycle to check one while working on it.
105 | RegisterTest runOnlyThis() {
106 | RunOnlyTest = new TestInfo;
107 | *RunOnlyTest = info;
108 | return *this;
109 | }
110 | };
111 |
112 | #define CONCAT2(x, y) x ## y
113 | #define CONCAT(x, y) CONCAT2(x, y)
114 |
115 | #define DECLARE_TEST(_name, _iterations, _testsPerIteration, _setupCode, _testCode, _cleanupCode) \
116 | static RegisterTest CONCAT(test, __COUNTER__) = RegisterTest(_name, []() -> RawTestResult { \
117 | RawTestResult info; \
118 | info.iterations = _iterations; \
119 | info.testsPerIteration = _testsPerIteration; \
120 | _setupCode; \
121 | info.startTime = mach_absolute_time(); \
122 | for(uint64_t i = 1; i <= _iterations; i++) { \
123 | /* NOTE: i starts from 1 so it can be used as a divisor for integer division testing, silly I know. */ \
124 | _testCode; \
125 | } \
126 | info.endTime = mach_absolute_time(); \
127 | _cleanupCode; \
128 | return info; \
129 | })
130 |
131 | DECLARE_TEST("Empty loop", 1000000000, 1, {}, {}, {});
132 |
133 |
134 | class StubClass
135 | {
136 | public:
137 | virtual void stub() { }
138 | };
139 |
140 | DECLARE_TEST("C++ virtual method call", 100000000, 10,
141 | class StubClass *obj = new StubClass,
142 | obj->stub();
143 | obj->stub();
144 | obj->stub();
145 | obj->stub();
146 | obj->stub();
147 | obj->stub();
148 | obj->stub();
149 | obj->stub();
150 | obj->stub();
151 | obj->stub();,
152 | delete obj);
153 |
154 | @interface DummyClass: NSObject
155 | - (void)dummyMethod;
156 | @end
157 | @implementation DummyClass
158 | - (void)dummyMethod {}
159 | @end
160 |
161 | DECLARE_TEST("Objective-C message send", 100000000, 10,
162 | DummyClass *dummy = [[DummyClass alloc] init],
163 | [dummy dummyMethod];
164 | [dummy dummyMethod];
165 | [dummy dummyMethod];
166 | [dummy dummyMethod];
167 | [dummy dummyMethod];
168 | [dummy dummyMethod];
169 | [dummy dummyMethod];
170 | [dummy dummyMethod];
171 | [dummy dummyMethod];
172 | [dummy dummyMethod];,
173 | [dummy release]);
174 |
175 | DECLARE_TEST("IMP-cached message send", 100000000, 10,
176 | DummyClass *dummy = [[DummyClass alloc] init];
177 | SEL sel = @selector(dummyMethod);
178 | void (*imp)(id, SEL) = (void (*)(id, SEL))[dummy methodForSelector: sel],
179 | imp(dummy, sel);
180 | imp(dummy, sel);
181 | imp(dummy, sel);
182 | imp(dummy, sel);
183 | imp(dummy, sel);
184 | imp(dummy, sel);
185 | imp(dummy, sel);
186 | imp(dummy, sel);
187 | imp(dummy, sel);
188 | imp(dummy, sel);,
189 | [dummy release]);
190 |
191 | DECLARE_TEST("NSInvocation message send", 1000000, 10,
192 | DummyClass *dummy = [[DummyClass alloc] init];
193 | SEL sel = @selector(dummyMethod);
194 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [dummy methodSignatureForSelector: sel]];
195 | [invocation setSelector: sel];
196 | [invocation setTarget: dummy];,
197 | [invocation invoke];
198 | [invocation invoke];
199 | [invocation invoke];
200 | [invocation invoke];
201 | [invocation invoke];
202 | [invocation invoke];
203 | [invocation invoke];
204 | [invocation invoke];
205 | [invocation invoke];
206 | [invocation invoke];,
207 | [dummy release]);
208 |
209 | DECLARE_TEST("Integer division", 100000000, 10,
210 | int x,
211 | x = 1000000000 / i;
212 | x = 1000000000 / i;
213 | x = 1000000000 / i;
214 | x = 1000000000 / i;
215 | x = 1000000000 / i;
216 | x = 1000000000 / i;
217 | x = 1000000000 / i;
218 | x = 1000000000 / i;
219 | x = 1000000000 / i;
220 | x = 1000000000 / i;,
221 | );
222 |
223 | DECLARE_TEST("Floating-point division", 100000000, 10,
224 | double x;
225 | double y = 42.3;,
226 | x = 100000000.0 / y;
227 | x = 100000000.0 / y;
228 | x = 100000000.0 / y;
229 | x = 100000000.0 / y;
230 | x = 100000000.0 / y;
231 | x = 100000000.0 / y;
232 | x = 100000000.0 / y;
233 | x = 100000000.0 / y;
234 | x = 100000000.0 / y;
235 | x = 100000000.0 / y;,
236 | );
237 |
238 | DECLARE_TEST("Floating-point division with integer conversion", 100000000, 10,
239 | double x,
240 | x = 100000000.0 / i;
241 | x = 100000000.0 / i;
242 | x = 100000000.0 / i;
243 | x = 100000000.0 / i;
244 | x = 100000000.0 / i;
245 | x = 100000000.0 / i;
246 | x = 100000000.0 / i;
247 | x = 100000000.0 / i;
248 | x = 100000000.0 / i;
249 | x = 100000000.0 / i;,
250 | );
251 |
252 | extern "C" void objc_release(id);
253 | extern "C" void objc_retain(id);
254 |
255 | DECLARE_TEST("ObjC retain and release", 10000000, 10,
256 | id obj = [[NSObject alloc] init],
257 | objc_retain(obj); objc_release(obj);
258 | objc_retain(obj); objc_release(obj);
259 | objc_retain(obj); objc_release(obj);
260 | objc_retain(obj); objc_release(obj);
261 | objc_retain(obj); objc_release(obj);
262 | objc_retain(obj); objc_release(obj);
263 | objc_retain(obj); objc_release(obj);
264 | objc_retain(obj); objc_release(obj);
265 | objc_retain(obj); objc_release(obj);
266 | objc_retain(obj); objc_release(obj);,
267 | objc_release(obj));
268 |
269 | DECLARE_TEST("Object creation", 1000000, 10, {},
270 | objc_release([[NSObject alloc] init]);
271 | objc_release([[NSObject alloc] init]);
272 | objc_release([[NSObject alloc] init]);
273 | objc_release([[NSObject alloc] init]);
274 | objc_release([[NSObject alloc] init]);
275 | objc_release([[NSObject alloc] init]);
276 | objc_release([[NSObject alloc] init]);
277 | objc_release([[NSObject alloc] init]);
278 | objc_release([[NSObject alloc] init]);
279 | objc_release([[NSObject alloc] init]);,
280 | );
281 |
282 | DECLARE_TEST("Autorelease pool push/pop", 10000000, 10, {},
283 | @autoreleasepool {}
284 | @autoreleasepool {}
285 | @autoreleasepool {}
286 | @autoreleasepool {}
287 | @autoreleasepool {}
288 | @autoreleasepool {}
289 | @autoreleasepool {}
290 | @autoreleasepool {}
291 | @autoreleasepool {}
292 | @autoreleasepool {},
293 | );
294 |
295 | DECLARE_TEST("16-byte malloc/free", 10000000, 10, {},
296 | free(malloc(16));
297 | free(malloc(16));
298 | free(malloc(16));
299 | free(malloc(16));
300 | free(malloc(16));
301 | free(malloc(16));
302 | free(malloc(16));
303 | free(malloc(16));
304 | free(malloc(16));
305 | free(malloc(16));,
306 | );
307 |
308 | DECLARE_TEST("16MB malloc/free", 1000000, 10, {},
309 | free(malloc(1 << 24));
310 | free(malloc(1 << 24));
311 | free(malloc(1 << 24));
312 | free(malloc(1 << 24));
313 | free(malloc(1 << 24));
314 | free(malloc(1 << 24));
315 | free(malloc(1 << 24));
316 | free(malloc(1 << 24));
317 | free(malloc(1 << 24));
318 | free(malloc(1 << 24));,
319 | );
320 |
321 | #define DECLARE_MEMCPY_TEST(humanSize, machineSize, count) \
322 | DECLARE_TEST(humanSize " memcpy", count, 10, \
323 | char *src = (char *)calloc((machineSize) + 16, 1); \
324 | char *dst = (char *)malloc((machineSize) + 16); \
325 | char *offsetSrc = src + 16; \
326 | char *offsetDst = dst + 16;, \
327 | memcpy(offsetDst, offsetSrc, machineSize); \
328 | memcpy(offsetDst, offsetSrc, machineSize); \
329 | memcpy(offsetDst, offsetSrc, machineSize); \
330 | memcpy(offsetDst, offsetSrc, machineSize); \
331 | memcpy(offsetDst, offsetSrc, machineSize); \
332 | memcpy(offsetDst, offsetSrc, machineSize); \
333 | memcpy(offsetDst, offsetSrc, machineSize); \
334 | memcpy(offsetDst, offsetSrc, machineSize); \
335 | memcpy(offsetDst, offsetSrc, machineSize); \
336 | memcpy(offsetDst, offsetSrc, machineSize);, \
337 | free(src); \
338 | free(dst))
339 |
340 | DECLARE_MEMCPY_TEST("16 byte", 16, 100000000);
341 | DECLARE_MEMCPY_TEST("1MB", 1 << 20, 10000);
342 |
343 | static NSString *tmpFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent: @"testrand"];
344 |
345 | #define DECLARE_WRITE_FILE_TEST(humanSize, machineSize, count, atomic) \
346 | DECLARE_TEST(atomic ? "Write " humanSize " file (atomic)" : "Write " humanSize " file", count, 1, \
347 | NSData *data = [[NSFileHandle fileHandleForReadingAtPath: @"/dev/random"] readDataOfLength: machineSize], \
348 | [data writeToFile: tmpFilePath atomically: atomic], \
349 | [[NSFileManager defaultManager] removeItemAtPath: tmpFilePath error: NULL])
350 |
351 | DECLARE_WRITE_FILE_TEST("16 byte", 16, 10000, NO);
352 | DECLARE_WRITE_FILE_TEST("16 byte", 16, 10000, YES);
353 | DECLARE_WRITE_FILE_TEST("16MB", 1 << 24, 30, NO);
354 | DECLARE_WRITE_FILE_TEST("16MB", 1 << 24, 30, YES);
355 |
356 | #define DECLARE_READ_FILE_TEST(humanSize, machineSize, count) \
357 | DECLARE_TEST("Read " humanSize " file", count, 1, \
358 | NSData *data = [[NSFileHandle fileHandleForReadingAtPath: @"/dev/random"] readDataOfLength: machineSize]; \
359 | [data writeToFile: tmpFilePath atomically: NO];, \
360 | [[[NSData alloc] initWithContentsOfFile: tmpFilePath] release], \
361 | [[NSFileManager defaultManager] removeItemAtPath: tmpFilePath error: NULL])
362 |
363 | DECLARE_READ_FILE_TEST("16 byte", 16, 1000000);
364 | DECLARE_READ_FILE_TEST("16MB", 1 << 24, 1000);
365 |
366 | static void *stub_pthread( void * )
367 | {
368 | return NULL;
369 | }
370 |
371 | DECLARE_TEST("pthread create/join", 100000, 1, {},
372 | pthread_t pt;
373 | pthread_create(&pt, NULL, stub_pthread, NULL);
374 | pthread_join(pt, NULL);,
375 | {});
376 |
377 | DECLARE_TEST("Dispatch queue create/destroy", 1000000, 10, {},
378 | dispatch_release(dispatch_queue_create("dummy testing queue", NULL));
379 | dispatch_release(dispatch_queue_create("dummy testing queue", NULL));
380 | dispatch_release(dispatch_queue_create("dummy testing queue", NULL));
381 | dispatch_release(dispatch_queue_create("dummy testing queue", NULL));
382 | dispatch_release(dispatch_queue_create("dummy testing queue", NULL));
383 | dispatch_release(dispatch_queue_create("dummy testing queue", NULL));
384 | dispatch_release(dispatch_queue_create("dummy testing queue", NULL));
385 | dispatch_release(dispatch_queue_create("dummy testing queue", NULL));
386 | dispatch_release(dispatch_queue_create("dummy testing queue", NULL));
387 | dispatch_release(dispatch_queue_create("dummy testing queue", NULL));,
388 | {});
389 |
390 | DECLARE_TEST("Dispatch_sync", 10000000, 10,
391 | dispatch_queue_t queue = dispatch_queue_create("dummy testing queue", NULL),
392 | dispatch_sync(queue, ^{});
393 | dispatch_sync(queue, ^{});
394 | dispatch_sync(queue, ^{});
395 | dispatch_sync(queue, ^{});
396 | dispatch_sync(queue, ^{});
397 | dispatch_sync(queue, ^{});
398 | dispatch_sync(queue, ^{});
399 | dispatch_sync(queue, ^{});
400 | dispatch_sync(queue, ^{});
401 | dispatch_sync(queue, ^{});,
402 | dispatch_release(queue));
403 |
404 | DECLARE_TEST("Dispatch_async and wait", 100000, 10,
405 | dispatch_queue_t queue = dispatch_queue_create("dummy testing queue", NULL);
406 | __block volatile int done,
407 | done = 0; dispatch_async(queue, ^{ done = 1; }); while(!done);
408 | done = 0; dispatch_async(queue, ^{ done = 1; }); while(!done);
409 | done = 0; dispatch_async(queue, ^{ done = 1; }); while(!done);
410 | done = 0; dispatch_async(queue, ^{ done = 1; }); while(!done);
411 | done = 0; dispatch_async(queue, ^{ done = 1; }); while(!done);
412 | done = 0; dispatch_async(queue, ^{ done = 1; }); while(!done);
413 | done = 0; dispatch_async(queue, ^{ done = 1; }); while(!done);
414 | done = 0; dispatch_async(queue, ^{ done = 1; }); while(!done);
415 | done = 0; dispatch_async(queue, ^{ done = 1; }); while(!done);
416 | done = 0; dispatch_async(queue, ^{ done = 1; }); while(!done);,
417 | dispatch_release(queue));
418 |
419 | @interface DelayedPerformClass: NSObject @end
420 | @implementation DelayedPerformClass {
421 | uint64_t _currentIteration;
422 | @public
423 | uint64_t _iterationLimit;
424 | }
425 |
426 | - (void)delayedPerform {
427 | if(_currentIteration++ < _iterationLimit) {
428 | [self performSelector: @selector(delayedPerform) withObject: nil afterDelay: 0];
429 | } else {
430 | CFRunLoopStop(CFRunLoopGetCurrent());
431 | }
432 | }
433 |
434 | @end
435 |
436 | DECLARE_TEST("Zero-zecond delayed perform", 100000, 1,
437 | DelayedPerformClass *obj = [[DelayedPerformClass alloc] init];
438 | obj->_iterationLimit = 100000;,
439 | [obj performSelector: @selector(delayedPerform) withObject: nil afterDelay: 0];
440 | CFRunLoopRun();
441 | break;, /* We do our own loop, so break out of the testing loop. Uuuugly. */
442 | [obj release]);
443 |
444 | DECLARE_TEST("Simple JSON encode", 1000000, 1,
445 | NSDictionary *dict = (@{@"one": @"won", @"two": @2, @"three": @"free"}),
446 | @autoreleasepool {
447 | [NSJSONSerialization dataWithJSONObject: dict options: 0 error: NULL];
448 | },
449 | {});
450 |
451 | DECLARE_TEST("Simple JSON decode", 1000000, 1,
452 | NSDictionary *dict = (@{@"one": @"won", @"two": @2, @"three": @"free"});
453 | NSData *json = [NSJSONSerialization dataWithJSONObject: dict options: 0 error: NULL],
454 | @autoreleasepool {
455 | [NSJSONSerialization JSONObjectWithData: json options: 0 error: NULL];
456 | },
457 | {});
458 |
459 | DECLARE_TEST("Simple XML plist encode", 1000000, 1,
460 | NSDictionary *dict = (@{@"one": @"won", @"two": @2, @"three": @"free"}),
461 | @autoreleasepool {
462 | [NSPropertyListSerialization dataWithPropertyList:dict format: NSPropertyListXMLFormat_v1_0 options: 0 error: NULL];
463 | },
464 | {});
465 |
466 | DECLARE_TEST("Simple binary plist encode", 1000000, 1,
467 | NSDictionary *dict = (@{@"one": @"won", @"two": @2, @"three": @"free"}),
468 | @autoreleasepool {
469 | [NSPropertyListSerialization dataWithPropertyList:dict format: NSPropertyListBinaryFormat_v1_0 options: 0 error: NULL];
470 | },
471 | {});
472 |
473 | DECLARE_TEST("Simple XML plist decode", 1000000, 1,
474 | NSDictionary *dict = (@{@"one": @"won", @"two": @2, @"three": @"free"});
475 | NSData *plist = [NSPropertyListSerialization dataWithPropertyList:dict format: NSPropertyListXMLFormat_v1_0 options: 0 error: NULL],
476 | @autoreleasepool {
477 | [NSPropertyListSerialization propertyListWithData: plist options: 0 format: NULL error: NULL];
478 | },
479 | {});
480 |
481 | DECLARE_TEST("Simple binary plist decode", 1000000, 1,
482 | NSDictionary *dict = (@{@"one": @"won", @"two": @2, @"three": @"free"});
483 | NSData *plist = [NSPropertyListSerialization dataWithPropertyList:dict format: NSPropertyListBinaryFormat_v1_0 options: 0 error: NULL],
484 | @autoreleasepool {
485 | [NSPropertyListSerialization propertyListWithData: plist options: 0 format: NULL error: NULL];
486 | },
487 | {});
488 |
489 | #pragma mark Mac-specific tests
490 |
491 | #if !TARGET_OS_IOS
492 | DECLARE_TEST("NSTask process spawn", 100, 1, {},
493 | NSTask *task = [[NSTask alloc] init];
494 | [task setLaunchPath: @"/usr/bin/false"];
495 | [task launch];
496 | [task waitUntilExit];
497 | [task release];,
498 | );
499 |
500 | DECLARE_TEST("NSWindow create/destroy", 1000, 1, {},
501 | objc_release([[NSWindow alloc] init]),
502 | {});
503 |
504 | DECLARE_TEST("NSView create/destroy", 1000000, 1, {},
505 | objc_release([[NSView alloc] init]),
506 | {});
507 | #endif
508 |
509 |
510 | #pragma mark iOS-specific tests
511 |
512 | #if TARGET_OS_IOS
513 | DECLARE_TEST("UIView create/destroy", 1000000, 1, {},
514 | objc_release([[UIView alloc] init]),
515 | {});
516 | #endif
517 |
518 |
--------------------------------------------------------------------------------