-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
GH-34723: [Java] Enable log trace for Netty allocator memory usage #35314
Conversation
|
|
||
class MemoryLogsAppender extends ListAppender<ILoggingEvent> { | ||
public boolean contains(List<String> values, Level level) { | ||
return list.stream() |
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.
Just inline this? I don't see why we need a subclass and a method
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.
Added
java/memory/memory-netty/src/main/java/io/netty/buffer/PooledByteBufAllocatorL.java
Show resolved
Hide resolved
java/memory/memory-netty/src/test/java/org/apache/arrow/memory/TestBaseAllocator.java
Outdated
Show resolved
Hide resolved
boolean result = listAppenderContains.apply(Arrays.asList("Memory Usage: \n", "Large buffers outstanding: ", | ||
"Normal buffers outstanding: "), | ||
Level.TRACE); | ||
logger.detachAppender(memoryLogsAppender); |
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.
this needs to be in a try-finally
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.
Added
BiFunction<List<String>, Level, Boolean> listAppenderContains = | ||
(List<String> values, Level level) -> memoryLogsAppender.list.stream() | ||
.anyMatch( | ||
log -> log.toString().contains(values.get(0)) && | ||
log.toString().contains(values.get(1)) && | ||
log.toString().contains(values.get(2)) && | ||
log.getLevel().equals(level) | ||
); | ||
boolean result = listAppenderContains.apply(Arrays.asList("Memory Usage: \n", "Large buffers outstanding: ", | ||
"Normal buffers outstanding: "), | ||
Level.TRACE); |
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.
Just write it as a loop...
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.
Added
public void testMemoryUsage() { | ||
ListAppender<ILoggingEvent> memoryLogsAppender = new ListAppender<>(); | ||
Logger logger = (Logger) LoggerFactory.getLogger("arrow.allocator"); | ||
logger.setLevel(Level.TRACE); |
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.
Reset the log level afterwards, too
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.
Added
memoryLogsAppender.start(); | ||
try (ArrowBuf buf = new ArrowBuf(ReferenceManager.NO_OP, null, | ||
1024, new PooledByteBufAllocatorL().empty.memoryAddress())) { | ||
buf.memoryAddress(); |
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.
What I'm saying is, you have no guarantee the logger will actually have logged anything by the time the next few lines run. So this is just adding a flaky test.
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.
And IMO, the easier way to test this would be to factor out a function that generates the log string, test that function, and use that function from the thread, rather than hooking into the physical logger.
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.
Validation inside a loop
boolean result = false; | ||
long startTime = System.currentTimeMillis(); | ||
while (true && (System.currentTimeMillis() - startTime) < 20000) { | ||
result = listAppenderContains.apply(Arrays.asList("Memory Usage: \n", "Large buffers outstanding: ", |
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.
Again...why the lambda? Just write it out as a loop
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.
Changed
); | ||
boolean result = false; | ||
long startTime = System.currentTimeMillis(); | ||
while (true && (System.currentTimeMillis() - startTime) < 20000) { |
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.
Why the redundant condition?
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.
Moved inside de loop to try to read logs for 10 seconds maximum, then finished with error.
assertTrue(result); | ||
} finally { | ||
logger.detachAppender(memoryLogsAppender); | ||
logger.setLevel(null); |
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.
Shouldn't we reset it to what it originally was?
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.
Initially it was marked with null
try (ArrowBuf buf = new ArrowBuf(ReferenceManager.NO_OP, null, | ||
1024, new PooledByteBufAllocatorL().empty.memoryAddress())) { | ||
buf.memoryAddress(); |
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.
Why can't we just use an allocator to create the buffer?
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.
Just trying to use allocator but for some reason the log is not populated if I run the test by command line, but able to populate log if I run the same test with allocator thru the IDE.
log.toString().contains("Normal buffers outstanding: ") && | ||
log.getLevel().equals(Level.TRACE) | ||
); | ||
if (result || (System.currentTimeMillis() - startTime) > 10000) { // 10 seconds maximum for time to write logs |
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.
you could just make this the loop guard?
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.
Added
Conbench analyzed the 7 benchmark runs on commit There were no benchmark performance regressions. 🎉 The full Conbench report has more details. |
Rationale for this change
To close #34723
What changes are included in this PR?
Enable log trace for Netty allocator memory usage
Are these changes tested?
New log enabled:
Logs:
Are there any user-facing changes?
No