我正在使用savon gem与soap api进行交互。我正在尝试使用parallel gem向api发送三个并行请求。通常每个请求大约需要13秒才能完成,因此对于三个请求大约需要39秒。在使用并行gem并使用3个线程发送三个并行请求之后,需要大约23秒来完成所有三个请求,这非常好但我无法弄清楚为什么它没有在14-15秒内完成它。我真的需要降低总时间,因为它会直接影响我网站的响应时间。关于它为什么会发生的任何想法?网络请求本质上是阻塞的吗?
我发送请求如下
Parallel.map(["GDSSpecialReturn", "Normal", "LCCSpecialReturn"], :in_threads => 3){ |promo_plan| self.search_request(promo_plan) }
我尝试过使用多个进程但没有用。
答案 0 :(得分:3)
我有两个理论:
在并行计算中使用多个处理器的程序的加速受到程序序列部分所需时间的限制
我认为如果你在同一个系统上运行你的数据库,选项2就是罪魁祸首。问题是,当SOAP调用命中DB时,它会受到这两个因素的影响。即使是速度极快的15000 RPM服务器硬盘也只能每秒管理约200次IO操作。 SSD将达到10,000-100,000 + IO / s。 See figures on Wikipedia for ballparks.但是,大多数数据库都会进行一些聪明的内存缓存来缓解这些问题。
一种聪明的方法来测试它是否是因子2是运行H2 Database内存数据库并使用它来测试SOAP调用。它们的完成速度要快得多,可能和你一样应该一次看到1,3或$ CPU-COUNT个请求的类似执行时间。
答案 1 :(得分:1)
这实际上是个大问题,这取决于很多因素。
MRI,Rubinus,JRuby可能有所不同。所以我不确定是否是平行宝石 支持Rubinus和JRuby。
您的计算机中有多少CPU核心,您可以使用并行流程来利用它?如果您有多个核心,您是否尝试过使用过程?
Parallel.map(["GDSSpecialReturn", "Normal", "LCCSpecialReturn"]){ |promo_plan| self.search_request(promo_plan) } # by default it will use [number] of processes if you have [number] of CPUs
self.search_request
发生了什么?如果你在MRI环境中运行它,导致GIL,它实际上运行你的代码不同时。或者准确地说,IO呼叫不会阻塞(MRI实施),因此只有网络呼叫部分将同时运行 ,而不是所有其他部分。这就是为什么我对你在 self.search_request 中所做的其他工作感兴趣,因为这会对整体性能产生影响。
所以我建议你可以在不同的环境和不同的机器上测试你的代码(在本地机器和真实的生产机器之间可能会有所不同,所以请尝试调整和基准测试)以获得最佳结果。
顺便说一句,如果你想了解更多关于ruby中的线程/进程的信息,强烈推荐Jesse Storimer的Working with ruby threads,他做了很好的解释所有这些事情。
希望它有所帮助,谢谢。