2013-08-15 2 views
1

트위스트 된 웹 벤치마킹 도구를 작성하려고합니다. Twisted는 웹 애플리케이션을위한 매우 환상적인 비동기 프레임 워크입니다. 이 프레임 워크를 처음 2 주 만에 시작 했으므로 여기에 문제가 있습니다 : 이 벤치마킹 도구를 ApacheBench와 비교할 때 결과는 동일한 동시성에서 크게 다릅니다.트위스트를 사용한 벤치마킹 도구

파이썬 pyab.py 여기 50000 50 http://xx.com/a.txt

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

그리고 아파치 벤치의 결과는 다음과 같습니다 : 여기 내 도구의 결과는

AB -c 50 - n 50000 http://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까지 올라갈 수 있습니다.

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() 

내 코드에 어떤 잘못이 있습니까 : 여기

내 코드 (pyab.py)인가? 감사!

+0

결과 텍스트 파일 URL은 토픽에 대해서는 충분하지 않은 사이트를 가리 킵니다 – andrean

+0

이것은 단지 데모이며 웹 서버는 로컬 웹 서버입니다. – closure

+0

오, 죄송합니다. 결과에 대한 다운로드 링크가 있다고 생각합니다 .. – andrean

답변

0

마지막으로 사용했을 때 ab에는 수십 개의 심각한 버그가있는 것으로 알려졌습니다. 때로는 엄청나게 부풀린 결과를보고하기도합니다. 때로는 부정적인 결과를보고합니다. 때때로 그것은 추락 할 것입니다. httperf과 같은 다른 도구를 온 전성 검사로 사용해 보겠습니다.

그러나 실제로 서버가 빠르면 다른 문제가 발생할 수 있습니다.

ab이 수정 된 경우에도 CPython에서 실행되는 Python 프로그램과 비교하여 C 프로그램에 대해 설명합니다. 파이썬에서 C보다 8 배 느리다는 것은 실제로 그렇게 나쁘지는 않기 때문에 실제로 spawnProcess과 멀티 코어 동시성을 사용하지 않는다는 것을 제외하고는 프로그램에 실제로 문제가 있다고 생각하지 않습니다.

처음에는 PyPy에서 더 나은 결과를 얻었습니까?

+0

조언 해 주셔서 감사합니다. 정말 도움이됩니다. 첫째, 어쩌면 아파치 벤치는 나에게 잘못된 결과를 준다. httperf 및 다른 벤치마킹 도구를 사용하여이를 확인합니다. Sencod는 서버가 너무 빠르다는 이유는 단지 "hello"가 포함 된 정적 파일만을 제공하기 때문입니다. 셋째, 두 개의 pyab 인스턴스를 동시에 실행하면 둘 다 1000 (req/sec)까지 올라갈 수 있습니다. 나는 모든 실마리를 나중에 하나씩 점검 할 것이다. 다시 한 번 감사드립니다! – closure