Skip to content

Add Reader.LookupOffset & Decode #23

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

Merged
merged 2 commits into from May 23, 2016
Merged

Add Reader.LookupOffset & Decode #23

merged 2 commits into from May 23, 2016

Conversation

jgraettinger
Copy link
Contributor

@jgraettinger jgraettinger commented May 20, 2016

Expose database offsets, and decoding records at those offsets, as a
first-class concept via LookupOffset & Decode. Allow decoded records to
indirect nested structures by introducing special handling for the
uintptr type: fields with this type are decoded by storing the database
offset of the indirected record.

Reflection is expensive, many database records ("continent", "country", etc)
are embarrassingly cacheable, and database offsets make for excellent caching
keys. These methods allow clients to trivially identify and re-use structures
which have previously been extracted.


This change is Reviewable

case reflect.Uintptr:
result.Set(reflect.ValueOf(uintptr(pointer)))
return newOffset, nil
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change necessary? Wouldn't the same thing happen in the call to .decode() anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is de-referencing the pointer at offset and storing the result, whereas the case in decode is storing the referenced pointer prior to decode.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add comments here & above to clarify the difference.

Copy link
Owner

@oschwald oschwald May 22, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but then it calls decode on the new offset from the pointer, which would do the Uintptr handling for the new offset.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, quite right. Updated to remove.

@oschwald
Copy link
Owner

oschwald commented May 21, 2016

Overall this seems reasonable. I am a bit concerned with people not understanding the functionality and filing bug reports due to misuse. It also seems to add a small amount of overhead in the benchmarks, but that might be unavoidable.

Longer term, I would like to implement some sort of caching strategy, although that might make more sense in a higher-level library like geoip2 rather than in this library.

Johnny Graettinger added 2 commits May 22, 2016 15:59
Expose database offsets, and decoding records at those offsets, as a
first-class concept via LookupOffset & Decode. Allow decoded records to
indirect nested structures by introducing special handling for the
uintptr type: fields with this type are decoded by storing the database
offset of the indirected record.

Reflection is expensive, many database records ("continent", "country", etc)
are embarrassingly cacheable, and database offsets make for excellent caching
keys. These methods allow clients to trivially identify and re-use structures
which have previously been extracted.
@jgraettinger
Copy link
Contributor Author

I am a bit concerned with people not understanding the functionality and filing bug reports due to misuse.

I've refactored and extended documentation on LookupOffset & Decode to document the behavior & the motivating use case. Let me know your thoughts.

It also seems to add a small amount of overhead in the benchmarks, but that might be unavoidable.

Here's what I'm seeing now:

master:
BenchmarkMaxMindDB-4       50000             33877 ns/op
BenchmarkCountryCode-4    500000              2225 ns/op

offset-lookups:
BenchmarkMaxMindDB-4       50000             35602 ns/op
BenchmarkCountryCode-4    500000              2224 ns/op

Longer term, I would like to implement some sort of caching strategy, although that might make more sense in a higher-level library like geoip2 rather than in this library.

Agreed, I don't think that's appropriate in maxminddb-golang itself. Caching requires too much knowledge regarding the record type being extracted, and IMO it's a feature that maxminddb doesn't impose such knowledge.

@oschwald oschwald merged commit 6c9a71e into oschwald:master May 23, 2016
@oschwald
Copy link
Owner

Looks great. Thanks! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants