<div dir="ltr">Thanks for the suggestion!<div><br></div><div style>My testfiles are a few bytes each, so the max-file-size setting doesn&#39;t apply, unfortunately.</div><div style><br></div><div style>Disabling quick-read for the gluster client mount indeed gives a bit lower latency, but it still isn&#39;t better than the Gluster NFS client (or using the native Linux NFS server, for that matter).</div>
<div style><br></div><div style>Cheers!</div><div style>//Willem</div><div style><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Apr 24, 2013 at 5:31 AM, Raghavendra Gowdappa <span dir="ltr">&lt;<a href="mailto:rgowdapp@redhat.com" target="_blank">rgowdapp@redhat.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi willem,<br>
<br>
Please find the inlined comments:<br>
<div><div class="h5"><br>
----- Original Message -----<br>
&gt; From: &quot;Willem&quot; &lt;<a href="mailto:gwillem@gmail.com">gwillem@gmail.com</a>&gt;<br>
&gt; To: <a href="mailto:gluster-users@gluster.org">gluster-users@gluster.org</a><br>
&gt; Sent: Thursday, April 18, 2013 11:58:46 PM<br>
&gt; Subject: [Gluster-users] Low (&lt;0.2ms) latency reads, is it possible at all?<br>
&gt;<br>
&gt; I&#39;m testing GlusterFS viability for use with a typical PHP webapp (ie. lots<br>
&gt; of small files). I don&#39;t care so much for the C in the CAP theorem, as I<br>
&gt; have very few writes. I could live with a write propagation delay of 5<br>
&gt; minutes (or dirty caches for up to 5 minutes).<br>
&gt;<br>
&gt; So I&#39;m optimizing for low latency reads of small files. My testsetup is 2<br>
&gt; node replication. Each node is both server and gluster client. Both are in<br>
&gt; sync. I stop glusterfs-server @ node2. @node1, I run a simple benchmark:<br>
&gt; repeatedly (to prime the cache) open &amp; close 1000 small files. I have<br>
&gt; enabled the client-side io-cache and quick-read translators (see below for<br>
&gt; config).<br>
&gt;<br>
&gt; The results are consistently 2 ms per open (O_RDONLY) call. Which is too<br>
&gt; slow, unfortunately, as I need &lt; 0.2ms.<br>
&gt;<br>
&gt; The same test with a local Gluster server and NFS mount, I get somewhat<br>
&gt; better performance but still 0.6ms.<br>
&gt;<br>
&gt; The same test with Linux NFS server (v3) and local mount, I get 0.12ms per<br>
&gt; open.<br>
&gt;<br>
&gt; I can&#39;t explain the lag using Gluster, because I can&#39;t see any traffic being<br>
&gt; sent to node2. I would expect that using the io-cache translator and<br>
&gt; local-only operation, the performance would approach that of the kernel FS<br>
&gt; cache.<br>
&gt;<br>
&gt; Is this assumption correct? If yes, how would I profile the client sub system<br>
&gt; to detect the bottleneck?<br>
&gt;<br>
&gt; If no, then I have to accept that 0.8ms open calls are the best that I could<br>
&gt; squeeze out of this system. Then I&#39;ll probably look into AFS, userspace<br>
&gt; async replication or gluster NFS mount with cachefilesd. Which would you<br>
&gt; recommend?<br>
&gt;<br>
&gt; Thanks a lot!<br>
&gt; BTW I like Gluster a lot, and hope that it is also suitable for this small<br>
&gt; files use case ;)<br>
&gt;<br>
&gt; //Willem<br>
&gt;<br>
&gt; PS Am testing with kernel 3.5.0-17-generic 64bit and gluster 3.2.5-1ubuntu1.<br>
&gt;<br>
&gt; Client volfile:<br>
&gt; +------------------------------------------------------------------------------+<br>
&gt; 1: volume testvol-client-0<br>
&gt; 2: type protocol/client<br>
&gt; 3: option remote-host g1<br>
&gt; 4: option remote-subvolume /data<br>
&gt; 5: option transport-type tcp<br>
&gt; 6: end-volume<br>
&gt; 7:<br>
&gt; 8: volume testvol-client-1<br>
&gt; 9: type protocol/client<br>
&gt; 10: option remote-host g2<br>
&gt; 11: option remote-subvolume /data<br>
&gt; 12: option transport-type tcp<br>
&gt; 13: end-volume<br>
&gt; 14:<br>
&gt; 15: volume testvol-replicate-0<br>
&gt; 16: type cluster/replicate<br>
&gt; 17: subvolumes testvol-client-0 testvol-client-1<br>
&gt; 18: end-volume<br>
&gt; 19:<br>
&gt; 20: volume testvol-write-behind<br>
&gt; 21: type performance/write-behind<br>
&gt; 22: option flush-behind on<br>
&gt; 23: subvolumes testvol-replicate-0<br>
&gt; 24: end-volume<br>
&gt; 25:<br>
&gt; 26: volume testvol-io-cache<br>
&gt; 27: type performance/io-cache<br>
&gt; 28: option max-file-size 256KB<br>
&gt; 29: option cache-timeout 60<br>
&gt; 30: option priority *.php:3,*:0<br>
&gt; 31: option cache-size 256MB<br>
&gt; 32: subvolumes testvol-write-behind<br>
&gt; 33: end-volume<br>
&gt; 34:<br>
&gt; 35: volume testvol-quick-read<br>
&gt; 36: type performance/quick-read<br>
<br>
</div></div>default value for option &quot;max-file-size&quot; is 64KB. Seems like your files are bigger than 64KB. Can you add this option and rerun the tests? Also can you rerun the tests by disabling quick-read and compare the results?<br>

<div><div class="h5"><br>
&gt; 37: option cache-size 256MB<br>
&gt; 38: subvolumes testvol-io-cache<br>
&gt; 39: end-volume<br>
&gt; 40:<br>
&gt; 41: volume testvol<br>
&gt; 42: type debug/io-stats<br>
&gt; 43: option latency-measurement off<br>
&gt; 44: option count-fop-hits off<br>
&gt; 45: subvolumes testvol-quick-read<br>
&gt; 46: end-volume<br>
&gt;<br>
&gt; Server volfile:<br>
&gt; +------------------------------------------------------------------------------+<br>
&gt; 1: volume testvol-posix<br>
&gt; 2: type storage/posix<br>
&gt; 3: option directory /data<br>
&gt; 4: end-volume<br>
&gt; 5:<br>
&gt; 6: volume testvol-access-control<br>
&gt; 7: type features/access-control<br>
&gt; 8: subvolumes testvol-posix<br>
&gt; 9: end-volume<br>
&gt; 10:<br>
&gt; 11: volume testvol-locks<br>
&gt; 12: type features/locks<br>
&gt; 13: subvolumes testvol-access-control<br>
&gt; 14: end-volume<br>
&gt; 15:<br>
&gt; 16: volume testvol-io-threads<br>
&gt; 17: type performance/io-threads<br>
&gt; 18: subvolumes testvol-locks<br>
&gt; 19: end-volume<br>
&gt; 20:<br>
&gt; 21: volume testvol-marker<br>
&gt; 22: type features/marker<br>
&gt; 23: option volume-uuid bc89684f-569c-48b0-bc67-09bfd30ba253<br>
&gt; 24: option timestamp-file /etc/glusterd/vols/testvol/marker.tstamp<br>
&gt; 25: option xtime off<br>
&gt; 26: option quota off<br>
&gt; 27: subvolumes testvol-io-threads<br>
&gt; 28: end-volume<br>
&gt; 29:<br>
&gt; 30: volume /data<br>
&gt; 31: type debug/io-stats<br>
&gt; 32: option latency-measurement off<br>
&gt; 33: option count-fop-hits off<br>
&gt; 34: subvolumes testvol-marker<br>
&gt; 35: end-volume<br>
&gt; 36:<br>
&gt; 37: volume testvol-server<br>
&gt; 38: type protocol/server<br>
&gt; 39: option transport-type tcp<br>
&gt; 40: option auth.addr./data.allow *<br>
&gt; 41: subvolumes /data<br>
&gt; 42: end-volume<br>
&gt;<br>
&gt; My benchmark to simulate PHP webapp i/o:<br>
&gt; #!/usr/bin/env python<br>
&gt;<br>
&gt; import sys<br>
&gt; import os<br>
&gt; import time<br>
&gt; import optparse<br>
&gt;<br>
&gt; def print_timing(func):<br>
&gt; def wrapper(*arg):<br>
&gt; t1 = time.time()<br>
&gt; res = func(*arg)<br>
&gt; t2 = time.time()<br>
&gt; print &#39;%-15.15s %6d ms&#39; % (func.func_name, int ( (t2-t1)*1000.0 ))<br>
&gt; return res<br>
&gt; return wrapper<br>
&gt;<br>
&gt;<br>
&gt; def parse_options():<br>
&gt; parser = optparse.OptionParser()<br>
&gt; parser.add_option(&quot;--path&quot;, &#39;-p&#39;, default=&quot;/mnt/glusterfs&quot;,<br>
&gt; help=&quot;Base directory for running tests (default: /mnt/glusterfs)&quot;,<br>
&gt; )<br>
&gt; parser.add_option(&quot;--num&quot;, &#39;-n&#39;, type=&quot;int&quot;, default=100,<br>
&gt; help=&quot;Number of files per test (default: 100)&quot;,<br>
&gt; )<br>
&gt; (options, args) = parser.parse_args()<br>
&gt; return options<br>
&gt;<br>
&gt; class FSBench():<br>
&gt; def __init__(self,path=&quot;/tmp&quot;,num=100):<br>
&gt; self.path = path<br>
&gt; self.num = num<br>
&gt; @print_timing<br>
&gt; def test_open_read(self):<br>
&gt; for filename in self.get_files():<br>
&gt; f = open(filename)<br>
&gt; data = f.read()<br>
&gt; f.close()<br>
&gt; def get_files(self):<br>
&gt; for i in range(self.num):<br>
&gt; filename = self.path + &quot;/test_%03d&quot; % i<br>
&gt; yield filename<br>
&gt; @print_timing<br>
&gt; def test_stat(self):<br>
&gt; for filename in self.get_files():<br>
&gt; os.stat(filename)<br>
&gt;<br>
&gt; @print_timing<br>
&gt; def test_stat_nonexist(self):<br>
&gt; for filename in self.get_files():<br>
&gt; try:<br>
&gt; os.stat(filename+&quot;blkdsflskdf&quot;)<br>
&gt; except OSError:<br>
&gt; pass<br>
&gt; @print_timing<br>
&gt; def test_write(self):<br>
&gt; for filename in self.get_files():<br>
&gt; f = open(filename,&#39;w&#39;)<br>
&gt; f.write(&#39;hi there\n&#39;)<br>
&gt; f.close()<br>
&gt; @print_timing<br>
&gt; def test_delete(self):<br>
&gt; for filename in self.get_files():<br>
&gt; os.unlink(filename)<br>
&gt; if __name__ == &#39;__main__&#39;:<br>
&gt;<br>
&gt; options = parse_options()<br>
&gt; bench = FSBench(path=options.path, num=options.num)<br>
&gt; bench.test_write()<br>
&gt; bench.test_open_read()<br>
&gt; bench.test_stat()<br>
&gt; bench.test_stat_nonexist()<br>
&gt; bench.test_delete()<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
</div></div>&gt; _______________________________________________<br>
&gt; Gluster-users mailing list<br>
&gt; <a href="mailto:Gluster-users@gluster.org">Gluster-users@gluster.org</a><br>
&gt; <a href="http://supercolony.gluster.org/mailman/listinfo/gluster-users" target="_blank">http://supercolony.gluster.org/mailman/listinfo/gluster-users</a><br>
</blockquote></div><br></div>