init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled
This commit is contained in:
728
Telegram/ThirdParty/dispatch/tests/Foundation/bench.mm
vendored
Normal file
728
Telegram/ThirdParty/dispatch/tests/Foundation/bench.mm
vendored
Normal file
@@ -0,0 +1,728 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
#ifdef __ANDROID__
|
||||
#include <linux/sysctl.h>
|
||||
#else
|
||||
#if !defined(__linux__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#endif /* __ANDROID__ */
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#ifdef __BLOCKS__
|
||||
#include <Block.h>
|
||||
#endif
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <dispatch/private.h>
|
||||
|
||||
//#define BENCH_SLOW 1
|
||||
|
||||
extern "C" {
|
||||
__private_extern__ void func(void);
|
||||
#ifdef __BLOCKS__
|
||||
__private_extern__ void (^block)(void);
|
||||
#endif
|
||||
static void backflip(void *ctxt);
|
||||
static void backflip_done(void);
|
||||
}
|
||||
|
||||
@interface BasicObject : NSObject
|
||||
{
|
||||
}
|
||||
- (void) method;
|
||||
@end
|
||||
|
||||
@implementation BasicObject
|
||||
- (void) method
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
class BasicClass {
|
||||
public:
|
||||
virtual void virtfunc(void) {
|
||||
};
|
||||
};
|
||||
|
||||
static void *
|
||||
force_a_thread(void *arg)
|
||||
{
|
||||
pause();
|
||||
abort();
|
||||
return arg;
|
||||
}
|
||||
|
||||
static volatile int32_t global;
|
||||
static volatile int64_t w_global;
|
||||
|
||||
#if TARGET_OS_EMBEDDED
|
||||
static const size_t cnt = 5000000;
|
||||
#else
|
||||
static const size_t cnt = 200000000;
|
||||
#endif
|
||||
static const size_t cnt2 = cnt/100;
|
||||
|
||||
static uint64_t bfs;
|
||||
static long double loop_cost;
|
||||
static long double cycles_per_nanosecond;
|
||||
static mach_timebase_info_data_t tbi;
|
||||
|
||||
static void __attribute__((noinline))
|
||||
print_result(uint64_t s, const char *str)
|
||||
{
|
||||
uint64_t d, e = mach_absolute_time();
|
||||
long double dd;
|
||||
|
||||
d = e - s;
|
||||
|
||||
if (tbi.numer != tbi.denom) {
|
||||
d *= tbi.numer;
|
||||
d /= tbi.denom;
|
||||
}
|
||||
|
||||
dd = (__typeof__(dd))d / (__typeof__(dd))cnt;
|
||||
|
||||
dd -= loop_cost;
|
||||
|
||||
if (loop_cost == 0.0) {
|
||||
loop_cost = dd;
|
||||
}
|
||||
|
||||
dd *= cycles_per_nanosecond;
|
||||
dd = roundl(dd * 200.0)/200.0;
|
||||
|
||||
printf("%-45s%15.3Lf cycles\n", str, dd);
|
||||
}
|
||||
|
||||
#if BENCH_SLOW || !TARGET_OS_EMBEDDED
|
||||
static void __attribute__((noinline))
|
||||
print_result2(uint64_t s, const char *str)
|
||||
{
|
||||
uint64_t d, e = mach_absolute_time();
|
||||
long double dd;
|
||||
|
||||
d = e - s;
|
||||
|
||||
if (tbi.numer != tbi.denom) {
|
||||
d *= tbi.numer;
|
||||
d /= tbi.denom;
|
||||
}
|
||||
|
||||
dd = (__typeof__(dd))d / (__typeof__(dd))cnt2;
|
||||
|
||||
dd -= loop_cost;
|
||||
dd *= cycles_per_nanosecond;
|
||||
|
||||
printf("%-45s%15.3Lf cycles\n", str, dd);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
static inline uint64_t
|
||||
rdtsc(void)
|
||||
{
|
||||
uint32_t lo, hi;
|
||||
|
||||
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
|
||||
|
||||
return (uint64_t)hi << 32 | lo;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct fml {
|
||||
struct fml *fml_next;
|
||||
} *fixed_malloc_lifo_head;
|
||||
|
||||
struct fml *fixed_malloc_lifo(void);// __attribute__((noinline));
|
||||
void fixed_free_lifo(struct fml *fml);// __attribute__((noinline));
|
||||
|
||||
struct fml *
|
||||
fixed_malloc_lifo(void)
|
||||
{
|
||||
struct fml *fml_r = fixed_malloc_lifo_head;
|
||||
|
||||
if (fml_r) {
|
||||
fixed_malloc_lifo_head = fml_r->fml_next;
|
||||
return fml_r;
|
||||
} else {
|
||||
return (struct fml *)malloc(32);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fixed_free_lifo(struct fml *fml)
|
||||
{
|
||||
fml->fml_next = fixed_malloc_lifo_head;
|
||||
fixed_malloc_lifo_head = fml;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
pthread_mutex_t plock = PTHREAD_MUTEX_INITIALIZER;
|
||||
OSSpinLock slock = OS_SPINLOCK_INIT;
|
||||
BasicObject *bo;
|
||||
BasicClass *bc;
|
||||
pthread_t pthr_pause;
|
||||
dispatch_queue_t q, mq;
|
||||
kern_return_t kr;
|
||||
#if BENCH_SLOW
|
||||
semaphore_t sem;
|
||||
#endif
|
||||
uint64_t freq;
|
||||
uint64_t s;
|
||||
size_t freq_len = sizeof(freq);
|
||||
size_t bf_cnt = cnt;
|
||||
unsigned i;
|
||||
int r;
|
||||
|
||||
printf("\n====================================================================\n");
|
||||
printf("[TEST] dispatch benchmark\n");
|
||||
printf("[PID] %d\n", getpid());
|
||||
printf("====================================================================\n\n");
|
||||
|
||||
r = sysctlbyname("hw.cpufrequency", &freq, &freq_len, NULL, 0);
|
||||
assert(r != -1);
|
||||
assert(freq_len == sizeof(freq));
|
||||
|
||||
cycles_per_nanosecond = (long double)freq / (long double)NSEC_PER_SEC;
|
||||
|
||||
#if BENCH_SLOW
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
assert(pool);
|
||||
#endif
|
||||
|
||||
/* Malloc has different logic for threaded apps. */
|
||||
r = pthread_create(&pthr_pause, NULL, force_a_thread, NULL);
|
||||
assert(r == 0);
|
||||
|
||||
kr = mach_timebase_info(&tbi);
|
||||
assert(kr == 0);
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
assert(tbi.numer == tbi.denom); /* This will fail on PowerPC. */
|
||||
#endif
|
||||
|
||||
bo = [[BasicObject alloc] init];
|
||||
assert(bo);
|
||||
|
||||
bc = new BasicClass();
|
||||
assert(bc);
|
||||
|
||||
q = dispatch_queue_create("com.apple.bench-dispatch", NULL);
|
||||
assert(q);
|
||||
|
||||
mq = dispatch_get_main_queue();
|
||||
assert(mq);
|
||||
|
||||
printf("%-45s%15Lf\n\n", "Cycles per nanosecond:", cycles_per_nanosecond);
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__asm__ __volatile__ ("");
|
||||
}
|
||||
print_result(s, "Empty loop:");
|
||||
|
||||
printf("\nLoop cost subtracted from the following:\n\n");
|
||||
|
||||
#if TARGET_OS_EMBEDDED
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
mach_absolute_time();
|
||||
}
|
||||
print_result(s, "mach_absolute_time():");
|
||||
#else
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt2; i; i--) {
|
||||
mach_absolute_time();
|
||||
}
|
||||
print_result2(s, "mach_absolute_time():");
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
rdtsc();
|
||||
}
|
||||
print_result(s, "rdtsc():");
|
||||
#endif
|
||||
|
||||
#if BENCH_SLOW
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt2; i; i--) {
|
||||
pthread_t pthr;
|
||||
void *pr;
|
||||
|
||||
r = pthread_create(&pthr, NULL, (void *(*)(void *))func, NULL);
|
||||
assert(r == 0);
|
||||
r = pthread_join(pthr, &pr);
|
||||
assert(r == 0);
|
||||
}
|
||||
print_result2(s, "pthread create+join:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt2; i; i--) {
|
||||
kr = semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, 0);
|
||||
assert(kr == 0);
|
||||
kr = semaphore_destroy(mach_task_self(), sem);
|
||||
assert(kr == 0);
|
||||
}
|
||||
print_result2(s, "Mach semaphore create/destroy:");
|
||||
|
||||
kr = semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, 0);
|
||||
assert(kr == 0);
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt2; i; i--) {
|
||||
kr = semaphore_signal(sem);
|
||||
assert(kr == 0);
|
||||
}
|
||||
print_result2(s, "Mach semaphore signal:");
|
||||
kr = semaphore_destroy(mach_task_self(), sem);
|
||||
assert(kr == 0);
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
free(malloc(32));
|
||||
}
|
||||
print_result(s, "free(malloc(32)):");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt / 2; i; i--) {
|
||||
void *m1 = malloc(32);
|
||||
void *m2 = malloc(32);
|
||||
free(m1);
|
||||
free(m2);
|
||||
}
|
||||
print_result(s, "Avoiding the MRU cache of free(malloc(32)):");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
fixed_free_lifo(fixed_malloc_lifo());
|
||||
}
|
||||
print_result(s, "per-thread/fixed free(malloc(32)):");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
assert(strtoull("18446744073709551615", NULL, 0) == ~0ull);
|
||||
}
|
||||
print_result(s, "strtoull(\"18446744073709551615\") == ~0ull:");
|
||||
#endif
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
func();
|
||||
}
|
||||
print_result(s, "Empty function call:");
|
||||
|
||||
#ifdef __BLOCKS__
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
block();
|
||||
}
|
||||
print_result(s, "Empty block call:");
|
||||
#endif
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
bc->virtfunc();
|
||||
}
|
||||
print_result(s, "Empty C++ virtual call:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
[bo method];
|
||||
}
|
||||
print_result(s, "Empty ObjC call:");
|
||||
|
||||
#if BENCH_SLOW
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt2; i; i--) {
|
||||
[bo description];
|
||||
}
|
||||
print_result2(s, "\"description\" ObjC call:");
|
||||
|
||||
[pool release];
|
||||
|
||||
pool = NULL;
|
||||
#endif
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__asm__ __volatile__ ("nop");
|
||||
}
|
||||
print_result(s, "raw 'nop':");
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__asm__ __volatile__ ("pause");
|
||||
}
|
||||
print_result(s, "raw 'pause':");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__asm__ __volatile__ ("mfence");
|
||||
}
|
||||
print_result(s, "Atomic mfence:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__asm__ __volatile__ ("lfence");
|
||||
}
|
||||
print_result(s, "Atomic lfence:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__asm__ __volatile__ ("sfence");
|
||||
}
|
||||
print_result(s, "Atomic sfence:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
uint64_t sidt_rval;
|
||||
__asm__ __volatile__ ("sidt %0" : "=m" (sidt_rval));
|
||||
}
|
||||
print_result(s, "'sidt' instruction:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
long prev;
|
||||
__asm__ __volatile__ ("cmpxchg %1,%2"
|
||||
: "=a" (prev) : "r" (0l), "m" (global), "0" (1l));
|
||||
}
|
||||
print_result(s, "'cmpxchg' without the 'lock' prefix:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
global = 0;
|
||||
__asm__ __volatile__ ("mfence" ::: "memory");
|
||||
}
|
||||
print_result(s, "Store + mfence:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
unsigned long _clbr;
|
||||
#ifdef __LP64__
|
||||
__asm__ __volatile__ ("cpuid" : "=a" (_clbr)
|
||||
: "0" (0) : "rbx", "rcx", "rdx", "cc", "memory");
|
||||
#else
|
||||
#ifdef __llvm__
|
||||
__asm__ __volatile__ ("cpuid" : "=a" (_clbr) : "0" (0)
|
||||
: "ebx", "ecx", "edx", "cc", "memory" );
|
||||
#else // gcc does not allow inline i386 asm to clobber ebx
|
||||
__asm__ __volatile__ ("pushl %%ebx\n\tcpuid\n\tpopl %%ebx"
|
||||
: "=a" (_clbr) : "0" (0) : "ecx", "edx", "cc", "memory" );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
print_result(s, "'cpuid' instruction:");
|
||||
|
||||
#elif defined(__arm__)
|
||||
|
||||
#include <arm/arch.h>
|
||||
|
||||
#if !defined(_ARM_ARCH_7) && defined(__thumb__)
|
||||
#error "GCD requires instructions unvailable in ARMv6 Thumb1"
|
||||
#endif
|
||||
|
||||
#ifdef _ARM_ARCH_7
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__asm__ __volatile__ ("yield");
|
||||
}
|
||||
print_result(s, "raw 'yield':");
|
||||
#endif
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
#ifdef _ARM_ARCH_7
|
||||
__asm__ __volatile__ ("dmb ish" : : : "memory");
|
||||
#else
|
||||
__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory");
|
||||
#endif
|
||||
}
|
||||
print_result(s, "'dmb ish' instruction:");
|
||||
|
||||
#ifdef _ARM_ARCH_7
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__asm__ __volatile__ ("dmb ishst" : : : "memory");
|
||||
}
|
||||
print_result(s, "'dmb ishst' instruction:");
|
||||
#endif
|
||||
|
||||
#ifdef _ARM_ARCH_7
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__asm__ __volatile__ ("str %[_r], [%[_p], %[_o]]" :
|
||||
: [_p] "p" (&global), [_o] "M" (0), [_r] "r" (0) : "memory");
|
||||
__asm__ __volatile__ ("dmb ishst" : : : "memory");
|
||||
}
|
||||
print_result(s, "'str + dmb ishst' instructions:");
|
||||
#endif
|
||||
|
||||
#ifdef _ARM_ARCH_7
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
uintptr_t prev;
|
||||
uint32_t t;
|
||||
do {
|
||||
__asm__ __volatile__ ("ldrex %[_r], [%[_p], %[_o]]"
|
||||
: [_r] "=&r" (prev) \
|
||||
: [_p] "p" (&global), [_o] "M" (0) : "memory");
|
||||
__asm__ __volatile__ ("strex %[_t], %[_r], [%[_p], %[_o]]"
|
||||
: [_t] "=&r" (t) \
|
||||
: [_p] "p" (&global), [_o] "M" (0), [_r] "r" (0) : "memory");
|
||||
} while (t);
|
||||
}
|
||||
print_result(s, "'ldrex + strex' instructions:");
|
||||
#endif
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
#ifdef _ARM_ARCH_7
|
||||
__asm__ __volatile__ ("dsb ish" : : : "memory");
|
||||
#else
|
||||
__asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory");
|
||||
#endif
|
||||
}
|
||||
print_result(s, "'dsb ish' instruction:");
|
||||
|
||||
#if BENCH_SLOW
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
register long _swtch_pri __asm__("ip") = -59;
|
||||
__asm__ __volatile__ ("svc 0x80" : : "r" (_swtch_pri) : "r0", "memory");
|
||||
}
|
||||
print_result(s, "swtch_pri syscall:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
register long _r0 __asm__("r0") = 0, _r1 __asm__("r1") = 1, _r2 __asm__("r2") = 1;
|
||||
register long _thread_switch __asm__("ip") = -61;
|
||||
__asm__ __volatile__ ("svc 0x80" : "+r" (_r0)
|
||||
: "r" (_r1), "r" (_r2), "r" (_thread_switch): "memory");
|
||||
}
|
||||
print_result(s, "thread_switch syscall:");
|
||||
#endif
|
||||
|
||||
#endif // __arm__
|
||||
|
||||
#if BENCH_SLOW
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
pthread_yield_np();
|
||||
}
|
||||
print_result(s, "pthread_yield_np():");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt2; i; i--) {
|
||||
usleep(0);
|
||||
}
|
||||
print_result2(s, "usleep(0):");
|
||||
#endif
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__sync_lock_test_and_set(&global, 0);
|
||||
}
|
||||
print_result(s, "Atomic xchg:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__sync_val_compare_and_swap(&global, 1, 0);
|
||||
}
|
||||
print_result(s, "Atomic cmpxchg:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
__sync_fetch_and_add(&global, 1);
|
||||
}
|
||||
print_result(s, "Atomic increment:");
|
||||
|
||||
{
|
||||
global = 0;
|
||||
volatile int32_t *g = &global;
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
uint32_t result;
|
||||
__sync_and_and_fetch(g, 1);
|
||||
result = *g;
|
||||
if (result) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
print_result(s, "Atomic and-and-fetch, reloading result:");
|
||||
}
|
||||
|
||||
{
|
||||
global = 0;
|
||||
volatile int32_t *g = &global;
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
uint32_t result;
|
||||
result = __sync_and_and_fetch(g, 1);
|
||||
if (result) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
print_result(s, "Atomic and-and-fetch, using result:");
|
||||
}
|
||||
|
||||
global = 0;
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
OSAtomicIncrement32Barrier(&global);
|
||||
}
|
||||
print_result(s, "OSAtomicIncrement32Barrier:");
|
||||
|
||||
global = 0;
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
OSAtomicIncrement32(&global);
|
||||
}
|
||||
print_result(s, "OSAtomicIncrement32:");
|
||||
|
||||
w_global = 0;
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
OSAtomicIncrement64Barrier(&w_global);
|
||||
}
|
||||
print_result(s, "OSAtomicIncrement64Barrier:");
|
||||
|
||||
w_global = 0;
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
OSAtomicIncrement64(&w_global);
|
||||
}
|
||||
print_result(s, "OSAtomicIncrement64:");
|
||||
|
||||
global = 0;
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
while (!__sync_bool_compare_and_swap(&global, 0, 1)) {
|
||||
do {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
__asm__ __volatile__ ("pause");
|
||||
#elif defined(__arm__) && defined _ARM_ARCH_7
|
||||
__asm__ __volatile__ ("yield");
|
||||
#endif
|
||||
} while (global);
|
||||
}
|
||||
global = 0;
|
||||
}
|
||||
print_result(s, "Inlined spin lock/unlock:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
OSSpinLockLock(&slock);
|
||||
OSSpinLockUnlock(&slock);
|
||||
}
|
||||
print_result(s, "OSSpinLock/Unlock:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
r = pthread_mutex_lock(&plock);
|
||||
assert(r == 0);
|
||||
r = pthread_mutex_unlock(&plock);
|
||||
assert(r == 0);
|
||||
}
|
||||
print_result(s, "pthread lock/unlock:");
|
||||
|
||||
#ifdef __BLOCKS__
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
dispatch_sync(q, ^{ });
|
||||
}
|
||||
print_result(s, "dispatch_sync:");
|
||||
#endif
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
dispatch_sync_f(q, NULL, (void (*)(void *))func);
|
||||
}
|
||||
print_result(s, "dispatch_sync_f:");
|
||||
|
||||
#ifdef __BLOCKS__
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
dispatch_barrier_sync(q, ^{ });
|
||||
}
|
||||
print_result(s, "dispatch_barrier_sync:");
|
||||
#endif
|
||||
|
||||
s = mach_absolute_time();
|
||||
for (i = cnt; i; i--) {
|
||||
dispatch_barrier_sync_f(q, NULL, (void (*)(void *))func);
|
||||
}
|
||||
print_result(s, "dispatch_barrier_sync_f:");
|
||||
|
||||
s = mach_absolute_time();
|
||||
dispatch_apply_f(cnt,
|
||||
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
|
||||
NULL, (void (*)(void *, size_t))func);
|
||||
s += loop_cost; // cancel out the implicit subtraction done by the next line
|
||||
print_result(s, "dispatch_apply_f():");
|
||||
|
||||
// do a "double backflip" to hit the fast-path of the enqueue/dequeue logic
|
||||
bfs = mach_absolute_time();
|
||||
dispatch_async_f(dispatch_get_main_queue(), &bf_cnt, backflip);
|
||||
dispatch_async_f(dispatch_get_main_queue(), &bf_cnt, backflip);
|
||||
|
||||
dispatch_main();
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void
|
||||
backflip_done(void)
|
||||
{
|
||||
print_result(bfs, "dispatch_async_f():");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
backflip(void *ctxt)
|
||||
{
|
||||
size_t *bf_cnt = (size_t *)ctxt;
|
||||
if (--(*bf_cnt)) {
|
||||
return dispatch_async_f(dispatch_get_main_queue(), ctxt, backflip);
|
||||
}
|
||||
backflip_done();
|
||||
}
|
||||
63
Telegram/ThirdParty/dispatch/tests/Foundation/dispatch_apply_gc.m
vendored
Normal file
63
Telegram/ThirdParty/dispatch/tests/Foundation/dispatch_apply_gc.m
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
#include <dispatch/dispatch.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#include <libkern/OSAtomic.h>
|
||||
|
||||
#include <bsdtests.h>
|
||||
#include "dispatch_test.h"
|
||||
|
||||
#if __OBJC_GC__
|
||||
const size_t final = 50000, desclen = 538892;
|
||||
#else
|
||||
const size_t final = 1000, desclen = 8892;
|
||||
#endif
|
||||
NSAutoreleasePool *pool = nil;
|
||||
|
||||
static void
|
||||
work(void* ctxt __attribute__((unused)))
|
||||
{
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
NSMutableArray *a = [NSMutableArray array];
|
||||
OSSpinLock sl = OS_SPINLOCK_INIT, *l = &sl;
|
||||
|
||||
dispatch_apply(final, dispatch_get_global_queue(0, 0), ^(size_t i){
|
||||
NSDecimalNumber *n = [NSDecimalNumber decimalNumberWithDecimal:
|
||||
[[NSNumber numberWithInteger:i] decimalValue]];
|
||||
OSSpinLockLock(l);
|
||||
[a addObject:n];
|
||||
OSSpinLockUnlock(l);
|
||||
});
|
||||
test_long("count", [a count], final);
|
||||
test_long("description length", [[a description] length], desclen);
|
||||
a = nil;
|
||||
[pool drain];
|
||||
test_stop_after_delay((void*)(intptr_t)1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
dispatch_test_start("Dispatch Apply GC"); // <rdar://problem/7455071>
|
||||
dispatch_async_f(dispatch_get_main_queue(), (void*)(intptr_t)1, work);
|
||||
CFRunLoopRun();
|
||||
return 0;
|
||||
}
|
||||
67
Telegram/ThirdParty/dispatch/tests/Foundation/dispatch_sync_gc.m
vendored
Normal file
67
Telegram/ThirdParty/dispatch/tests/Foundation/dispatch_sync_gc.m
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
#include <dispatch/dispatch.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <bsdtests.h>
|
||||
#include "dispatch_test.h"
|
||||
|
||||
#if __OBJC_GC__
|
||||
const size_t final = 50000, desclen = 538892;
|
||||
#else
|
||||
const size_t final = 1000, desclen = 8892;
|
||||
#endif
|
||||
NSAutoreleasePool *pool = nil;
|
||||
|
||||
static void
|
||||
work(void* ctxt __attribute__((unused)))
|
||||
{
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
NSMutableArray *a = [NSMutableArray array];
|
||||
dispatch_group_t g = dispatch_group_create();
|
||||
|
||||
dispatch_group_async(g, dispatch_get_global_queue(0, 0), ^{
|
||||
NSUInteger i;
|
||||
for (i = 0; i < final; i++) {
|
||||
NSDecimalNumber *n = [NSDecimalNumber decimalNumberWithDecimal:
|
||||
[[NSNumber numberWithInteger:i] decimalValue]];
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
[a addObject:n];
|
||||
});
|
||||
}
|
||||
});
|
||||
dispatch_group_notify(g, dispatch_get_main_queue(), ^{
|
||||
test_long("count", [a count], final);
|
||||
test_long("description length", [[a description] length], desclen);
|
||||
[pool drain];
|
||||
test_stop_after_delay((void*)(intptr_t)1);
|
||||
});
|
||||
dispatch_release(g);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
dispatch_test_start("Dispatch Sync GC"); // <rdar://problem/7458685>
|
||||
dispatch_async_f(dispatch_get_main_queue(), NULL, work);
|
||||
CFRunLoopRun();
|
||||
return 0;
|
||||
}
|
||||
73
Telegram/ThirdParty/dispatch/tests/Foundation/nsoperation.m
vendored
Normal file
73
Telegram/ThirdParty/dispatch/tests/Foundation/nsoperation.m
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2011 Apple Inc. All rights reserved.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_APACHE_LICENSE_HEADER_END@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <dispatch/dispatch.h>
|
||||
|
||||
#include <bsdtests.h>
|
||||
#include "dispatch_test.h"
|
||||
|
||||
@interface MYOperation : NSOperation
|
||||
{
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MYOperation
|
||||
|
||||
- (id) init
|
||||
{
|
||||
self = [super init];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)main
|
||||
{
|
||||
test_stop();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
dispatch_test_start("NSOperation");
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
|
||||
test_ptr_notnull("NSOperationQueue", queue);
|
||||
|
||||
MYOperation *operation = [[MYOperation alloc] init];
|
||||
test_ptr_notnull("NSOperation", operation);
|
||||
|
||||
[queue addOperation:operation];
|
||||
[operation release];
|
||||
|
||||
[[NSRunLoop mainRunLoop] run];
|
||||
|
||||
[pool release];
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user