похожие параллельные задачи, очень разное время выполнения (Java) - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть задание вставить 8 миллионов строк в таблицу базы данных oracle. Я масштабировал работу на 8 ядрах ЦП, вот пример кода:

final long start = System.currentTimeMillis();
final int batchSize = 800000;
final int nCore = Runtime.getRuntime().availableProcessors();
final int batchPerCore = batchSize / nCore;
final CountDownLatch taskCountDown = new CountDownLatch(nCore);
final CountDownLatch kickoffLatch = new CountDownLatch(1);
final ExecutorService es = Executors.newFixedThreadPool(nCore);

Class.forName("oracle.jdbc.driver.OracleDriver");

for (int n = 0; n < nCore; n++) {

    es.submit(() -> {

        log.info("Thread {} starts working on {} insertion jobs.", Thread.currentThread().getName(), batchPerCore);
        try (Connection conn = DriverManager.getConnection(DB_URL, USER_NAME, PASSWORD)) {

            Assert.assertNotNull("connection established", conn);
            conn.setAutoCommit(false);
            PreparedStatement pstmt = conn.prepareStatement(PREP_STATEMENT);


            for (int i = 0; i < batchPerCore; i++) {
                initPrepTranStatement(pstmt);
                pstmt.addBatch();

            }

            int[] resultTran = pstmt.executeBatch();
            Assert.assertEquals(resultTran.length, batchPerCore);
            conn.commit();
            log.info("Thread {} completed its job!", Thread.currentThread().getName());
            taskCountDown.countDown();

        } catch (SQLException e) {
            e.printStackTrace();
        }

    });

} // ~ for ~

es.shutdown();

kickoffLatch.countDown();

taskCountDown.await();

log.info("It takes {} milliseconds to complete all {} tasks for {} insertions each. ",
        (System.currentTimeMillis()-start), nCore, batchPerCore);

в процессе выполнения, он показывает 3 задачи, выполненные при выполнении курсов в 14:09, но другие еще ожидающие на момент написания статьи (15:29).

Вот журнал:

Apr 27, 2020 1:25:17 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-7 starts working on 100000 insertion jobs.
Apr 27, 2020 1:25:17 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-2 starts working on 100000 insertion jobs.
Apr 27, 2020 1:25:17 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-5 starts working on 100000 insertion jobs.
Apr 27, 2020 1:25:17 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-8 starts working on 100000 insertion jobs.
Apr 27, 2020 1:25:17 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-4 starts working on 100000 insertion jobs.
Apr 27, 2020 1:25:17 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-3 starts working on 100000 insertion jobs.
Apr 27, 2020 1:25:17 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-6 starts working on 100000 insertion jobs.
Apr 27, 2020 1:25:17 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-1 starts working on 100000 insertion jobs.
Apr 27, 2020 2:09:53 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-4 completed its job!
Apr 27, 2020 2:09:53 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-6 completed its job!
Apr 27, 2020 2:09:53 PM com.db.loader.DBFlexDataLoadingPerfTest lambda$4
INFO: Thread pool-1-thread-7 completed its job!

Использование DriverManager в этом случае не очень хорошая идея, тем не менее, я должен был использовать реализацию DataSource это не имеет значения или не влияет на цель этого теста.

Учитывая, что все задачи одинаковы с точки зрения характера работы и способа выполнения, я не могу понять, почему некоторые серьезно отстают от других, и, скорее всего, они просто висят там.

Конкретные аргументы JVM не заданы. Машина Windows 10 pro, с 8-ядерным i7-6700 и 32G RAM.

1 Ответ

0 голосов
/ 27 апреля 2020

Потоки не определены c. Не гарантируется, что все задачи будут равномерно выполняться всеми потоками. В большинстве сценариев c они могут быть даже сериализованы (маловероятно, но не невозможно). Это все на усмотрение реализации JVM и планировщика ОС.

Кроме того, может существовать несколько факторов, зависящих от реализации, которые не видны в предоставленном фрагменте кода (например, обработка драйвера или базы данных параллельных пакетов подмножеством)

...