为什么异步代码比同步代码慢这么多?

3

我在SQL Server中创建一个测试表,如下:

CREATE TABLE Person
(
    PersonID INT NOT NULL IDENTITY,
    PersonName NCHAR(500) NOT NULL,
    PersonFamily NCHAR(500) NOT NULL,
 
    CONSTRAINT PK_Person PRIMARY KEY(PersonID)
)

接着我创建了两个测试异步的方法。

第一个方法使用异步的方式读取所有人员信息,而第二个方法则使用同步的方式。

异步方法:

private async Task<List<Person>> ReadPersonsAsync()
{
    List<Person> result = new List<Person>();

    using (SqlConnection sqlConnection = new SqlConnection(ConnectionString))
    {
        using (SqlCommand sqlCommand = new SqlCommand())
        {
            sqlCommand.CommandText = "SELECT * FROM Person";
            sqlCommand.CommandType = System.Data.CommandType.Text;
            sqlCommand.Connection = sqlConnection;

            await sqlConnection.OpenAsync();

            using (var reader = await sqlCommand.ExecuteReaderAsync())
            {
                while (await reader.ReadAsync())
                {
                    result.Add(new Person
                    {
                        ID = int.Parse(reader[0].ToString()),
                        Name = reader[1].ToString(),
                        Family = reader[2].ToString()
                    });
                }
            }
        }
    }

    return result;
}

同步方法:

private List<Person> ReadPersons()
{
    List<Person> result = new List<Person>();

    using (SqlConnection sqlConnection = new SqlConnection(ConnectionString))
    {
        using (SqlCommand sqlCommand = new SqlCommand())
        {
            sqlCommand.CommandText = "SELECT * FROM Person";
            sqlCommand.CommandType = System.Data.CommandType.Text;
            sqlCommand.Connection = sqlConnection;

            sqlConnection.Open();

            using (var reader = sqlCommand.ExecuteReader())
            {
                while (reader.Read())
                {
                    result.Add(new Person
                    {
                        ID = int.Parse(reader[0].ToString()),
                        Name = reader[1].ToString(),
                        Family = reader[2].ToString()
                    });
                }
            }
        }
    }

    return result;
}

当我使用异步方法时需要10秒钟,但同步方法只需要2秒钟。
我的代码哪里出了问题?谢谢。

2
Async/await 不仅仅是为了让代码运行更快,更多的是为了使服务器更具可扩展性,例如以高效的方式运行更多并发代码... - marc_s
2
“Person”表中有多少条记录? - Theodor Zoulias
4
请注意,如果您运行相同的查询两次,第一次执行将花费一些时间来编译执行计划(SQL Server),而第二个查询将使用已经编译的执行计划。10秒和2秒的差异不是由于异步操作引起的。 - Fabio
2
SqlClientland的情况很糟糕。使用SqlCommand异步方法处理大数据时性能极差,详见此处;异步读取大数据(二进制、文本)速度极慢,详见此处;SQL Reader异步比同步慢10倍,详见此处 - Theodor Zoulias
1个回答

1
答案是,异步读取器在您所使用的Dot Net版本中比“正常”读取器效率低。
sqlCommand.ExecuteReaderAsync()

sqlCommand.ExecuteReader()
慢。
因此,为了获得最佳性能,您应该同步读取数据,或选择不同的框架。

同步和异步之间的时间差只有几毫秒。仅通过同步/异步无法解释8秒的时间差太大了。 - Gabriel Luci
理论上,如果异步和同步函数都以完全相同的方式编码,优化到完全相同的程度,并且调用完全相同的子程序,则是可以的。实际上,这两个函数的编码方式不同,其中一个比另一个更有效率。 - OwlFace

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接