<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Exchange Server">
<!-- converted from text --><style><!-- .EmailQuote { margin-left: 1pt; padding-left: 4pt; border-left: #800000 2px solid; } --></style>
</head>
<body>
<meta content="text/html; charset=UTF-8">
<style type="text/css" style="">
<!--
p
        {margin-top:0;
        margin-bottom:0}
-->
</style>
<div dir="ltr">
<div id="x_divtagdefaultwrapper" dir="ltr" style="font-size:12pt; color:#000000; font-family:Calibri,Helvetica,sans-serif">
<p>Ann,</p>
<br>
<p>I would be happy to help with review, etc, on this once it's ready to be posted.</p>
<p><br>
</p>
<p>In the meantime, <span>I am curious about how you handled the compression and the discontiguous set of pages problem.&nbsp; Did you use scatter-gather lists like the encryption code does, or some other solution?</span><br>
</p>
<p><br>
</p>
<p>Are you willing/able to share the current code, perhaps even off list?&nbsp; I certainly understand if not, but I am curious to see how it will work and explore the performance implications.</p>
<p><br>
</p>
<p>- Patrick<br>
</p>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> Anna Fuchs &lt;anna.fuchs@informatik.uni-hamburg.de&gt;<br>
<b>Sent:</b> Thursday, July 27, 2017 3:26:00 AM<br>
<b>To:</b> Patrick Farrell; Xiong, Jinshan<br>
<b>Cc:</b> Matthew Ahrens; Zhuravlev, Alexey; lustre-devel<br>
<b>Subject:</b> Re: [lustre-devel] Design proposal for client-side compression</font>
<div>&nbsp;</div>
</div>
</div>
<font size="2"><span style="font-size:10pt;">
<div class="PlainText">Patrick, <br>
<br>
&gt; Having reread your LAD presentation (I was there, but it's been a<br>
&gt; while...), I think you've got a good architecture.<br>
<br>
There have been some changes since that, but the general things should<br>
be the same.<br>
<br>
&gt; A few thoughts.<br>
&gt; <br>
&gt; 1. Jinshan was just suggesting including in the code a switch to<br>
&gt; enable/disable the feature at runtime, for an example, see his fast<br>
&gt; read patch:<br>
&gt; <a href="https://review.whamcloud.com/#/c/20255/">https://review.whamcloud.com/#/c/20255/</a><br>
&gt; Especially the proc section:<br>
&gt; <a href="https://review.whamcloud.com/#/c/20255/7/lustre/llite/lproc_llite.c">https://review.whamcloud.com/#/c/20255/7/lustre/llite/lproc_llite.c</a><br>
&gt; The effect of that is a file in proc that one can use to<br>
&gt; disable/enable the feature by echoing 0 or 1.<br>
&gt; (I think there is probably a place for tuning beyond that, but that's<br>
&gt; separate.)<br>
&gt; This is great for features that may have complex impacts, and also<br>
&gt; for people who want to test a feature to see how it changes things.<br>
<br>
Oh, I misunderstood Jinshan last time, sorry. Yes, it would be much<br>
easier for users and should be possible. Thank you for references!<br>
<br>
&gt; 2. Lustre clients iterate over the stripes, basically.<br>
&gt; <br>
&gt; Here's an explanation of the write path on the client that should<br>
&gt; help.&nbsp; This explanation is heavily simplified and incorrect in some<br>
&gt; of the details, but should be accurate enough for your question.<br>
&gt; The I/O model on the client (for buffered I/O, direct I/O is<br>
&gt; different) is that the writing process (userspace process) starts an<br>
&gt; I/O, then identifies which parts of the I/O go to which stripes, gets<br>
&gt; the locks it needs, then copies the data through the page cache... <br>
&gt; Once the data is copied to the page cache, Lustre then works on<br>
&gt; writing out that data.&nbsp; In general, it does it asynchronously, where<br>
&gt; the userspace process returns and then data write-out is handled by<br>
&gt; the ptlrpcd (daemon) threads, but in various exceptional conditions<br>
&gt; it may do the write-out in the userspace process.<br>
&gt; <br>
&gt; In general, the write out is going to happen in parallel (to<br>
&gt; different OSTs) with different ptlrpcd threads taking different<br>
&gt; chunks of data and putting them on the wire, and sometimes the<br>
&gt; userspace thread doing that work for some of the data as well.<br>
&gt; <br>
&gt; So &quot;How much memory do we need at most at the same time?&quot; is not a<br>
&gt; question with an easy answer.&nbsp; When doing a bulk RPC, generally, the<br>
&gt; sender sends an RPC announcing the bulk data is ready, then the<br>
&gt; recipient copies the data (RDMA) (or the sender sends it over to a<br>
&gt; buffer if no RDMA) and announces to the client it has done so.&nbsp; I'm<br>
&gt; not 100% clear on the sequencing here, but the key thing is there's a<br>
&gt; time where we've sent the RPC but we aren't done with the buffer.&nbsp; So<br>
&gt; we can send another RPC before that buffer is retired.&nbsp; (If I've got<br>
&gt; this badly wrong, I hope someone will correct me.<br>
&gt; <br>
&gt; So the total amount of memory required to do this is going to depend<br>
&gt; on how fast data is being sent, rather than on the # of OSTs or any<br>
&gt; other constant.<br>
&gt; <br>
&gt; There *is* a per OST limit to how many RPCs a client can have in<br>
&gt; flight at once, but it's generally set so the client can get good<br>
&gt; performance to one OST.&nbsp; Allocating data for max_rpcs_in_flight*num<br>
&gt; OSTs would be far too much, because in the 1000 OST case, a client<br>
&gt; can probably only have a few hundred RPCs in flight (if that...) at<br>
&gt; once on a normal network.<br>
&gt; <br>
&gt; But if we are writing from one client to many OSTs, how many RPCs are<br>
&gt; in flight at once is going to depend more on how fast our network is<br>
&gt; (or, possibly, CPU on the client if the network is fast and/or CPU is<br>
&gt; slow) than any explicit limits.&nbsp; The explicit limits are much higher<br>
&gt; than we will hit in practice.<br>
&gt; <br>
&gt; Does that make sense?&nbsp; It doesn't make your problem any easier...<br>
<br>
Totally, and you are right, it is more complex than I hoped. <br>
<br>
&gt; <br>
&gt; It actually seems like maybe a global pool of pages *is* the right<br>
&gt; answer.&nbsp; The question is how big to make it...<br>
&gt; What about making it grow on demand up to a configurable upper limit?<br>
&gt; <br>
&gt; The allocation code for encryption is here (it's pretty complicated<br>
&gt; and it works on the assumption that it must get pages or return<br>
&gt; ENOMEM - The compression code doesn't absolutely have to get pages,<br>
&gt; so it could be changed):<br>
&gt; sptlrpc_enc_pool_get_pages<br>
&gt; <br>
&gt; It seems like maybe that code could be adjusted to serve both the<br>
&gt; encryption case (must not fail, if it can't get memory, return<br>
&gt; -ENOMEM to cause retries), and the compression case (can fail, if it<br>
&gt; fails, should not do compression...&nbsp; Maybe should consume less<br>
&gt; memory)<br>
<br>
Currently we are not very close to the sptlrpc layer and do not use any<br>
of the encryption structures (it was initially planned, but turned out<br>
differently). But we have already looked at those pools.<br>
<br>
&gt; <br>
&gt; About thread counts:<br>
&gt; Encryption is handled in the ptlrpc code, and your presentation noted<br>
&gt; the plan is to mimic that, which sounds good to me.&nbsp; That means<br>
&gt; there's no reason for you to explicitly control the number of threads<br>
&gt; doing compression, the same number of threads doing sending will be<br>
&gt; doing compression, which seems fine.&nbsp; (Unless there's some point of<br>
&gt; contention in the compression code, but that seems unlikely...)<br>
<br>
We currently intervene before the request is created<br>
(osc_brw_prep_request) but still we don't do anything explicitly with<br>
threads, just put some more tasks to the existing ones. Limited<br>
resources is more the later part where we will optimize, tune and<br>
introduce the adaptive part. <br>
<br>
&gt; <br>
&gt; Hope that helps a bit.<br>
<br>
It helps a lot! Thank you!<br>
<br>
Anna<br>
</div>
</span></font>
</body>
</html>