Oracle 19 in Docker (WSL2) is much slower than a native Oracle 12 install on Windows

I am attempting to run Oracle 19 inside a Docker container on Windows, but despite the usage of WSL2, I am still seeing an 80% drop in performance as compared to a natively installed Oracle 12 instance on the same machine.

Based on what I read on Docker blogs, I did not expect such a drastic drop in performance when running on WSL2. I am looking for some ideas as to what might be causing the slowdown.

Please note that Oracle 19 data is stored on the WSL2 filesystem, so nothing is bound to any host Windows directories:

$ docker container inspect --format '{{json .Mounts}}' oracle19_ubuntu_test
(
  {
    "Type": "volume",
    "Name": "526a083007c33fb2ec59886191a7b975b2083d020b3714322e79abc51c77a55c",
    "Source": "/var/lib/docker/volumes/526a083007c33fb2ec59886191a7b975b2083d020b3714322e79abc51c77a55c/_data",
    "Destination": "/opt/oracle/oradata",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
)

Initially I noticed the slowdown when my test suite took 5 minutes longer to run against the dockerized Oracle instance. To figure out what’s going on, I created another small test suite with 3 scenarios:

1) JDBC Connection performance test

This test repeatedly establishes a new JDBC connection and performs a small query that should not use any Disk I/O. This is done in a loop of 100 iterations and the total time is measured. This test attempts to measure the overhead of establishing a JDBC connection.

The test query:

select 1 from dual

This test runs 42% slower on Docker.

2) Big Data Generate and Fetch test

This test executes a query which generates a lot of data in memory, and then returns that data. This test measures query performance and JDBC transport time, hopefully without any disk I/O.

The test query:

select dbms_random.value(0, 10000000000) from dual connect by level <= 100000

This test runs 84% slower on Docker

3) Big Data Fetch test

This is a lot like Test #2, but the data is pre-generated and stored in BIG_DATA table, so this test measures just the query performance reading from a table, and JDBC transport time.

BIG_DATA table was pre-created as follows:

CREATE TABLE BIG_TABLE (
  RN_1 INTEGER NOT NULL,
  RN_2 INTEGER NOT NULL
)

INSERT INTO BIG_TABLE (RN_1, RN_2)
select 
  trunc(dbms_random.value(1,10000000000)) RN_1,
  trunc(dbms_random.value(1,10000000000)) RN_2 
from dual
connect by level <= 2000000;

And the test query:

SELECT * FROM BIG_TABLE fetch first 100000 rows only

This test runs 83% slower in Docker.

Details

You can see specific timings in a nice table here: https://docs.google.com/spreadsheets/d/1qgHw23UQG_NbKKF7XuPm9JIFJQQckTGtEJY_DPDkNwY

You can see the JUnit code that runs the above 3 tests here:
https://gitlab.com/vace117/oracle-19-docker-wsl2-performance/-/blob/master/src/test/java/vace117/jdbc/JdbcConnectionTests.java

Hypothesis

I suspect the problem might be with the network stack. The reasons I think that might be the case:

  • Heavy operations that run inside the db (such as generation of data for BIG_TABLE) actually run slightly faster on dockerized Oracle 19 than they do on native Oracle 12. So it’s not at all slow, once the operation is running inside the database.

  • Test #1 that simply opens and closes JDBC connections is 42% slower for Docker

  • Test #2 and Test #3 are equally slower on docker (~ 83%), even though one test has disk I/O and the other does not. What they have in common is sending the data back over the JDBC connection.

Test System Setup

  • Windows: Version 1909 (OS Build 18363.1082)
  • Docker: 20.10.0, build 7287ab3
  • Native Oracle: Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
  • Docker Oracle: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 Production

Oracle 19 Image

The Oracle 19 image was built using the official Dockerfile provided here:
https://github.com/oracle/docker-images/tree/master/OracleDatabase/SingleInstance/dockerfiles

The following settings were modified in 'docker-images/OracleDatabase/SingleInstance/dockerfiles/19.3.0/dbca.rsp.tmpl':

createAsContainerDatabase=false
totalMemory=16384

The total memory allocation was cranked up to unreasonable levels, just to eliminate any potential SGA and PGA memory issues. V$PGASTAT and V$SGASTAT views were used to verify that PGA and SGA limits are indeed set very high (much higher than my Native Oracle 12 instance).

I have also verified that the Oracle’s docker container has access to all CPUs and 26G of RAM.

Looking for some general thoughts/ideas/validation/refutation of my hypothesis. What could be causing the slowness in my setup? Is network stack a likely candidate based on the evidence I presented?