Skip to content
This repository has been archived by the owner on Sep 19, 2018. It is now read-only.

Benchmarking/sample case #59

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,5 @@ DerivedData
*.ipa
*.xcuserstate

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
# Pods/
# Ignore 5-10MB JSON payloads
BNRSwiftJSONTests/Benchmark/*.json
164 changes: 164 additions & 0 deletions BNRSwiftJSON.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "0720"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
2 changes: 2 additions & 0 deletions BNRSwiftJSON/JSONParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
// Copyright © 2015 Big Nerd Ranch. Licensed under MIT.
//

import Foundation

private struct Literal {
static let BACKSLASH = UInt8(ascii: "\\")
static let BACKSPACE = UInt8(ascii: "\u{0008}")
Expand Down
7 changes: 7 additions & 0 deletions BNRSwiftJSONTests/BNRSwiftJSONTests-Bridging-Header.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//

#import "CardSet.h"
#import "Card.h"
#import "CardUtilities.h"
88 changes: 88 additions & 0 deletions BNRSwiftJSONTests/Benchmark.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//
// JSONBenchmark.swift
// BNRSwiftJSON
//
// Created by Zachary Waldowski on 5/20/15.
// Copyright (c) 2015 Big Nerd Ranch Inc. All rights reserved.
//

import XCTest
import BNRSwiftJSON

private enum ErrorFromObjCModel: ErrorType {
case FailedToDecode
}

class JSONBenchmark: XCTestCase {

private var jsonData: NSData!

override func setUp() {
super.setUp()

let testBundle = NSBundle(forClass: JSONBenchmark.self)
guard let data = testBundle.URLForResource("AllSetsArray", withExtension: "json").flatMap(NSData.init) else {
XCTFail("Could not read stress test data from test bundle")
return
}

jsonData = data
}

private func measureWithoutRR<T>(body: () throws -> T, assertions: (T -> ())?) {
measureMetrics(self.dynamicType.defaultPerformanceMetrics(), automaticallyStartMeasuring: false) {
var value: T!

self.startMeasuring()
value = try? body()
self.stopMeasuring()

XCTAssertNotNil(value)
assertions?(value)

value = nil
}
}

func testJSONDeserializeCocoa() {
measureWithoutRR({
try NSJSONSerialization.JSONObjectWithData(self.jsonData, options: [])
}, assertions: nil)
}

func testJSONDeserializeCustom() {
measureWithoutRR({
try JSON(data: self.jsonData, usingParser: JSONParser.self)
}, assertions: nil)
}

func testJSONDeserializeCustomViaCocoa() {
measureWithoutRR({
try JSON(data: self.jsonData, usingParser: NSJSONSerialization.self)
}, assertions: nil)
}

func testJSONDeserializeToCocoaModel() {
measureWithoutRR({ () throws -> ([CardSetObjC], Int) in
let cocoaJSON = try NSJSONSerialization.JSONObjectWithData(self.jsonData, options: []) as! [[String: AnyObject]]
guard let objects = CardSetObjC.cardSetsFromDictionaries(cocoaJSON) else {
throw ErrorFromObjCModel.FailedToDecode
}
return (objects, cocoaJSON.count)
}, assertions: {
XCTAssertEqual($0.0.count, $0.1, "Failed to convert all sets")
})
}

func testJSONDeserializeToModel() {
measureWithoutRR({ () throws -> ([CardSet], Int) in
let json = try JSON(data: self.jsonData, usingParser: JSONParser.self)
let expectedCount = try json.array().count
let objects = try json.arrayOf(type: CardSet.self)
return (objects, expectedCount)
}, assertions: {
XCTAssertEqual($0.0.count, $0.1, "Failed to convert all sets")
})
}

}
Empty file.
50 changes: 50 additions & 0 deletions BNRSwiftJSONTests/Card.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// Card.h
// BNRSwiftJSON
//
// Created by Zachary Waldowski on 5/20/15.
// Copyright (c) 2015 Big Nerd Ranch Inc. All rights reserved.
//

@import Foundation;
#import "CardUtilities.h"

NS_ASSUME_NONNULL_BEGIN

@interface CardObjC : NSObject

@property (nonatomic, copy, readonly) NSString *layout;
@property (nonatomic, copy, readonly) NSString *name;
@property (nonatomic, copy, readonly) NSString *manaCost;
@property (nonatomic, readonly) NSNumber *cmc;
@property (nonatomic, copy, readonly, nullable) NSArray<NSString *> *colors;
@property (nonatomic, copy, readonly) NSString *type;
@property (nonatomic, copy, readonly, nullable) NSArray<NSString *> *supertypes;
@property (nonatomic, copy, readonly) NSArray<NSString *> *types;
@property (nonatomic, copy, readonly, nullable) NSArray<NSString *> *subtypes;
@property (nonatomic, copy, readonly) NSString *rarity;
@property (nonatomic, copy, readonly, nullable) NSString *text;
@property (nonatomic, copy, readonly, nullable) NSString *flavor;
@property (nonatomic, copy, readonly) NSString *artist;
@property (nonatomic, copy, readonly, nullable) NSString *number;
@property (nonatomic, copy, readonly, nullable) NSString *power;
@property (nonatomic, copy, readonly, nullable) NSString *toughness;
@property (nonatomic, copy, readonly, nullable) NSString *loyalty;
@property (nonatomic, readonly, nullable) NSNumber *multiverseID;
@property (nonatomic, readonly, nullable) NSArray<NSNumber *> *variations;
@property (nonatomic, readonly, nullable) NSString *watermark;
@property (nonatomic, readonly, nullable) NSString *border;
@property (nonatomic, readonly, getter=isTimeshifted) BOOL timeshifted;
@property (nonatomic, readonly, nullable) NSNumber *hand;
@property (nonatomic, readonly, nullable) NSNumber *life;
@property (nonatomic, readonly, getter=isReserved) BOOL reserved;
@property (nonatomic, readonly) ReleaseDateKind releaseDateKind;
@property (nonatomic, readonly, nullable) NSDateComponents *releaseDate;
@property (nonatomic, readonly, getter=isStarter) BOOL starter;

- (nullable instancetype)initWithDictionary:(NSDictionary<NSString *, id> *)dictionary NS_DESIGNATED_INITIALIZER;
@property (nonatomic, copy) NSDictionary<NSString *, id> *dictionaryValue;

@end

NS_ASSUME_NONNULL_END
119 changes: 119 additions & 0 deletions BNRSwiftJSONTests/Card.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//
// Card.m
// BNRSwiftJSON
//
// Created by Zachary Waldowski on 5/20/15.
// Copyright (c) 2015 Big Nerd Ranch Inc. All rights reserved.
//

#import "Card.h"
#import "CardUtilities.h"

@implementation CardObjC

- (instancetype)init {
return (self = [self initWithDictionary:@{}]);
}

- (nullable instancetype)initWithDictionary:(NSDictionary *)dict {
self = [super init];
if (!self) { return nil; }

id(^forceUnwrap)(NSString *) = ^(NSString *key){
id ret = dict[key];
NSAssert(ret != nil, @"Unexpectedly found nil while fetching value for %@", key);
return ret;
};

_layout = forceUnwrap(@"layout");
_name = forceUnwrap(@"name");
_manaCost = dict[@"manaCost"] ?: @"";
_cmc = dict[@"cmc"] ?: @0;
_colors = dict[@"colors"];
_type = forceUnwrap(@"type");
_supertypes = dict[@"supertypes"];
_types = dict[@"types"] ?: @[];
_subtypes = dict[@"subtypes"];
_rarity = forceUnwrap(@"rarity");
_text = dict[@"text"];
_flavor = dict[@"flavor"];
_artist = forceUnwrap(@"artist");
_number = dict[@"number"];
_power = dict[@"power"];
_toughness = dict[@"toughness"];
_loyalty = dict[@"loyalty"];
_multiverseID = dict[@"multiverseid"];
_variations = dict[@"variations"];
_watermark = dict[@"watermark"];
_border = dict[@"border"];
if ([dict[@"timeshifted"] boolValue]) {
_timeshifted = YES;
}
_hand = dict[@"hand"];
_life = dict[@"life"];
if ([dict[@"reserved"] boolValue]) {
_reserved = YES;
}
_releaseDate = ReleaseDateFromString(dict[@"releaseDate"], &_releaseDateKind);
if ([dict[@"starter"] boolValue]) {
_starter = YES;
}

return self;
}

- (NSDictionary *)dictionaryValue {
NSMutableDictionary *result = NSMutableDictionary.new;

BOOL(^setIfNotNil)(NSString *, id) = ^(NSString *key, id value) {
if (value == nil) {
return NO;
}
result[key] = value;
return YES;
};

BOOL(^setIfTrue)(NSString *, BOOL) = ^(NSString *key, BOOL value) {
if (!value) {
return NO;
}
result[key] = value ? @YES : @NO;
return YES;
};

result[@"layout"] = self.layout;
result[@"name"] = self.name;
if (self.manaCost.length != 0) {
result[@"manaCost"] = self.manaCost;
result[@"cmc"] = self.cmc;
}
setIfNotNil(@"colors", self.colors);
result[@"type"] = self.type;
setIfNotNil(@"supertypes", self.supertypes);
if (self.types.count != 0) {
result[@"types"] = self.types;
}
setIfNotNil(@"subtypes", self.subtypes);
result[@"rarity"] = self.rarity;
setIfNotNil(@"text", self.text);
setIfNotNil(@"flavor", self.flavor);
result[@"artist"] = self.artist;
setIfNotNil(@"number", self.number);
setIfNotNil(@"power", self.power);
setIfNotNil(@"toughness", self.toughness);
setIfNotNil(@"loyalty", self.loyalty);
setIfNotNil(@"multiverseid", self.multiverseID);
setIfNotNil(@"variations", self.variations);
setIfNotNil(@"watermark", self.watermark);
setIfNotNil(@"border", self.border);
setIfTrue(@"timeshifted", self.timeshifted);
setIfNotNil(@"hand", self.hand);
setIfNotNil(@"life", self.life);
setIfTrue(@"reserved", self.reserved);
setIfNotNil(@"releaseDate", ReleaseDateToString(self.releaseDate, self.releaseDateKind));
setIfTrue(@"starter", self.starter);

return result;
}

@end
77 changes: 77 additions & 0 deletions BNRSwiftJSONTests/Card.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// Card.swift
// BNRSwiftJSON
//
// Created by Zachary Waldowski on 5/19/15.
// Copyright (c) 2015 Big Nerd Ranch Inc. Licensed under MIT.
//

import BNRSwiftJSON

struct Card {

let layout: String
let name: String
let manaCost: String
let cmc: Int
let colors: [String]?
let type: String
let supertypes: [String]?
let types: [String]
let subtypes: [String]?
let rarity: String
let text: String?
let flavor: String?
let artist: String
let number: String?
let power: String?
let toughness: String?
let loyalty: Int?
let multiverseID: Int?
let variations: [Int]?
let watermark: String?
let border: String?
let isTimeshifted: Bool
let hand: Int?
let life: Int?
let isReserved: Bool
let releaseDate: ReleaseDate?
let isStarter: Bool

}

// MARK: - BNRSwiftJSON-style

extension Card: JSONDecodable {

init(json: BNRSwiftJSON.JSON) throws {
layout = try json.decode("layout")
name = try json.decode("name")
manaCost = try json.decode("manaCost", or: "")
cmc = try json.decode("cmc", or: 0)
colors = try json.arrayOf("colors", ifNotFound: true)
type = try json.decode("type")
supertypes = try json.arrayOf("supertypes", ifNotFound: true)
types = try json.arrayOf("types", or: [])
subtypes = try json.arrayOf("subtypes", ifNotFound: true)
rarity = try json.decode("rarity")
text = try json.decode("text", ifNotFound: true)
flavor = try json.decode("flavor", ifNotFound: true)
artist = try json.decode("artist")
number = try json.decode("number", ifNotFound: true)
power = try json.decode("power", ifNotFound: true)
toughness = try json.decode("toughness", ifNotFound: true)
loyalty = try json.decode("loyalty", ifNotFound: true)
multiverseID = try json.decode("multiverseid", ifNotFound: true)
variations = try json.arrayOf("variations", ifNotFound: true)
watermark = try json.decode("watermark", ifNotFound: true)
border = try json.decode("border", ifNotFound: true)
isTimeshifted = try json.decode("timeshifted", or: false)
hand = try json.decode("hand", ifNotFound: true)
life = try json.decode("life", ifNotFound: true)
isReserved = try json.decode("reserved", or: false)
releaseDate = try json.decode("releaseDate", ifNotFound: true)
isStarter = try json.decode("starter", or: false)
}

}
Loading