基线版本:性能非常差的应用程序

用于计算更新的初始性能不佳的代码示例如下所示:

注意

为简单起见,以下示例中没有错误处理。 任何生产应用程序始终检查返回值。

 

警告

应用程序的前几个示例提供了有意降低的性能,以便说明通过更改代码可以改进性能。 请勿在应用程序中使用这些代码示例;它们仅用于说明目的。

 

#include <windows.h>

BOOL Map[ROWS][COLS];

void LifeUpdate()
{
    ComputeNext( Map );
    for( int i = 0 ; i < ROWS ; ++i )     //serialized
        for( int j = 0 ; j < COLS ; ++j )
            Set( i, j, Map[i][j] );    //chatty
}

BYTE Set(row, col, bAlive)
{
    SOCKET s = socket(...);
    BYTE byRet = 0;
    setsockopt( s, SO_SNDBUF, &Zero, sizeof(int) );
    bind( s, ... );
    connect( s, ... );
    send( s, &row, 1 );
    send( s, &col, 1 );
    send( s, &bAlive, 1 );
    recv( s, &byRet, 1 );
    closesocket( s );
    return byRet;
}

在此状态下,应用程序的网络性能可能最差。 此版本的示例应用程序的问题包括:

  • 应用程序很健谈。 每个事务都太小, 单元不需要逐个更新。
  • 事务是严格序列化的,即使单元可以同时更新。
  • 发送缓冲区设置为零,应用程序每次发送都会产生 200 毫秒的延迟,每个单元格三次。
  • 应用程序连接非常繁重,每个单元连接一次。 由于 TIME-WAIT 状态,应用程序在给定目标每秒的连接数上受到限制,但这不是问题,因为每个事务需要 600 毫秒以上。
  • 应用程序很胖;许多事务对服务器状态没有影响,因为许多单元格不会从更新更改为更新。
  • 应用程序表现出较差的流式处理;小型发送消耗大量 CPU 和 RAM。
  • 应用程序假定其发送采用 little endian 表示形式。 对于当前 Windows 平台而言,这是一个自然假设,但对于长期存在的代码来说可能很危险。

关键性能指标

以下性能指标以往返时间 (RTT) 、良好输出和协议开销表示。 有关这些术语的说明,请参阅 网络术语 主题。

  • 单元格时间(单个单元更新的网络时间)需要 4*RTT + 600 毫秒,用于 Nagle 和延迟 ACK 交互。
  • Goodput 小于 6 个字节。
  • 协议开销为 99.6%。

改进慢速应用程序

网络术语

修订版 1:清理明显

修订版 2:重新设计更少的连接

修订版 3:压缩块发送

未来改进