Skip to content

Instantly share code, notes, and snippets.

@faultier
Created April 22, 2010 01:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save faultier/374671 to your computer and use it in GitHub Desktop.
Save faultier/374671 to your computer and use it in GitHub Desktop.
*.swp
.DS_Store
*.o
array_map
thread_test
concurrent
string_benchmark
#import <Foundation/Foundation.h>
#import "NSArrayMap.h"
int main(int argc, char **argv) {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSArrayMapper block = ^ id (id item) {
return [NSString stringWithFormat:@"My name is %@ since yesterday.",item];
};
NSArray *array = [NSArray arrayWithObjects:@"Sato",@"Ito",@"Kato",@"Naito",@"Saemonsaburo",nil];
NSLog(@"\n%@", array);
NSLog(@"\n%@", [array mapUsingBlock:block]);
[pool drain];
return 0;
}
// vim: ft=objc ff=unix fenc=utf-8 ts=2 sts=2 sw=2 expandtab :
#!/usr/bin/env ruby
# coding: utf-8
require 'pp'
array = %w(ひたぎ 真宵 駿河 撫子 )
pp array
pp array.map {|item|
"#{item}が好きすぎて生きるのが辛い"
}
#import <Foundation/Foundation.h>
typedef void (^Benchmarker)(void);
typedef enum {
BenchmarkFormatTime,
BenchmarkFormatCompare,
} BenchmarkFormat;
@interface Benchmark : NSObject
{ // attributes
@private
NSUInteger iterations_;
BenchmarkFormat format_;
NSMutableDictionary *targets_;
}
@property (assign) NSUInteger iterations;
@property (assign) BenchmarkFormat format;
@property (readonly) NSDictionary *targets;
+ (void)benchmarkWithTargets:(NSDictionary *)targets;
- (id)initWithTargets:(NSDictionary *)targets iterations:(NSUInteger)iterations;
- (id)initWithTargets:(NSDictionary *)targets;
- (void)setTarget:(Benchmarker)block forName:(NSString *)name;
- (void)benchmark;
- (void)clear;
@end
// vim: set ft=objc ff=unix fenc=utf-8 ts=2 sts=2 sw=2 expandtab :
#import "Benchmark.h"
#define _FloatToNumber(f) [NSNumber numberWithFloat:f]
static NSUInteger _defaultIterations = 10000;
@implementation Benchmark
@synthesize iterations = iterations_;
@synthesize format = format_;
@synthesize targets = targets_;
+ (void)benchmarkWithTargets:(NSDictionary *)targets {
Benchmark *b = [[Benchmark alloc] initWithTargets:targets];
[b benchmark];
[b release];
}
- (id)initWithTargets:(NSDictionary *)targets iterations:(NSUInteger)iterations {
if ((self = [super init])) {
iterations_ = iterations;
format_ = BenchmarkFormatTime;
targets_ = [targets retain];
}
return self;
}
- (id)initWithTargets:(NSDictionary *)targets {
return [self initWithTargets:targets iterations:_defaultIterations];
}
- (id)init {
return [self initWithTargets:[NSMutableDictionary dictionary] iterations:_defaultIterations];
}
- (void)dealloc {
[targets_ release];
[super dealloc];
}
- (void)setTarget:(Benchmarker)block forName:(NSString *)name {
[targets_ setObject:block forKey:name];
}
- (void)benchmark {
NSMutableDictionary *results = [NSMutableDictionary dictionary];
for (id key in [targets_ keyEnumerator]) {
Benchmarker bench = (Benchmarker)[targets_ objectForKey:key];
__block NSTimeInterval total = 0;
__block NSTimeInterval max = 0;
__block NSTimeInterval min = 0;
void (^job)(void) = ^{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSDate *d = [NSDate date];
bench();
NSTimeInterval time = [[NSDate date] timeIntervalSinceDate:d];
total += time;
max = (max > time) ? max : time;
min = (min > 0 && min < time) ? min : time;
[pool drain];
};
NSUInteger i = self.iterations;
while (i--) {
job();
}
NSTimeInterval avg = total / self.iterations;
NSArray *res = [NSArray arrayWithObjects:
_FloatToNumber(total),
_FloatToNumber(max),
_FloatToNumber(min),
_FloatToNumber(avg),
nil];
[results setObject:res forKey:key];
}
NSUInteger keyLen = 0;
for (NSString *key in [results keyEnumerator]) {
keyLen = ([key length] > keyLen) ? [key length] : keyLen;
}
NSString *format = [NSString stringWithFormat:@"%%-%d%s", (keyLen+1), "s"];
NSArray *keys = [results keysSortedByValueUsingComparator:
^(id a, id b) { return [[(NSArray *)a objectAtIndex:0] compare:[(NSArray *)b objectAtIndex:0]]; }
];
switch (self.format) {
case BenchmarkFormatTime:
printf([[NSString stringWithFormat:@"%%-%d%s %%10s %%10s %%10s %%10s\n", (keyLen+1), "s"] UTF8String],
"",
"total",
"max",
"min",
"avg");
[keys enumerateObjectsUsingBlock:
^(id key, NSUInteger idx, BOOL* stop) {
NSArray *r = (NSArray *)[results objectForKey:key];
printf([format UTF8String], [key UTF8String]);
for (NSNumber *t in r) {
printf(" % 3.7f", [t floatValue]);
}
puts("");
}
];
break;
case BenchmarkFormatCompare:
[keys enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:
^(id key, NSUInteger idx, BOOL* stop) {
NSTimeInterval r = [[(NSArray *)[results objectForKey:key] objectAtIndex:0] floatValue];
printf([format UTF8String], [key UTF8String]);
printf("%7.0f/s", self.iterations * (1 / r));
[keys enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:
^(id key2, NSUInteger idx2, BOOL* stop2) {
if ([key2 isEqualToString:key]) {
printf(" ---");
}
else {
NSTimeInterval r2 = [[(NSArray *)[results objectForKey:key2] objectAtIndex:0] floatValue];
float comp = ((r2 / r - 1.00) * 100);
printf(" %6.0f%%", comp);
}
}
];
puts("");
}
];
break;
}
}
- (void)clear {
[targets_ release];
targets_ = [[NSMutableDictionary alloc] init];
}
@end
// vim: set ft=objc ff=unix fenc=utf-8 ts=2 sts=2 sw=2 expandtab :
#import <Foundation/Foundation.h>
void testSequential(unsigned int times, dispatch_block_t block) {
unsigned int i;
for (i = 0; i < times; i++) {
block();
}
}
void testDispatchAsync(unsigned int times, dispatch_block_t block) {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
unsigned int i;
for (i = 0; i < times; i++) {
dispatch_group_async(group, queue, block);
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}
void testOperation(unsigned int times, dispatch_block_t block) {
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
unsigned int i;
for (i = 0; i < times; i++) {
[queue addOperationWithBlock:block];
}
[queue waitUntilAllOperationsAreFinished];
}
int main(int argc, char **argv) {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
dispatch_block_t block = [[^{
NSLog(@"あと0.25秒だけ寝させてー");
[NSThread sleepForTimeInterval:0.25];
// NSLog(@"%@", [NSThread currentThread];
} copy] autorelease];
// NSLog(@"%@", [NSThread currentThread]);
NSDate *d1, *d2, *d3;
NSTimeInterval t1, t2, t3;
NSLog(@"----- start sequential -----");
d1 = [NSDate date];
testSequential(20, block);
t1 = [[NSDate date] timeIntervalSinceDate:d1];
NSLog(@"------ end sequential ------");
NSLog(@"--- start dispatch async ---");
d2 = [NSDate date];
testDispatchAsync(20, block);
t2 = [[NSDate date] timeIntervalSinceDate:d2];
NSLog(@"---- end dispatch async ----");
NSLog(@"----- start operation ------");
d3 = [NSDate date];
testOperation(20, block);
t3 = [[NSDate date] timeIntervalSinceDate:d3];
NSLog(@"------ end operation -------");
puts("");
NSLog(@"sequential %f sec", t1);
NSLog(@"dispatch async %f sec", t2);
NSLog(@"operation %f sec", t3);
[pool drain];
return 0;
}
// vim: ft=objc ff=unix fenc=utf-8 ts=2 sts=2 sw=2 expandtab :
#!/usr/bin/env ruby
# coding: utf-8
def do_sequential(n, f)
n.times do
f.call
end
end
def do_thread(n, f)
n.times do
Thread.new { f.call }
end
(ThreadGroup::Default.list - [Thread.current]).each{|th| th.join }
end
b = lambda {
puts "0.25秒後から本気出す"
sleep 0.25
}
puts "----- start sequential -----"
t1 = Time.now
do_sequential 20, b
t1 = Time.now - t1
puts "------ end sequential ------"
puts "------- start thread -------"
t2 = Time.now
do_thread 20, b
t2 = Time.now - t2
puts "-------- end thread --------"
puts ""
puts "sequential #{t1} sec"
puts "thread #{t2} sec"
#import <Foundation/Foundation.h>
typedef id (^NSArrayMapper)(id);
@interface NSArray (NSArrayMap)
- (NSArray *)mapUsingBlock:(NSArrayMapper)block;
- (NSArray *)mapUsingBlock:(NSArrayMapper)block concurrent:(BOOL)yesOrNo;
@end
// vim: ft=objc ff=unix fenc=utf-8 ts=2 sts=2 sw=2 expandtab :
#import "NSArrayMap.h"
@implementation NSArray (NSArrayMap)
- (NSArray *)mapUsingBlock:(NSArrayMapper)block {
return [self mapUsingBlock:block concurrent:NO];
}
- (NSArray *)mapUsingBlock:(NSArrayMapper)block concurrent:(BOOL)concurrent {
NSMutableArray *mapped = [self mutableCopy];
void (^mapBlock)(id,NSUInteger,BOOL*) =
^(id item, NSUInteger idx, BOOL *stop) {
id obj = block(item);
[mapped replaceObjectAtIndex:idx withObject:obj];
};
if (concurrent) {
[self enumerateObjectsWithOptions:NSEnumerationConcurrent
usingBlock:mapBlock];
} else {
[self enumerateObjectsUsingBlock:mapBlock];
}
return [mapped autorelease];
}
@end
// vim: set ft=objc ff=unix fenc=utf-8 ts=2 sts=2 sw=2 expandtab :
# vim: set fileencoding=utf-8 filetype=ruby
require 'rake/clean'
FRAMEWORKS = %w(Foundation)
PROGS = %w(array_map thread_test concurrent string_benchmark)
CLEAN.include('*.o', PROGS)
task :default => :build
task :build => PROGS
file 'array_map' => %w(array_map.m NSArrayMap.o) do |t|
sh "gcc #{FRAMEWORKS.map{|f| "-framework #{f}"}.join(' ')} -o #{t} #{t.prerequisites.join(' ')}"
end
file 'thread_test' => %w(thread_test.m) do |t|
sh "gcc #{FRAMEWORKS.map{|f| "-framework #{f}"}.join(' ')} -o #{t} #{t.prerequisites.join(' ')}"
end
file 'concurrent' => %w(concurrent.m) do |t|
sh "gcc #{FRAMEWORKS.map{|f| "-framework #{f}"}.join(' ')} -o #{t} #{t.prerequisites.join(' ')}"
end
file 'string_benchmark' => %w(string_benchmark.m Benchmark.o) do |t|
sh "gcc #{FRAMEWORKS.map{|f| "-framework #{f}"}.join(' ')} -o #{t} #{t.prerequisites.join(' ')}"
end
rule '.o' => %w(.m .h) do |t|
sh "gcc -x objective-c -c -o #{t} #{t.source}"
end
#import <Foundation/Foundation.h>
#import "Benchmark.h"
int main(int argc, char **argv) {
NSAutoreleasePool *pool = [NSAutoreleasePool new];
int n = 100;
NSString *str = @"またお前か";
const char *cStr = [str UTF8String];
BenchmarkFormat format = (argc > 1 && strcmp(argv[1],"--compare") == 0) ? BenchmarkFormatCompare : BenchmarkFormatTime;
Benchmarker b1 = [[^{
size_t len = strlen(cStr) - 1;
char *buff = (char *)malloc((len * n + 1) * sizeof(char));
buff[0] = '\0';
unsigned int i = n;
while (i--) {
strncat(buff,cStr,len);
}
free(buff);
} copy] autorelease];
Benchmarker b2 = [[^{
NSString *buff = [NSString string];
unsigned int i = n;
while (i--) {
buff = [NSString stringWithFormat:@"%@%@", buff, str];
}
} copy] autorelease];
Benchmarker b3 = [[^{
NSMutableString *buff = [NSMutableString string];
unsigned int i = n;
while (i--) {
[buff appendString:str];
}
} copy] autorelease];
Benchmark *bm = [Benchmark new];
[bm setFormat:format];
[bm setTarget:b1 forName:@"C String"];
[bm setTarget:b2 forName:@"NSString"];
[bm setTarget:b3 forName:@"NSMutableString"];
[bm benchmark];
[pool release];
return 0;
}
// vim: ft=objc ff=unix fenc=utf-8 ts=2 sts=2 sw=2 expandtab :
#import <Foundation/Foundation.h>
@interface Runner : NSObject {
}
- (void)run;
@end
@implementation Runner
- (void)run {
NSLog(@"あと0.25秒だけ寝させてー");
[NSThread sleepForTimeInterval:0.25];
//[NSThread exit];
}
@end
int main(int argc, char **argv) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Runner *runner = [[Runner alloc] init];
unsigned int i;
NSLog(@"using NSThread -------------");
NSMutableArray *group = [NSMutableArray array];
i = 20;
while (i--) {
NSThread *t = [[NSThread alloc] initWithTarget:runner
selector:@selector(run)
object:nil];
[group addObject:t];
[t start];
[t autorelease];
}
for (NSThread *t in group) {
while ([t isExecuting]) {
// 本当は単に
// [NSThread sleepForTimeInterval:0.01];
// とかしてメインスレッドで子スレッドの終了を待つだけの処理のつもり。
// このコードだとRunLoopが回ってないので、
// NSThreadとかNSTimerとかが動いてくれないので、
// とりあえずrunUntilDateでRunLoopを回してごまかす。
[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.01]];
}
}
puts("");
NSLog(@"using NSOperationQueue -----");
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
i = 20;
while (i--) {
NSOperation *op = [[NSInvocationOperation alloc] initWithTarget:runner
selector:@selector(run)
object:nil];
[queue addOperation:op];
[op autorelease];
}
[queue waitUntilAllOperationsAreFinished];
[queue release];
[runner release];
[pool release];
return 0;
}
// vim: set ft=objc fenc=utf-8 ts=2 sts=2 sw=2 expandtab :
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment