-
Notifications
You must be signed in to change notification settings - Fork 171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make fewer lookup
requests when inode type might be known
#12
Comments
Our current `lookup` does two concurrent ListObjects requests. After thinking about it a bit more carefully, one of them can be replaced with a cheaper, faster HeadObject request. The "unsuffixed" request we were doing was purely to discover whether an object of the exact looked-up name existed, which is what HeadObject does. Switching to HeadObject reduces the request costs of a lookup. One disadvantage of HeadObject is when looking up directories. The unsuffixed ListObjects we're replacing here could discover a common prefix and return it immediately without waiting for the other request to complete. But in practice, the two requests were dispatched concurrently, so the customer still pays for both requests, and the latency is the minimum latency of two concurrently ListObjects. Now, the latency for a directory lookup will be the maximum of a concurrent ListObjects and HeadObject. An issue in this change is that we expect HeadObject to return 404 when doing directory lookups, but right now the way our error types are structured gives us no way to distinguish 404s from other errors. For now, I'm just swallowing all errors on the HeadObject request, and I'll follow up with a broader change to fix our error handling story to make this work. This is a partial fix for #12, but in future we can do better for lookups against objects we've seen before by remembering their type. Signed-off-by: James Bornholt <bornholt@amazon.com>
Our current `lookup` does two concurrent ListObjects requests. After thinking about it a bit more carefully, one of them can be replaced with a cheaper, faster HeadObject request. The "unsuffixed" request we were doing was purely to discover whether an object of the exact looked-up name existed, which is what HeadObject does. Switching to HeadObject reduces the request costs of a lookup. One disadvantage of HeadObject is when looking up directories. The unsuffixed ListObjects we're replacing here could discover a common prefix and return it immediately without waiting for the other request to complete. But in practice, the two requests were dispatched concurrently, so the customer still pays for both requests, and the latency is the minimum latency of two concurrently ListObjects. Now, the latency for a directory lookup will be the maximum of a concurrent ListObjects and HeadObject. An issue in this change is that we expect HeadObject to return 404 when doing directory lookups, but right now the way our error types are structured gives us no way to distinguish 404s from other errors. For now, I'm just swallowing all errors on the HeadObject request, and I'll follow up with a broader change to fix our error handling story to make this work. This is a partial fix for #12, but in future we can do better for lookups against objects we've seen before by remembering their type. Signed-off-by: James Bornholt <bornholt@amazon.com>
#69 improved this by replacing one ListObjects with a HeadObject. What's left to do is to use cached state as a hint to optimize the requests here—if we already suspect something is a file (or directory), we can start with the HeadObject (or ListObjects) and only do the other request if it fails. |
lookup
requestslookup
requests more frugal when inode type might be known
lookup
requests more frugal when inode type might be knownlookup
requests when inode type might be known
Not sure if applicable, I'm not familiar with internals of FUSE, however: In mount.fuse(8) I see two options:
Which both sounds excellent, if mount-s3 could set/use these? We have a very static object structure, so caching would be great and work very well. (Thanks for a very exciting and promising project btw!) |
Yeah, we actually do set those timeouts, here: mountpoint-s3/mountpoint-s3/src/fs.rs Lines 201 to 216 in b632bbe
We set them very low because we want to preserve S3's strong consistency model by default. But we know for some workloads, the bucket doesn't change very much/at all, and so we could cache that metadata much longer. We're tracking that as a roadmap item in #255. This issue is tracking a smaller improvement we could make: if we've listed a file/directory previously, then when the cache expires we could speculate that it's still a file/directory when we try to look it up from S3 again. I think with the way that lookup works right now, that would allow us to skip some HeadObject requests, but probably not any ListObjects requests. |
Right now our
lookup
implementation does two concurrent ListObjectsV2 requests. List requests are expensive, both cost-wise and performance-wise. We should think about a better strategy here, perhaps starting with a HeadObject request. If there's an existing inode, we could also use that as a hint as to which requests are most likely to succeed (only as a hint, because the bucket might have changed).The text was updated successfully, but these errors were encountered: