2013-07-06 69 views
0

我正在构建一个使用换行符\n来分隔未知长度的消息(但通常为< 64字节)的TCP应用程序。我发现this article非常有用。Python TCP套接字recv(1)与recv(n)的效率

是否最好(即最有效/最快)的方法来一次处理一个字符,并检查它是换行符还是recv更大的缓冲区并在类中存储“剩菜”?

一次一个

def __recv_until_newline(self): 
    message = "" 
    while True: 
     chunk = self.socket.recv(1) 
     if chunk == "" or chunk == "\n": 
      break 
     message += chunk 
    return message 

保持一个缓冲

def __recv_until_newline(self): 
    """ self.__buffer holds previously received message parts""" 
    message = self.__buffer 
    while True: 
     chunk = self.socket.recv(64) 
     message += chunk 
     if chunk == "" or "\n" in message: 
      break 

    # something a bit more intelligent than this in reality, but you get the idea 
    messages = message.split('\n') 
    self.__buffer = "".join([x for x in message[1:]]) 
    return messages[0] 
+1

另请注意,您的第一个版本具有*二次*复杂性。每当你做'message + = chunk'时,都会创建一个* new *字符串对象,这意味着整个'message'被复制并且添加最后一个字节。如果消息长度为64字节,那么第一个循环将简单地创建一个长度为1的字符串,第二个必须复制前一个字符串并添加1个字符,然后您必须复制两个字符并添加另一个字符你的成本大约是'sum(range(64))= 2016',而不是''recv(64)''。使用'list'和'''.join'你可以避免这种二次方行为。 – Bakuriu

回答

1

获得大块肯定是更有效的,只是因为你正在做的操作较少。想想这样:如果你有一条长度为1000的消息,那么你的循环将在第一种情况下激发1000次,仅在第二种情况下激发1000次。性能损失是显而易见的。当然这是因为Python的原因,但即使在操作系统级别,它也是更有效率的,因为有相同的原因:使得1000次sys调用为16次。并且扫描字符串(顺便说一句:您应扫描长度为64的chunk而不是message)比649拨打recv要便宜。这是非常多的。

+0

感谢您的回复...有点有道理它只是执行有点混乱:) –