基准工具使用扭曲



我正在尝试编写一个基于twisted的web基准测试工具。Twisted是一个非常棒的web应用程序异步框架。因为我刚开始使用这个框架只有两周时间,所以我面临一个问题,它是:当我将这个基准测试工具与ApacheBench进行比较时,在相同的并发性上,结果差异很大。这是我的工具的结果:

python pyab.py 50000 50http://xx.com/a.txt

speed:1063(q/s), worker:50, interval:7, req_made:7493, req_done:7443, req_error:0

以下是Apache Bench的结果:

ab-c 50-n 50000http://xx.com/a.txt

Server Software:        nginx/1.4.1
Server Hostname:        203.90.245.26
Server Port:            8080
Document Path:          /a.txt
Document Length:        6 bytes
Concurrency Level:      50
Time taken for tests:   6.89937 seconds
Complete requests:      50000
Failed requests:        0
Write errors:           0
Total transferred:      12501750 bytes
HTML transferred:       300042 bytes
Requests per second:    8210.27 [#/sec] (mean)
Time per request:       6.090 [ms] (mean)
Time per request:       0.122 [ms] (mean, across all concurrent requests)
Transfer rate:          2004.62 [Kbytes/sec] received
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.8      0       4
Processing:     1    5   3.4      5     110
Waiting:        0    2   3.6      2     109
Total:          1    5   3.5      5     110
Percentage of the requests served within a certain time (ms)
  50%      5
  66%      6
  75%      6
  80%      6
  90%      7
  95%      7
  98%      8
  99%      8
 100%    110 (longest request)

在相同的url和并发性上,ApacheBench可以达到8000 req/sec,而pyab只有1000 req/sec。

这是我的代码(pyab.py):

from twisted.internet import reactor,threads
from twisted.internet.protocol import Protocol
from twisted.internet.defer import Deferred
from twisted.web.client import Agent
from twisted.web.client import HTTPConnectionPool
from twisted.web.http_headers import Headers
from twisted.python import log
import time, os, stat, logging, sys
from collections import Counter
logging.basicConfig(
    #filename= "/%s/log/%s.%s" % (RUN_DIR,RUN_MODULE,RUN_TIME),
    format="%(asctime)s [%(levelname)s] %(message)s",
    level=logging.WARNING,
    #level=logging.DEBUG,
    stream=sys.stdout
)
#log.startLogging(sys.stdout)
observer = log.PythonLoggingObserver()
observer.start()

class IgnoreBody(Protocol):
    def __init__(self, deferred, tl):
        self.deferred = deferred
        self.tl = tl
    def dataReceived(self, bytes):
        pass
    def connectionLost(self, reason):
        self.deferred.callback(None)

class Pyab:
    def __init__( self, n = 50000, concurrency = 100, url='http://203.90.245.26:8080/a.txt'):
        self.n = n
        self.url = url
        self.pool = HTTPConnectionPool(reactor, persistent=True)
        self.pool.maxPersistentPerHost = concurrency
        self.agent = Agent(reactor, connectTimeout = 5, pool = self.pool)
        #self.agent = Agent(reactor, connectTimeout = 5)
        self.time_start = time.time()
        self.max_worker = concurrency
        self.cnt = Counter({
            'worker' : 0 ,
            'req_made' : 0,
            'req_done' : 0,
            'req_error' : 0,
            })

    def monitor( self ):
        interval = int(time.time() - self.time_start)
        speed = 0
        if interval != 0:
            speed = int( self.cnt['req_done'] / interval )
        log.msg("speed:%d(q/s), worker:%d, interval:%d, req_made:%d, req_done:%d, req_error:%d" 
                % (speed, self.cnt['worker'], interval, self.cnt['req_made'], self.cnt['req_done'], self.cnt['req_error']), logLevel=logging.WARNING)

        reactor.callLater(1, lambda : self.monitor())
    def start( self ):
        self.keeprunning = True
        self.monitor()
        self.readMore()
    def stop( self ):
        self.keeprunning = False
    def readMore( self ):
        while self.cnt['worker'] < self.max_worker and self.cnt['req_done'] < self.n :
            self.make_request()
        if self.keeprunning and self.cnt['req_done'] < self.n:
            reactor.callLater( 0.0001, lambda: self.readMore() )
        else:
            reactor.stop()

    def make_request( self ):
        d = self.agent.request(
            'GET',
            #'http://examplexx.com/',
            #'http://example.com/',
            #'http://xa.xingcloud.com/v4/qvo/WDCXWD7500AADS-00M2B0_WD-WCAV5E38536685366?update0=ref0%2Ccor&update1=nation%2Ccn&action0=visit&_ts=1376397973636',
            #'http://203.90.245.26:8080/a.txt',
            self.url,
            Headers({'User-Agent': ['Twisted Web Client Example']}),
            None)
        self.cnt['worker'] += 1
        self.cnt['req_made'] += 1
        def cbResponse(resp):
            self.cnt['worker'] -= 1
            self.cnt['req_done'] += 1
            log.msg('response received')
            finished = Deferred()
            resp.deliverBody(IgnoreBody(finished, self))
            return finished
        def cbError(error):
            self.cnt['worker'] -= 1
            self.cnt['req_error'] += 1
            log.msg(error, logLevel=logging.ERROR)

        d.addCallback(cbResponse)
        d.addErrback(cbError)

if __name__ == '__main__' :
    if len(sys.argv) < 4:
        print "Usage: %s <n> <concurrency> <url>" % (sys.argv[0])
        sys.exit()
    ab = Pyab(n=int(sys.argv[1]), concurrency=int(sys.argv[2]), url=sys.argv[3])
    ab.start()
    reactor.run()

我的代码有问题吗?谢谢

当我上次使用它时,ab已知有几十个严重的错误。有时,这会导致它报告的结果被夸大。有时它会报告负面结果。有时它会崩溃。我会尝试另一个工具,比如httperf,作为健全性检查。

但是,如果你的服务器真的那么快,那么你可能会遇到另一个问题。

即使ab已经修复,您在这里谈论的是C程序与在CPython上运行的Python程序。Python中比C慢8x实际上并没有那么糟糕,所以我不认为你的程序有什么问题,只是它没有使用spawnProcess和多核并发。

首先,看看你是否在PyPy上得到了更好的结果。

相关内容

  • 没有找到相关文章

最新更新