WEB开发网
开发学院软件开发VC Visual C++优化对大型数据集合的并发访问 阅读

Visual C++优化对大型数据集合的并发访问

 2010-08-22 20:47:32 来源:WEB开发网   
核心提示:我的针对这一问题的解决方案是封装在 CritSecTable 类中(参见图 11 和图 12),该类的接口看起来几乎与 CritSec 的接口完全相同,Visual C++优化对大型数据集合的并发访问(8),不同之处在于 acquire 和 release 方法采用 void* 参数,Figure 13 DBEntry

我的针对这一问题的解决方案是封装在 CritSecTable 类中(参见图 11 和图 12)。该类的接口看起来几乎与 CritSec 的接口完全相同,不同之处在于 acquire 和 release 方法采用 void* 参数。

Figure 13 DBEntry Class

bool      DBEntry::g_useSingleCritSec = true;
CritSec     DBEntry::g_singleCritSec;
CritSecTable  DBEntry::g_critSecTable;
void DBEntry::acquire()
{
  if (g_useSingleCritSec)
  {
    g_singleCritSec.acquire();
  }
  else
  {
    g_critSecTable.acquire(this);
  }
}
void DBEntry::release()
{
  if (g_useSingleCritSec)
  {
    g_singleCritSec.release();
  }
  else
  {
    g_critSecTable.release(this);
  }
}

要使用该类,需要将一个 CritSecTable 实例与您希望对其进行并发访问的大型集合(在这种情况下,即内存中的数据库)相关联。当您希望锁定或取消锁定某个项时,需要分别在 CritSecTable 对象上调用 acquire 或 release,并将该项的地址作为 void* 参数进行传递。有关示例,请参见 DBEntry 类的 acquire 和 release 方法的实现(如图 13 所示)。(我已经实现了这些方法,以便它们可以为整个数据库使用单个临界区,或者使用一个 CritSecTable,具体取决于全局标志 g_useSingleCritSec 的设置。)

CritSecTable 在内部维护了一个 CritSec 实例数组(在我的实现中,包含 256 个实例)。当您调用 acquire 或 release 时,它将根据该 void* 参数计算一个哈希,然后使用该哈希对数组进行索引,并在相应的 CritSec 对象上调用 acquire 或 release。这意味着对于任何给定的数据库项,您都将始终使用同一个 CritSec 对象,从而保证您能够保持正确的同步行为。

如果两个线程试图同时锁定不同的项,则其中一个线程阻塞另一个线程的可能性非常低(二百五十六分之一的可能性)。当然,随着试图对数据库进行并发访问的线程数的增加,其中一个或多个线程被阻塞的可能性也将增加。然而,在 Windows 中这通常不是一个问题。运行 Windows 的计算机很少具有八个以上的 CPU,并且(据我所知)上限是 32 个。如果您的服务器应用程序正在使用 I/O 完成端口(正像它应该做的那样),则在任意给定时间,您的服务器中正在运行的线程数目将接近于 CPU 的数目。(注:有关 I/O 完成端口的讨论超出了本文的范围,但最近几年来 MSDN Magazine 中出现过几篇有关该主题的好文章。

我选择使 CritSec 数组的长度为 256,因为它有利于使用一个非常简单但有效的哈希函数。在此情况下,该哈希函数只是简单地对 void* 的字节进行 XOR 运算,从而得到单个无符号 char。我已经花费了一些时间,针对 void* 的长度为四个字节、八个字节的情况以及一般性情况(针对您恰好在具有 7 字节指针的系统上运行 Windows 的情形)优化该哈希函数。在 32 位 Intel 系统上,Visual C++ 编译器将哈希方法的 32 行 C++ 代码简化为只有六条汇编语言指令。

如果您的应用程序将具有数量大得多的线程试图同时锁定不同的项,则您可能需要更大的 CritSec 数组,但您将需要更为复杂的哈希函数来对其进行哈希运算。

并发性结果

我在具有一个 CPU 的 500 MHz Pentium III 计算机上以及具有四个 CPU 的 550 MHz Pentium III Xeon 计算机上运行了 CD 示例。在每种情况下,我都使用不断增加的辅助线程数目运行了两个测试(一个使用单个临界区,另一个使用 CritSecTable)。图 14 显示了在单 CPU 计算机上使用一到八个辅助线程运行测试的结果。

图 14 单 CPU 计算机上的结果

上一页  3 4 5 6 7 8 9  下一页

Tags:Visual 优化 大型

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接