- Notifications
You must be signed in to change notification settings - Fork 25.6k
Optimize some per-document hot paths in the geoip processor #120824
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
Changes from 10 commits
005ac8a 9509b1f a219a39 596d3ff faf0b5f a6a4135 eb47572 b04e3a7 a44e3b4 03489a5 56108af 2895ae4 File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| pr: 120824 | ||
| summary: Optimize some per-document hot paths in the geoip processor | ||
| area: Ingest Node | ||
| type: enhancement | ||
| issues: [] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -206,12 +206,32 @@ public static Metadata fromXContent(XContentParser parser) { | |
| } | ||
| | ||
| public boolean isCloseToExpiration() { | ||
| return Instant.ofEpochMilli(lastCheck).isBefore(Instant.now().minus(25, ChronoUnit.DAYS)); | ||
| final Instant now = Instant.ofEpochMilli(System.currentTimeMillis()); // millisecond precision is sufficient (and faster) | ||
| return Instant.ofEpochMilli(lastCheck).isBefore(now.minus(25, ChronoUnit.DAYS)); | ||
| } | ||
| | ||
| // these constants support the micro optimization below, see that note | ||
| private static final TimeValue THIRTY_DAYS = TimeValue.timeValueDays(30); | ||
| private static final long THIRTY_DAYS_MILLIS = THIRTY_DAYS.millis(); | ||
| | ||
| public boolean isNewEnough(Settings settings) { | ||
| TimeValue valid = settings.getAsTime("ingest.geoip.database_validity", TimeValue.timeValueDays(30)); | ||
| return Instant.ofEpochMilli(lastCheck).isAfter(Instant.now().minus(valid.getMillis(), ChronoUnit.MILLIS)); | ||
| // micro optimization: this looks a little silly, but the expected case is that database_validity is only used in tests. | ||
| // we run this code on every document, though, so the argument checking and other bits that getAsTime does is enough | ||
| // to show up in a flame graph. | ||
| | ||
| // if you grep for "ingest.geoip.database_validity" and you'll see that it's not a 'real' setting -- it's only defined in | ||
| // AbstractGeoIpIT, that's why it's an inline string constant here and no some static final, and also why it cannot | ||
| // be the case that this setting exists in a real running cluster | ||
| | ||
| final long valid; | ||
| if (settings.hasValue("ingest.geoip.database_validity")) { | ||
| valid = settings.getAsTime("ingest.geoip.database_validity", THIRTY_DAYS).millis(); | ||
| There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this slow only when there is no value (b/c we generate an exception or something)? Or is it always slow? If the latter, should we calculate this outside of this method, and have a settings listener listening for updates to the setting? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added another comment here in the code -- the setting itself is kindof a hack to get around the situation where we want to be able to test this code but we can't make it possible to actually change the value of the setting in 'the real world'. I'm not at all opposed to continuing to grind on this, but I'd love to do that in a different PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I took a closer look at the idea of the settings listener, and I think the reason we're not doing any of that right now is specifically because the setting in question isn't a 'real setting' -- AFAICT all the settings update listener type methods require a proper Somebody could probably get pretty far by extracting our current code and manually watching for settings changes like this: | ||
| } else { | ||
| valid = THIRTY_DAYS_MILLIS; | ||
| } | ||
| | ||
| final Instant now = Instant.ofEpochMilli(System.currentTimeMillis()); // millisecond precision is sufficient (and faster) | ||
| return Instant.ofEpochMilli(lastCheck).isAfter(now.minus(valid, ChronoUnit.MILLIS)); | ||
| } | ||
| | ||
| @Override | ||
| | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could pass in a ThreadPool, and use ThreadPool::absoluteTimeInMillis, which would be significantly faster since it's cached. Same goes in the other place below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. I'll see if I can make that happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't make it pass tests! I'm going to open a new ticket to track it.