X Tutup
Skip to content

JAVA-2326: Reduce memory allocations during queries execution#1293

Closed
netudima wants to merge 4 commits intoapache:3.xfrom
netudima:3.x
Closed

JAVA-2326: Reduce memory allocations during queries execution#1293
netudima wants to merge 4 commits intoapache:3.xfrom
netudima:3.x

Conversation

@netudima
Copy link
Copy Markdown

@netudima netudima commented Jul 8, 2019

Fields "id" are evaluated for each request and allocate extra objects in heap but actually needed only for tracing. The values can be calculated lazy.

netudima added 4 commits July 9, 2019 00:35
… are evaluated for each request and allocate extra objects in heap but actually needed only for tracing. The values can be calculated lazy.
…ns, for Integer boxing within trace log parameters and for requests time tracking logic
Copy link
Copy Markdown
Contributor

@adutra adutra left a comment

Choose a reason for hiding this comment

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

Thanks for you PR. Everything makes sense although I'm not sure any of these changes will produce a significant performance improvement. Have you benchmarked your changes? I'm also a bit reluctant in introducing these changes now that the 3.x branch is being retired.


logger.trace("{}, stream {}, writing request {}", this, request.getStreamId(), request);
if (logger.isTraceEnabled())
logger.trace("{}, stream {}, writing request {}", this, request.getStreamId(), request);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just to make sure I understand, you are trying to avoid the array allocation for the varags arguments?

Copy link
Copy Markdown
Author

@netudima netudima Oct 26, 2019

Choose a reason for hiding this comment

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

array allocation in such places is usually optimized by escape analysis, the main issue which I see for such trace logging - hidden auto-boxing of int streamId.

The main goal of all the changes is to reduce an overall memory allocation on an application side (and to reduce GC pauses for the application correspondently). I am not expecting a visible change in request processing avg latency/throughput. Maybe some small CPU reduction will be as a bonus due to reducing some small amount of work.
Added a comment to https://datastax-oss.atlassian.net/browse/JAVA-2326


if (doneWork) {
// Always flush what we have (don't artificially delay to try to coalesce more messages)
for (Channel channel : channels) channel.flush();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Makes sense, although I'm not very comfortable changing this logic.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

the main trigger for the change is to avoid HashSet iterator objects creation for empty spin loops of flushing


static EnumSet<Flag> deserialize(int flags) {
EnumSet<Flag> set = EnumSet.noneOf(Flag.class);
Flag[] values = Flag.values();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are you sure this gives us any perf improvement? I would expect the implementation of Enum.values() to be highly optimized.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

enum.values() method creates a new copy of array with values each time (due to inability to create immutable arrays in Java - https://dzone.com/articles/memory-hogging-enumvalues-method)

private volatile List<Host> triedHosts;
private volatile ConcurrentMap<InetSocketAddress, Throwable> errors;

private final Timer.Context timerContext;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So you are just trying to avoid the allocation of a Timer.Context object, right?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

yes, trying to avoid the extra object allocation

}

String getId() {
// atomicity is not required to set the value
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This method could be called concurrently from different speculative executions. Are you saying atomicity is not required because even if 2 threads enter the method at the same time, the effect is going to be deterministic and idempotent, i.e. field id will be eventually set to Long.toString(System.identityHashCode(this))?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

yes, you are right, the result is deterministic and double evaluation is not a problem if it will happen (an atomic construction, like AtomicLong, would be more expensive here)

@netudima netudima changed the title JAVA-2326: Avoid String allocations required only for trace in RequestHandler JAVA-2326: Reduce memory allocations during queries execution Oct 27, 2019
@olim7t
Copy link
Copy Markdown
Contributor

olim7t commented Mar 4, 2020

Closing per my comment on the JIRA ticket.

@olim7t olim7t closed this Mar 4, 2020
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.

3 participants

X Tutup