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

0qx6xfy6  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(93)

我正在用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


Edit 2:我也用tcpdump检查了连接,没有连接问题。
编辑3:GHCi, version 7.10.3
编辑4:编译命令ghc -o fetcher fetcher.hs
Edit 5:问题无法在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


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

0md85ypi

0md85ypi1#

我最好的猜测是,您的HTTP客户端不会考虑Content-Length http头,而只是继续下载,直到远程服务器关闭连接,
答:可能比仅仅阅读Content-Length头要慢得多,许多web服务器保持套接字打开的时间比需要的时间长得多(通常是为了套接字重用方案)
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客户端将显示响应主体为abc,而未优化为考虑Content-Length报头的http客户端将显示响应主体为abcx
x1c 0d1x的数据
注:这个命令应该在类unix系统上工作(Linux,*BSD,MacOS),但可能不会在Windows系统上工作.如果你正在运行Windows,它将在Cygwin上工作(可能在WSL上工作,但我还没有尝试,我仍然在滚动不支持WSL的Windows 7)

mec1mxoz

mec1mxoz2#

curl实现了Happy Eyeball。您可能会遇到IPv6问题。

相关问题