0

我正在四处寻找线程来开发很酷的简单网络爬虫,但它的工作速度很慢。

这是我在ibm 库中找到的一段代码:

    urls = [] # huge list of urls
    in_queue = Queue.Queue()
    out_queue = Queue.Queue()

    pool = ActivePool()
    s = threading.Semaphore(semaphore)

    for url in urls[:slice_size]:
            in_queue.put(url)
            t = ThreadUrl(pool, s, url, in_queue, out_queue)
            t.setDaemon(True)
            t.start()

    counter = slice_size
    while not in_queue.empty() or not out_queue.empty():
          speed_new_daemon = time.time()
          url = urls[counter]
          in_queue.put(url)
          t = ThreadUrl(pool, s, url, in_queue, out_queue)
          t.setDaemon(True)

          t.start()        # <------ why 20% of all time I lose here?

          counter += 1
          speed_new_daemon = time.time() - speed_new_daemon

          speed_parser = time.time()
          result = out_queue.get()
          my_parser(result)
          speed_parser = time.time() - speed_parser

          # speed_parser only 80%, when speed_new_daemon takes 20%...
    in_queue.join()
4

1 回答 1

4

您引用的 IBM 文档启动了 5 个线程:

#spawn a pool of threads, and pass them queue instance 
for i in range(5):
  t = ThreadUrl(queue)
  t.setDaemon(True)
  t.start()

您的代码完全不同。首先,它为每个 URL 创建一个线程池:

for url in urls[:slice_size]:
    in_queue.put(url)
    t = ThreadUrl(pool, s, url, in_queue, out_queue)
    t.setDaemon(True)
    t.start()

然后每次通过主循环继续创建新线程:

while not queue.empty() or not out_queue.empty():
      speed_start_new_daemon = time.time()
      url = urls[counter]
      in_queue.put(url)
      t = ThreadUrl(pool, s, url, in_queue, out_queue)
      t.setDaemon(True)

因此,最终,您将拥有大量线程。由于所有这些线程只争夺几个核心,每个线程将花费大部分时间等待。最重要的是,您最终会给调度程序施加压力,因此您的 CPU 将花费大量时间来试图弄清楚如何运行您的线程。

同时,启动 1000 个线程可能不会占用太多 CPU 时间,但下载 1000 个 URL 也不会占用太多 CPU 时间(它受 I/O 限制,而不是受处理器限制),所以……您期望 CPU 使用率在哪里集中?

于 2013-07-10T00:26:55.470 回答