Implement ASPageTable#81
Conversation
|
🚫 CI failed with log |
Adlai-Holler
left a comment
There was a problem hiding this comment.
@nguyenhuy Awesome! We both know how much friggin time the range controller spends querying layoutAttributesForElementsInRect:, and stupid UIKit won't expose their cached version to us, so this is a major step forward.
There was a problem hiding this comment.
There was a typo here we should fix – Attributes
There was a problem hiding this comment.
While we're at it, we should initialize this map table with NSObjectPointerPersonality | NSMapTableWeakMemory so that we get pointer equality/hashing. Maybe it's worth making a convenience initializer that specifies these options.
There was a problem hiding this comment.
Since this is such a hot path, it's probably worth only calling -allObjects inside the CGRectContainsRect branch, since it will allocate memory.
There was a problem hiding this comment.
Since these are going to be created a lot I think it's worth optimizing upfront. Let's pack the coordinates into an integer and trick NSMapTable into using it.
typedef struct {
uint16_t x,
uint16_t y
} ASPageCoordinate;
__unsafe_unretained id ASPageCoordinateMakeKey(ASPageCoordinate coordinate) {
return (__bridge id)(void *)((coordinate.x << 16) + coordinate.y + 1);
}- We add 1 because 0 is not a valid key for NSMapTable.
- It might be worth asserting that
x, y < (1 << 16)and maskingx,y & 0xFFFF.
Then create the map table with pointerFunctionsWithOptions:NSPointerFunctionsIntegerPersonality | NSPointerFunctionsOpaqueMemory and use [mapTable objectForKey:ASPageCoordinateMakeKey(coord)] to get your value.
There was a problem hiding this comment.
Good point. At first, ASPageCoordinate was actually implemented as a struct. But back then I was not sure if I'd use it frequently enough to justify the NSMapTable and NSArray tricks, so I made it an object. Now that we have a better idea of its usage, let me convert it back to a struct =))
There was a problem hiding this comment.
True, an integer is preferable even to a struct, since it'll avoid malloc/free. That said, if the code is cleaner the code is cleaner and that's mostly what matters.
There was a problem hiding this comment.
It might be reasonable to use an inlined or #define accessor to unpack the x / y. CGRectGetMinX() type function, could be ASCoordinateX(coordinate). Might not be worth it though.
There was a problem hiding this comment.
@Adlai-Holler @appleguy I've pushed a new change that turns ASPageCoordinate into an uint32_t. And yes, we need ASPageCoordinateGetX() and ASPageCoordinateGetY(). Please have another look when you have time!
There was a problem hiding this comment.
No need to create these local copies of strong ivars – since the ivar isn't marked volatile the compiler is free to cache the value in a register. If there's gonna be a lot of underscores, this can make things prettier, and if the ivar is weak, then we definitely ought to get a strong local copy.
There was a problem hiding this comment.
Note: Personality doesn't matter for values, since they're never hashed/equaled.
There was a problem hiding this comment.
Let's never use 3.0f 0.0f etc – the compiler will choose the appropriate type. CGFloat is double on 64-bit, after all.
There was a problem hiding this comment.
It may not be worth it, but we could make the layoutAttributes argument id<NSFastEnumeration> and then pass the map table's object enumerator directly, rather than forming an array.
There was a problem hiding this comment.
Actually keyEnumerator and objectEnumerator of NSMapTable are of type NSEnumerator. But yes, it's better to just accept an enumerator.
There was a problem hiding this comment.
NSEnumerator conforms to NSFastEnumeration
There was a problem hiding this comment.
Oh yeah, that's true! Thanks for clarifying
There was a problem hiding this comment.
Let's make this required – they can always return nil if they want, and that way they are sure to know that this method exists (and we don't have to ask the runtime whether they implement.)
de85f8d to
2faf387
Compare
Adlai-Holler
left a comment
There was a problem hiding this comment.
Sweeeeet! One more round of refinements and then let's move forward. Feel free to merge this if you address these and want to do more work when it's the middle-of-the-night in Cali.
There was a problem hiding this comment.
Let's make this contentSize since the origin will always be 0
There was a problem hiding this comment.
Let's make this non-null, since @[] is free.
There was a problem hiding this comment.
I think we need to key this on page-that-intersects-rect. You can imagine an item that spans 10 pages – we need to make sure we include that one whenever we search any of those 10 pages.
There was a problem hiding this comment.
Let's make this a mutable set, since layout attributes could be span multiple pages and we want to dedupe (see previous comment).
There was a problem hiding this comment.
Let's have the value-type here be array rather than set. That way we avoid hashing, equality, and converting-to-array.
There was a problem hiding this comment.
Looks like there's no C++ in this file, let's drop it down to .m.
There was a problem hiding this comment.
Looks like this isn't currently used. Unless you have a specific use in mind, let's remove for now.
There was a problem hiding this comment.
It's used by the coming gallery layout delegate.
- It is a screen page table that can be used to quickly filter out objects in a certain rect without checking each and every one of them. - ASCollectionLayoutState generates and keeps a table that maps page to layout attributes within that page. - ASCollectionLayout (and later, ASCollectionGalleryLayoutDelegate) consults its layout state for `layoutAttributesForElementsInRect:`. This ensures the method can return as quickly as possible, especially on a large data set (I heard some people have galleries with thousands of photos!).
Generated by 🚫 Danger |
layoutAttributesForElementsInRect:. This ensures the method can return as quickly as possible, especially on a large data set (I heard some people have galleries with thousands of photos!).This PR was extracted from #76. Ticket: #186