Skip to content

Instantly share code, notes, and snippets.

@jcalvert
Created October 15, 2011 16:46
Show Gist options
  • Select an option

  • Save jcalvert/1289826 to your computer and use it in GitHub Desktop.

Select an option

Save jcalvert/1289826 to your computer and use it in GitHub Desktop.
Ruby SOAP Performance
require 'java'
require './cxf-deps.jar'
require './client.jar'
require 'benchmark'
context = com.vetstreet.Context.instance
hello_dao = context.get_bean "helloDao"
Benchmark.bm do |x|
x.report do
t = []
1000.times do
t << Thread.new do
hello_dao.say_hi "Foobar"
end
end
t.each{|thread| p thread.value}
end
end
----
user system total real
4.877000 0.000000 4.877000 ( 4.877000)
3.363000 0.000000 3.363000 ( 3.363000) #with -server flag

###Intro Tests were run against localhost. The SOAP server is Fuse ESB (Apache Servicemix) with the 'cxf-osgi' example that provides a dirt simple HelloWorld. The CXF route utilizes the strategy outlined here: https://gist.github.com/1289254 and I've appended my dao code for the hell of it. The not showing bits are the generated sources from CXF

###Versions JRuby was 1.6.3 w/ --1.9. MRI Ruby was 1.9.2-p290. REE ree-1.8.7-2011.03. Rubinius was rbx-head via rvm. It choked on the threaded text, and macruby would run neither test. Apache CXF was 2.3.7.

####Details I ran everything on my Macbook Pro, 2.4GHz Core i5 w/8GB of RAM.

###Issues I continually ran into issues with Savon.

  1. I would pretty consistently get what seemed to be threading issues with Nokogiri. This seemed to get alleviated by removing the WSDL parse step and just setting the namespace/endpoint directly, which as a caveat, is the recommended performant way according to the Savon docs. I used version 0.9.7 for my tests.

  2. httpi which Savon uses throws errors when threaded.

 NameError: uninitialized constant HTTPClient

I'm not sure what the root semantics causing this is, but the lib/httpi/adapter/httpclient.rb file references the httpclient class without requiring it. I suspect it works generally because there's an assumption that whatever has required the adapter has required httpclient. When I added the require statement to the adapter, this seemed to fix the issue.

package com.vetstreet;
import javax.annotation.Resource;
import org.apache.servicemix.examples.cxf.HelloWorld;
import org.apache.servicemix.examples.cxf.SayHi;
public class HelloDao {
@Resource
HelloWorld helloService;
public String sayHi(String message)
{
SayHi hi = new SayHi();
hi.setArg0(message);
return helloService.sayHi(hi).getReturn();
}
}
<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="HelloWorldImplService" targetNamespace="http://cxf.examples.servicemix.apache.org/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://cxf.examples.servicemix.apache.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://cxf.examples.servicemix.apache.org/" xmlns="http://cxf.examples.servicemix.apache.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="sayHi">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="sayHiResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string"/>
</xs:sequence>
</xs:complexType>
<xs:element name="sayHi" nillable="true" type="sayHi"/>
<xs:element name="sayHiResponse" nillable="true" type="sayHiResponse"/>
</xs:schema>
</wsdl:types>
<wsdl:message name="sayHi">
<wsdl:part element="tns:sayHi" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="sayHiResponse">
<wsdl:part element="tns:sayHiResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="HelloWorld">
<wsdl:operation name="sayHi">
<wsdl:input message="tns:sayHi" name="sayHi">
</wsdl:input>
<wsdl:output message="tns:sayHiResponse" name="sayHiResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorldImplServiceSoapBinding" type="tns:HelloWorld">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="sayHi">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="sayHi">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="sayHiResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorldImplService">
<wsdl:port binding="tns:HelloWorldImplServiceSoapBinding" name="HelloWorldImplPort">
<soap:address location="http://localhost:8181/cxf/HelloWorld"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
require 'savon'
require 'benchmark'
t = []
client = Savon::Client.new do
wsdl.namespace = "http://cxf.examples.servicemix.apache.org/"
wsdl.endpoint = "http://localhost:8181/cxf/HelloWorld"
end
Benchmark.bm do |x|
x.report do
1000.times do
t << Thread.new(client) do
response = client.request :wsdl, :say_hi do
soap.body = '<arg0>Foobar</arg0>'
end
response.body[:say_hi_response][:return]
end
end
t.each{|thread| p thread.value}
end
end
----
#jruby
24.325000 0.000000 24.325000 ( 24.325000)
#mri-1.9.2
5.070000 1.600000 6.670000 ( 6.856004)
#ree
6.300000 0.730000 7.030000 ( 7.701387)
require 'savon'
require 'benchmark'
t = []
client = Savon::Client.new do
wsdl.namespace = "http://cxf.examples.servicemix.apache.org/"
wsdl.endpoint = "http://localhost:8181/cxf/HelloWorld"
end
Benchmark.bm do |x|
x.report do
1000.times do
response = client.request :wsdl, :say_hi do
soap.body = '<arg0>Foobar</arg0>'
end
p response.body[:say_hi_response][:return]
end
end
end
#ree
6.117263 0.419652 6.536915 ( 13.744288)
#jruby
17.269000 0.000000 17.269000 ( 17.269000)
#jruby warmed
12.529000 0.000000 12.529000 ( 12.529000)
#mri
3.720000 1.380000 5.100000 ( 5.016870)
#rubinius
5.756874 0.399275 6.156149 ( 12.985919)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment