简体   繁体   中英

Why Thread faster than Parallel.Foreach to open OracleConnection?

I have 2 pieces of code as follows, one use Thread and one use Parallel.Foreach

Thread

foreach (var i in new int [] {0, 1, 2, 3, 4, ..., 24 })
    new Thread(GET_DATA).Start(i);

Parallel

Parallel.Foreach(new int [] {0, 1, 2, 3, 4, ..., 24 }, GET_DATA);

with method GET_DATA

void GET_DATA(object state) {
    var x = (int)state;

    using (var conn = new OracleConnection(cs[x])) {
        conn.Open();
        using (var cmd = conn.CreateCommand()) {
            cmd.CommandText = "select * from dual";
            var dt = new DataTable();
            dt.Load(cmd.ExecuteReader());
        }
    }
}

and cs is connection string array for 25 Oracle Database

I use Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz with 16GB RAM , OracleConnection in Oracle.ManagedDataAccess library from nuget.

At first time, when no Connection Pool is created

  • Thread approach : all thread stop at 3 to 5 seconds after run
  • Parallel approach : parallel stop at 12 to 15 seconds after run

At next times, results of the 2 approaches are similar because Connection Pools are created.

I guess parallel running on single-core should be nearly 4 times slower than thread, can anyone explain it?

Thank you

In your first example you spawn 24 threads, and they will each start by waiting on an I/O operation (establishing socket connection to database) to complete.

In the second example you are using an unknown number of threads (depends on the number of cores, and degree of parallelization settings) to process a list of 24 items. Each thread will process a subset of the items in serial.

Since the operation is not CPU-bound in your process, but rather dependent on external processes (I/O to the database, operations on the database, etc.), the Parallel.Foreach will waste a lot of time waiting for one task to finish before starting the next.

Example

X is the completion of an operation, time goes vertically, threads go horizontally.

When using 24 threads:

1 2 3 ... 24   Time
| | |      |    |
| | |      |    |
| | |      |    |
| | |      |    |
| | |      |    |
X X X      X    V

When using 4 threads to process 24 items:

1 2 3 4   Time
| | | |    |    
| | | |    |    
| | | |    |    
X X X X    |    
| | | |    |
| | | |    |
| | | |    |
X X X X    |
| | | |    |
| | | |    |
| | | |    |
X X X X    |
. . . .    |
. . . .    |
. . . .    V
Parallel.Foreach(new int [] {0, 1, 2, 3, 4, ..., 24 }, GET_DATA);

Please also add this to Parallel.Foreach to make the two samples use the same number of thread.

new ParallelOptions { MaxDegreeOfParallelism = 24 }

As for normal foreach , This will wait for all threads to finish before exiting the loop

foreach (var i in new int [] {0, 1, 2, 3, 4, ..., 24 })
    new Thread(GET_DATA).Start(i);

I believe you will get the same result if you wait for all thread to be finish.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM