基线版本:性能非常差的应用程序
用于计算更新的初始性能不佳的代码示例如下所示:
注意
为简单起见,以下示例中没有错误处理。 任何生产应用程序始终检查返回值。
警告
应用程序的前几个示例提供了有意降低的性能,以便说明通过更改代码可以改进性能。 请勿在应用程序中使用这些代码示例;它们仅用于说明目的。
#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%。
相关主题