[Openstack] glance performance gains via sendfile()

2012-02-06 Thread Eoghan Glynn


Hi Reynolds,

I've been looking into your interesting idea around sendfile()[1]
usage, here are a few initial thoughts:

- There's potentially even more speed-up to be harnessed in serving
  out images from the filesystem store via sendfile(), than from using
  it client-side on the initial upload (based on the assumption that
  images would typically uploaded once but downloaded many times, also
  that the download time is more crucial for perceived responsiveness
  as an instance being spun up by nova may be held up until the image
  is retreived from glance, unless already cached).

- I'd suspect that some of the potential gain on the client side is
  currently thrown away by the syntax of the glance add CLI, specifically
  the use of shell redirection to pass the image content:

glance add name=MyImage  /path/to/image/file

  I'm open to correction, but this seems to needlessly copy the image
  content via user-space, even if the glance client avoids a second
  copy internally via the sendfile() usage. So I'd propose to also add
  a new cmd line arg to allow the file be directly specified, e.g.

glance add name=MyImage path=/path/to/image/file

  This would have different semantics to the location field, e.g 

location=file:///path/to/image/file

  (which would imply that the content is not uploaded to the remote
  store).

- The structure of typical pysendfile usage gets in the way of
  glance's image iterator pattern. On the client side this is more an
  an incovenience, requiring some restructuring of the code. However
  on the service-side, it seems we're a bit a hamstrung by the
  WSGI/webob APIs. For example the webob.response.body_file is
  filelike but doesn't expose a fileno attribute as there's no real
  underlying FD available intially, so the following kind of approach
  isn't workable:

sendfile(response.body_file.fileno(), 
 filestore_path.fileno(), ...)

  Seems a better approach would be to allow glance to be optionally
  deployed on a WSGI container that directly supports the [2]
  wsgi.file_wrapper extension (e.g. mod_wsgi on Apache, or uWSGI) or
  even allow one of the non-standard headers like X-Sendfile or 
  X-Accel-Redirect to be set where supported.

In case, I'll crack on with the basic client-side usage to begin with,
so that we can quantify the performance gain.

Cheers,
Eoghan

[1] http://code.google.com/p/pysendfile/
[2] 
http://www.python.org/dev/peps/pep-0333/#optional-platform-specific-file-handling

___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp


Re: [Openstack] glance performance gains via sendfile()

2012-02-06 Thread Rick Jones
If one wants to experiment with the performance effects of sendfile(), 
the netperf benchmark http://www.netperf.org/ has a TCP_SENDFILE 
test which complements the TCP_STREAM test.  It can also report CPU 
utilization and service demand to allow a comparison of efficiency.


netperf -H destination -t TCP_SENDFILE -F file -c -C -l 30

will run a 30-second TCP_SENDFILE tests using file as the data source 
(one is created if no -F option is specified) sending to destination 
(assumes that netserver has been launched on destination.  The 
corresponding TCP_STREAM test would be the obvious substitution.


One area of investigation would be the effect of send size on things. 
That can be accomplished with a test-specific (following a -- on the 
command line) -m option:


netperf  ...as above...  -- -m 64K

would cause netperf to send 65536 bytes in each send call.  The manual 
for the current top-of-trunk version of netperf is at:


http://www.netperf.org/svn/netperf2/trunk/doc/netperf.html

and the top-of-trunk bits can be pulled via subversion pointing at 
http://www.netperf.org/svn/netperf2/trunk


happy benchmarking,

rick jones

For example, between a pair of Ubuntu 11.04 systems with Mellanox 10GbE, 
and a pair of X5650 processors each (so 24 CPUs):


~$ ./netperf -p 12866 -H ndestination -c -C -l 30 -- -P 12867 -m 64K
MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 12867 AF_INET to 
destination () port 12867 AF_INET : demo
Recv   SendSend  Utilization   Service 
Demand

Socket Socket  Message  Elapsed  Send Recv SendRecv
Size   SizeSize Time Throughput  localremote   local 
remote

bytes  bytes   bytessecs.10^6bits/s  % S  % S  us/KB   us/KB

 87380  16384  6553630.00  9271.36   2.52 2.72 0.535 
0.576


~$ ./netperf -t TCP_SENDFILE -p 12866 -H destination -c -C -l 30 -- -P 
12867 -m 64K
TCP SENDFILE TEST from 0.0.0.0 (0.0.0.0) port 12867 AF_INET to 
destination () port 12867 AF_INET : demo
Recv   SendSend  Utilization   Service 
Demand

Socket Socket  Message  Elapsed  Send Recv SendRecv
Size   SizeSize Time Throughput  localremote   local 
remote

bytes  bytes   bytessecs.10^6bits/s  % S  % S  us/KB   us/KB

 87380  16384  6553630.00  9332.46   0.82 2.71 0.173 
0.572


It would be good to repeat each a couple times, but in this case at 
least, we see a considerable drop in sending side CPU utilization and 
service demand, the latter being a direct measure of efficiency.


(the socket sizes are simply what they were at the onset of the 
connection, not by the end.  for that, use omni output selectors - 
http://www.netperf.org/svn/netperf2/trunk/doc/netperf.html#Omni-Output-Selection 
- the test-specific -P option is to explicitly select port numbers for 
the data connection to deal with firewalls in my test environment - 
similarly for the global -p option selecting the port number on which 
netserver at destination is waiting)


With a smaller send size  the results may be a bit different:

~$ ./netperf -p 12866 -H destination -c -C -l 30 -- -P 12867
MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 12867 AF_INET to 
destination () port 12867 AF_INET : demo
Recv   SendSend  Utilization   Service 
Demand

Socket Socket  Message  Elapsed  Send Recv SendRecv
Size   SizeSize Time Throughput  localremote   local 
remote

bytes  bytes   bytessecs.10^6bits/s  % S  % S  us/KB   us/KB

 87380  16384  1638430.00  9332.43   2.64 2.74 0.556 
0.578
~$ ./netperf -t TCP_SENDFILE -p 12866 -H destination -c -C -l 30 -- -P 
12867
TCP SENDFILE TEST from 0.0.0.0 (0.0.0.0) port 12867 AF_INET to 
destination () port 12867 AF_INET : demo
Recv   SendSend  Utilization   Service 
Demand

Socket Socket  Message  Elapsed  Send Recv SendRecv
Size   SizeSize Time Throughput  localremote   local 
remote

bytes  bytes   bytessecs.10^6bits/s  % S  % S  us/KB   us/KB

 87380  16384  1638430.00  9351.32   1.26 2.73 0.264 
0.574


Mileage will vary depending on link-type, CPU's present, etc etc etc...

___
Mailing list: https://launchpad.net/~openstack
Post to : openstack@lists.launchpad.net
Unsubscribe : https://launchpad.net/~openstack
More help   : https://help.launchpad.net/ListHelp