Skip to content

Using ObjectReader to cache Jackson bindings when parsing JWT #194

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

Closed
wants to merge 1 commit into from
Closed

Using ObjectReader to cache Jackson bindings when parsing JWT #194

wants to merge 1 commit into from

Conversation

jack-harrison
Copy link

Hey Guys,

While perf testing a web service which uses auth0-spring-security-api, I noticed that a chunk of performance was getting taken up by Jackson's ObjectMapper.readValue due to the reflection required on every call to set up its bindings.

Thankfully, Jackson provides an ObjectReader which caches the bindings for us, and is completely thread safe once after initial configuration. Since all configuration happens in the JWTParser header, this is perfectly safe to do and provides some significant performance improvements.

Here is a quick and dirty test I wrote to test the performance:

public class PerfTest {

    private static final String TOKEN = "eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJpc3MiOiJhdXRoMCJ9.mZ0m_N1J4PgeqWmi903JuUoDRZDBPB7HwkS4nVyWH1M";
    private static final int COUNT = 10000;
    private static final int THREADS = 50;

    @BeforeClass
    public static void warmup() {
        JWT jwt = new JWT();
        for (int i = 0; i < 1000; i++) {
            jwt.decodeJwt(TOKEN);
        }

        for (int i = 0; i < 1000; i++) {
            JWT.decode(TOKEN);
        }
    }

    @Test
    public void singleInstancePerformance() throws Exception {
        long start = System.nanoTime();

        JWT jwt = new JWT();
        runSingleThread(() -> jwt.decodeJwt(TOKEN));

        System.out.println("singleInstancePerformance:" + (System.nanoTime() - start) / 1000000L);
    }

    @Test
    public void singleInstanceThreadedPerformance() throws Exception {
        long start = System.nanoTime();

        JWT jwt = new JWT();
        runThreaded(() -> jwt.decodeJwt(TOKEN));

        System.out.println("singleInstanceThreadedPerformance:" + (System.nanoTime() - start) / 1000000L);
    }

    @Test
    public void staticPerformance() throws Exception {
        long start = System.nanoTime();

        runSingleThread(() -> JWT.decode(TOKEN));

        System.out.println("staticPerformance:" + (System.nanoTime() - start) / 1000000L);
    }

    @Test
    public void staticThreadedPerformance() throws Exception {
        long start = System.nanoTime();

        runThreaded(() -> JWT.decode(TOKEN));

        System.out.println("staticThreadedPerformance:" + (System.nanoTime() - start) / 1000000L);
    }

    private void runSingleThread(Runnable runnable) throws Exception {
        for (int i = 0; i < COUNT; i++) {
            runnable.run();
        }
    }

    private void runThreaded(Runnable runnable) throws Exception {
        List<Thread> threads = new LinkedList<>();
        for (int i = 0; i < THREADS; i++) {
            Thread thread = new Thread(() -> {
                for (int j = 0; j < COUNT; j++) {
                    runnable.run();
                }
            });
            thread.start();
            threads.add(thread);
        }

        for (Thread thread : threads) {
            thread.join();
        }
    }
}

This gives the following using this version of the code on my Core i5 2.5GHz x4 16GB:

staticPerformance:1062
staticThreadedPerformance:9340
singleInstancePerformance:81
singleInstanceThreadedPerformance:3897

Running only the static tests on master gives the following:

staticPerformance:2243
staticThreadedPerformance:13758

which equates to a rather nice performance improvement on a web server under load.

Would someone consider merging this in and releasing a new version so I can make another PR on auth0-spring-security-api? I'm happy to make an alternative implementation if you're not happy with this one.

Copy link
Contributor

@skjolber skjolber left a comment

Choose a reason for hiding this comment

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

Looks good to me, would it be possible to resolve the conflict(s)?

@skjolber
Copy link
Contributor

@lbalmaceda can you please review and merge this?

@skjolber
Copy link
Contributor

@jack-harrison bump

@skjolber
Copy link
Contributor

skjolber commented Feb 1, 2019

These changes were included in #255, so this PR can be closed @lbalmaceda @jack-harrison

@jack-harrison jack-harrison deleted the improve-performance branch February 1, 2019 09:33
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