我正在用 clojure 编写一个网络爬虫,它需要恒定的时间,与我赋予该函数的深度无关。这就是函数本身。(它使用的是clojure soup,但我认为这无关紧要)
(defn crawl [source current-depth max-depth]
(if (= current-depth 0) (write-to-hf "{" false))
(let [targets (get-links source)]
(write-to-hf (str ":" source " " (seq targets) "\n") true)
(if (< current-depth max-depth)
(map crawl targets (repeat (inc current-depth)) (repeat max-depth))
(if (= current-depth 0)
(do (write-to-hf "}" true)
targets)
targets))))
(write-to-hf 是将数据写入文件的函数,所以我猜它也与问题无关。)
当我在 REPL 中测试我的函数时,写:
(crawl "http://bg.wikipedia.org" 0 1)
打印所有链接大约需要一个小时,但如果我将结果放入 var 中,则需要更少的时间。
(def a (crawl "http://bg.wikipedia.org" 0 1))
这对我来说看起来很正常,因为 I/O 操作是最耗时的,但我尝试测试将结果放入具有更多递归深度的 var 需要多少时间,并且它似乎是恒定的。甚至在做:
((crawl "http://bg.wikipedia.org" 0 100000000000))
需要同样的时间。
有人能解释一下为什么这是一个常数吗?我无法想象如何在不到一秒钟的时间内从维基百科(这是一个巨大的网站,每个页面上都有数百个链接)获取数十亿和更多页面的链接。