mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 13:07:02 +00:00
It looks like issue #1560 will cause a different sorting function to be used for selectors vs descriptors so performance of both should be monitored for regressions.
276 lines
7.2 KiB
Plaintext
276 lines
7.2 KiB
Plaintext
var FILE = require("file");
|
|
|
|
@import <Foundation/CPArray.j>
|
|
@import <Foundation/CPString.j>
|
|
@import <Foundation/CPNumber.j>
|
|
@import <Foundation/CPSortDescriptor.j>
|
|
|
|
var ELEMENTS = 100,
|
|
REPEATS = 10;
|
|
|
|
@implementation CPArrayPerformanceTest : OJTestCase
|
|
{
|
|
CPArray descriptors;
|
|
}
|
|
|
|
- (void)setUp
|
|
{
|
|
var descriptors = [
|
|
[CPSortDescriptor sortDescriptorWithKey:"a" ascending:NO],
|
|
[CPSortDescriptor sortDescriptorWithKey:"b" ascending:YES]
|
|
];
|
|
}
|
|
|
|
- (void)testAlmostSortedNumericUsingMergeSort
|
|
{
|
|
CPLog.warn("\nNUMERIC ALMOST SORTED");
|
|
var a = [self makeUnsorted],
|
|
sorted = [self sort:a usingSortSelector:@selector(sortedArrayUsingDescriptors:) withObject:descriptors];
|
|
[self checkAlmostSorted:sorted];
|
|
}
|
|
|
|
- (void)testAlmostSortedNumericUsingNativeSort
|
|
{
|
|
var a = [self makeUnsorted],
|
|
sorted = [self sort:a usingSortSelector:@selector(_native_sortedArrayUsingDescriptors:) withObject:descriptors];
|
|
[self checkAlmostSorted:sorted];
|
|
}
|
|
|
|
- (void)testRandomNumericUsingMergeSort
|
|
{
|
|
CPLog.warn("\nNUMERIC RANDOM");
|
|
var a = [self makeRandomNumeric],
|
|
sorted = [self sort:a usingSortSelector:@selector(sortedArrayUsingDescriptors:) withObject:descriptors];
|
|
[self checkRandomSorted:sorted];
|
|
}
|
|
|
|
- (void)testRandomNumericUsingNativeSort
|
|
{
|
|
var a = [self makeRandomNumeric],
|
|
sorted = [self sort:a usingSortSelector:@selector(_native_sortedArrayUsingDescriptors:) withObject:descriptors];
|
|
[self checkRandomSorted:sorted];
|
|
}
|
|
|
|
- (void)testRandomTextUsingMergeSort
|
|
{
|
|
CPLog.warn("\nTEXT RANDOM");
|
|
var a = [self makeRandomText],
|
|
sorted = [self sort:a usingSortSelector:@selector(sortedArrayUsingDescriptors:) withObject:descriptors];
|
|
[self checkRandomSorted:sorted];
|
|
}
|
|
|
|
- (void)testRandomTextUsingNativeSort
|
|
{
|
|
var a = [self makeRandomText],
|
|
sorted = [self sort:a usingSortSelector:@selector(_native_sortedArrayUsingDescriptors:) withObject:descriptors];
|
|
[self checkRandomSorted:sorted];
|
|
}
|
|
|
|
- (void)testAlmostSortedNumericUsingMergeSelectorSort
|
|
{
|
|
CPLog.warn("\nNUMERIC ALMOST SORTED (SELECTOR)");
|
|
var a = [self makeUnsorted],
|
|
sorted = [self sort:a usingSortSelector:@selector(sortedArrayUsingSelector:) withObject:@selector(compareAAscendingThenBDescending:)];
|
|
[self checkAlmostSorted:sorted];
|
|
}
|
|
|
|
- (void)testAlmostSortedNumericUsingNativeSelectorSort
|
|
{
|
|
var a = [self makeUnsorted],
|
|
sorted = [self sort:a usingSortSelector:@selector(_native_sortedArrayUsingSelector:) withObject:@selector(compareAAscendingThenBDescending:)];
|
|
[self checkAlmostSorted:sorted];
|
|
}
|
|
|
|
- (void)testRandomNumericUsingMergeSelectorSort
|
|
{
|
|
CPLog.warn("\nNUMERIC RANDOM (SELECTOR)");
|
|
var a = [self makeRandomNumeric],
|
|
sorted = [self sort:a usingSortSelector:@selector(sortedArrayUsingSelector:) withObject:@selector(compareAAscendingThenBDescending:)];
|
|
[self checkRandomSorted:sorted];
|
|
}
|
|
|
|
- (void)testRandomNumericUsingNativeSelectorSort
|
|
{
|
|
var a = [self makeRandomNumeric],
|
|
sorted = [self sort:a usingSortSelector:@selector(_native_sortedArrayUsingSelector:) withObject:@selector(compareAAscendingThenBDescending:)];
|
|
[self checkRandomSorted:sorted];
|
|
}
|
|
|
|
- (void)testRandomTextUsingMergeSelectorSort
|
|
{
|
|
CPLog.warn("\nTEXT RANDOM (SELECTOR)");
|
|
var a = [self makeRandomText],
|
|
sorted = [self sort:a usingSortSelector:@selector(sortedArrayUsingSelector:) withObject:@selector(compareAAscendingThenBDescending:)];
|
|
[self checkRandomSorted:sorted];
|
|
}
|
|
|
|
- (void)testRandomTextUsingNativeSelectorSort
|
|
{
|
|
var a = [self makeRandomText],
|
|
sorted = [self sort:a usingSortSelector:@selector(_native_sortedArrayUsingSelector:) withObject:@selector(compareAAscendingThenBDescending:)];
|
|
[self checkRandomSorted:sorted];
|
|
}
|
|
|
|
- (CPArray)sort:(CPArray)anArray usingSortSelector:(SEL)aSelector withObject:(id)anObject
|
|
{
|
|
var sorted,
|
|
start = (new Date).getTime();
|
|
|
|
for (var i = 0; i < REPEATS; ++i)
|
|
sorted = [anArray performSelector:aSelector withObject:anObject];
|
|
|
|
var end = (new Date).getTime();
|
|
|
|
CPLog.warn(aSelector + ": " + (end - start) + "ms");
|
|
|
|
return sorted;
|
|
}
|
|
|
|
- (CPArray)makeUnsorted
|
|
{
|
|
var array = [];
|
|
|
|
for (var i = 0; i < ELEMENTS; ++i)
|
|
{
|
|
var s = [Sortable new];
|
|
|
|
[s setA:(i % 5)];
|
|
[s setB:(ELEMENTS - i)];
|
|
|
|
array.push(s);
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
- (CPArray)makeRandomNumeric
|
|
{
|
|
var array = [];
|
|
|
|
for (var i = 0; i < ELEMENTS; i++)
|
|
{
|
|
var s = [Sortable new],
|
|
n1 = ROUND(RAND() * ELEMENTS),
|
|
n2 = ROUND(RAND() * ELEMENTS);
|
|
|
|
[s setA:n1];
|
|
[s setB:n2];
|
|
array.push(s);
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
- (CPArray)makeRandomText
|
|
{
|
|
var the_big_sort = FILE.read(FILE.join(FILE.dirname(module.path), "the_big_sort.txt"), { charset:"UTF-8" }),
|
|
words = the_big_sort.split(" ", ELEMENTS),
|
|
wordcount = words.length,
|
|
array = [];
|
|
|
|
for (var i = 0; i < wordcount - 1; i++)
|
|
{
|
|
var s = [Sortable new];
|
|
|
|
[s setA:words[i]];
|
|
[s setB:words[i + 1]];
|
|
array.push(s);
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
- (void)checkAlmostSorted:(CPArray)sorted
|
|
{
|
|
// Verify it really got sorted.
|
|
for (var j = 0; j < sorted.length; ++j)
|
|
{
|
|
var expectedA = 4 - FLOOR(j * 5 / ELEMENTS);
|
|
|
|
if (sorted[j].a != expectedA)
|
|
[self fail:"a out of order: " + expectedA + " != " + sorted[j].a];
|
|
|
|
var expectedB = (5 - expectedA) + 5 * (j % (ELEMENTS / 5));
|
|
|
|
if (sorted[j].b != expectedB)
|
|
[self fail:"b out of order: " + expectedB + " != " + sorted[j].b];
|
|
}
|
|
}
|
|
|
|
- (void)checkRandomSorted:(CPArray)sorted
|
|
{
|
|
// Verify that it really got sorted.
|
|
for (var j = 0; j < sorted.length - 1; ++j)
|
|
{
|
|
if ([sorted[j].a compare:sorted[j + 1].a] == CPOrderedAscending)
|
|
[self fail:"a out of order: " + sorted[j].a + " > " + sorted[j + 1].a];
|
|
|
|
if ([sorted[j].a compare:sorted[j + 1].a] == CPOrderedSame && [sorted[j].b compare: sorted[j + 1].b] == CPOrderedDescending)
|
|
[self fail:"b out of order: " + sorted[j].b + " < " + sorted[j + 1].b];
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation CPArray (NativeSort)
|
|
|
|
- (CPArray)_native_sortedArrayUsingDescriptors:(CPArray)descriptors
|
|
{
|
|
var sorted = [self copy];
|
|
|
|
[sorted _native_sortUsingDescriptors:descriptors];
|
|
|
|
return sorted;
|
|
}
|
|
|
|
- (CPArray)_native_sortUsingDescriptors:(CPArray)descriptors
|
|
{
|
|
var count = [descriptors count];
|
|
|
|
sort(function(lhs, rhs)
|
|
{
|
|
var i = 0,
|
|
result = CPOrderedSame;
|
|
|
|
while (i < count)
|
|
if ((result = [descriptors[i++] compareObject:lhs withObject:rhs]) != CPOrderedSame)
|
|
return result;
|
|
|
|
return result;
|
|
});
|
|
}
|
|
|
|
- (CPArray)_native_sortedArrayUsingSelector:(SEL)aSelector
|
|
{
|
|
var sorted = [self copy];
|
|
|
|
[sorted _native_sortUsingSelector:aSelector];
|
|
|
|
return sorted;
|
|
}
|
|
|
|
- (CPArray)_native_sortUsingSelector:(SEL)aSelector
|
|
{
|
|
sort(function(lhs, rhs)
|
|
{
|
|
return [lhs performSelector:aSelector withObject:rhs];
|
|
});
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation Sortable : CPObject
|
|
{
|
|
int a @accessors;
|
|
int b @accessors;
|
|
}
|
|
|
|
- (int)compareAAscendingThenBDescending:(Sortable)other
|
|
{
|
|
var aResult = [a compare:other.a];
|
|
|
|
return aResult === CPOrderedSame ? [b compare:other.b] : -aResult;
|
|
}
|
|
|
|
@end
|