haskell - 为什么我在 Haskell 中的 https getter 比 curl 慢?

标签 haskell curl

我正在用 Haskell 编写一个简单的 https getter 代码。收到响应后,我将其保存到压缩文件中。但是,与 curl 和 gzip 组合相比,我的版本非常慢。我怎样才能使它更快地 curl ?详情如下。

Haskell 代码(fetcher.hs):

import Control.Lens
import qualified Codec.Compression.GZip as GZip
import qualified Data.ByteString.Lazy as BL
import Network.Wreq

writeURIBodyToFile :: FilePath -> String -> IO()
writeURIBodyToFile filePath uri = do
  response <- get uri
  let body = (response ^. responseBody)
  BL.writeFile filePath (GZip.compress body)

main :: IO ()
main = writeURIBodyToFile "out.html.gz" "https://www.sahibinden.com/ilan/vasita-otomobil-seat-hatasiz-boyasiz-tramersiz-dsg-leon-469484363/detay/"

haskell 结果:
$ ghc -o fetcher fetcher.hs
$ time ./fetcher 

real    0m9.240s
user    0m8.840s
sys     0m0.232s

curl 结果:
$ time curl "https://www.sahibinden.com/ilan/vasita-otomobil-seat-hatasiz-boyasiz-tramersiz-dsg-leon-469484363/detay/" | gzip > out.html.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  102k  100  102k    0     0   331k      0 --:--:-- --:--:-- --:--:--  332k

real    0m0.524s
user    0m0.156s
sys     0m0.040s

编辑:
我也尝试了 http-conduit 包,没有任何改变。
import qualified Data.ByteString.Lazy as BL
import           Network.HTTP.Simple

main :: IO ()
main = do
    response <- httpLBS "https://www.sahibinden.com/ilan/vasita-otomobil-seat-hatasiz-boyasiz-tramersiz-dsg-leon-469484363/detay/"
    BL.writeFile "outnew.html" $ getResponseBody response

Edit2:我还检查了与 tcpdump 的连接,没有连接问题。

编辑3:GHCi, version 7.10.3
编辑4:编译命令ghc -o fetcher fetcher.hs
Edit5:在 2019 年 2 月,此代码无法重现该问题:
{-# LANGUAGE OverloadedStrings #-}
import Network.HTTP.Simple
import qualified Data.ByteString.Char8 as B8

main :: IO ()
main = httpBS "https://www.sahibinden.com/ilan/vasita-otomobil-mercedes-benz-mercedes-benz-c-180-fascination-7g-tronic-ozel-renk-652750468/detay" >>= B8.putStrLn . getResponseBody

结果:
$ ghc -o fetcher fetcher.hs
$ time ./fetcher 
real    0m0,549s
user    0m0,093s
sys     0m0,021s

Edit6:同样,问题无法在 2019 年 2 月的第一个代码示例中重现 GHCi, version 8.0.2

最佳答案

我最好的猜测是您的 HTTP 客户端不考虑 Content-Length http header ,并且只会继续下载,直到远程服务器关闭连接,即

答:可能比仅仅阅读 Content-Length 慢得多。 header ,许多网络服务器使套接字保持打开的时间比需要的时间长得多(通常用于套接字重用方案)

b:天真/简单的 http 客户端之间的共同主题。

你可以用一个像这样的小 netcat http 服务器来确认这一点:

printf "HTTP/1.0 200 OK\r\nContent-Length: 3\r\n\r\nabcx" | nc -l 9999

现在点击http://127.0.0.1:9999并检查响应,一个经过优化以考虑 Content-Length 的 http 客户端 header 会说响应正文是 abc ,而 http 客户端未优化以考虑 Content-Length header 会说响应正文是 abcx
enter image description here

注意:这个命令应该适用于类 unix 系统(Linux、*BSD、MacOS),但可能不适用于 Windows 系统。如果您运行的是 Windows,它将在 Cygwin 上运行(并且可能在 WSL 上工作,但我没有尝试过,我仍在滚动不支持 WSL 的 Windows 7)

关于haskell - 为什么我在 Haskell 中的 https getter 比 curl 慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45780131/

相关文章:

haskell - 在 GADT 数据构造函数中通过类型族指定依赖类型

c - 对 Data.Vector 进行基准测试时的时间出人意料地低

php - 如何使用Curl检查API请求超时?

php - cURL 失败并出现错误 : Couldn't understand the server certificate format

haskell - Yesod数据库迁移循环

haskell - GHC 7.6 中类型级别 Nat 的匹配

Scala 在 Haskell 中的部分函数

c - libcurl 简单 vs 多接口(interface)

python-2.7 - cURL 与请求(SSL 问题?)

php - 在 mysql 中存储 curl session cookie