Skip to content
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

idleScanTime evicts active elements of Cache #206

Open
vdshb opened this issue Oct 27, 2023 · 1 comment
Open

idleScanTime evicts active elements of Cache #206

vdshb opened this issue Oct 27, 2023 · 1 comment
Assignees
Labels

Comments

@vdshb
Copy link

vdshb commented Oct 27, 2023

I'm trying to understand how idleScanTime works. I've created a test, and can't realize why it fails. It looks like a bug to me.

public class Test {
    public static void main(String[] args) throws InterruptedException {
        // GIVEN
        var cache = new Cache2kBuilder<Integer, String>() {}
                .idleScanTime(Duration.of(500, ChronoUnit.MILLIS))
                .build();

        // WHEN
        cache.put(1, "1");

        // THEN
        for (int i = 0; i < 60; i++) {
            Thread.sleep(30);
            if (!"1".equals(cache.get(1))) {
                // This exception is thrown on i=33
                throw new RuntimeException(
                    "Cache supposed to have the value as last access was 30 milliseconds ago"
                );
            }
        }

        Thread.sleep(1600);
        if (cache.get(1) != null) {
            throw new RuntimeException(
                "Cache supposed to be empty as value last access was more than (idleScanTime * 3) milliseconds ago"
            );
        }
    }
}
@cruftex
Copy link
Member

cruftex commented Oct 31, 2024

Thanks for testing and the simple test case.

Cache2k is flagging entries that have been read, however, for performance reasons, on each read this is not forced to the main memory. So, this relies on the assumption that the application is non-trivial and at some time is doing something that needs to be visible by other threads e.g. a cache.put.

If you want to test like this, I assume this to work most of the time when you limit to one CPU core. I say most of the time, because the OS and the JVM would not guarantee that the main thread gets sufficient CPU time always within 500ms. An alternative would be to write something to a volatile variable or a synchronized block.

Right now, the idle scan implementation does not come with any added performance penalties to the normal cache operations. So, yes, its a bug, because its not doing what you expect from the documentation, however, fixing it would come at a performance penalty and the fix would probably only have an effect on trivial tests.

It would be interesting to see if there is a non-trivial application that would run into this problem. Maybe I optimized a bit too much here.

@cruftex cruftex self-assigned this Oct 31, 2024
@cruftex cruftex added the bug label Oct 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants