<div dir="ltr"><div class="markdown-here-wrapper" style=""><p style="margin:1.2em 0px!important">On Wed, Jan 6, 2016 at 10:05 AM, Volker Braun <<a href="mailto:vbraun.name@gmail.com" target="_blank">vbraun.name@gmail.com</a>> wrote:</p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr">IMHO output capture into a web browser isn't really different from the scrollback buffer of a terminal. We obviously enjoy the infinite scrollback but do not want an unbounded drawing surface in the terminal (= dom nodes in the web browser). And certainly nobody wants a piece of their output discarded in a long-running computation. <div><br></div><div>The technical implementation is virtual scrolling, this is what the terminal does and this is how the browser should do it, too.</div></div></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<p style="margin:1.2em 0px!important">Jon mentioned that there are a few levels for large output to cause problems. The lowest bar is putting the output on the page, which is by far the easiest to hit, causing an unresponsive browser. This is the level that can be addressed by virtual scrolling / truncating output in UI. Fortunately, it’s also the easiest one to implement.</p>
<p style="margin:1.2em 0px!important">If we truncate instead of virtual-scroll, then we have a choice for whether truncated output is included in the document or not, which alleviates the problem of opening notebooks that have a problematic amount of output. But it’s putting that on the page that’s ~always the problem, not loading the notebook JSON itself, so I’m somewhat less concerned about that.</p>
<p style="margin:1.2em 0px!important">The next level where it can cause problems is the output coming over the network in the first place. We can throttle this in the notebook server, as was implemented <a href="https://github.com/jupyter/notebook/pull/506">for 4.2</a> months ago. Again, this moves the bar for when output causes trouble, but isn’t a complete solution. Dumping truncated output to a file is complicated a bit by the separations we have in place, but it should be doable.</p>
<p style="margin:1.2em 0px!important">-MinRK</p>
<p style="margin:1.2em 0px!important"></p><div class="markdown-here-exclude"><p></p><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div><div><span class=""><br><br>On Tuesday, January 5, 2016 at 8:21:53 PM UTC+1, Jason Grout wrote:</span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><span class=""><div>(cross-posting to ipython-dev)</div><div><br></div>Jon,<div><br></div><div>At the recent San Francisco meetings, we talked about this. What do you think about:</div><div><br></div><div>1. keeping track of the size of the io messages sent from any specific kernel execution</div><div>2. When the total size of io reaches some specific size (user-configurable), transmitting a special "throwing away output, but here's how to save the output to a file if you want in the future, or how to increase the limit" message</div><div>3. keep a running buffer of the last bit of output attempted to be sent, and send it when the execution finishes (so basically a ring buffer that overwrites the oldest message)</div><div><br></div><div>This:</div><div><br></div><div>* allows small output through</div><div>* provides an explanatory message</div><div>* provides the last bit of output as well</div><div><br></div><div>One thing to figure out: a limit on size of output that is text may not be appropriate for output that is images, etc.</div><div><br></div><div>Thanks,</div><div><br></div><div>Jason</div></span><div><br><div><br><div class="gmail_quote"><span class="">On Tue, Jan 5, 2016 at 12:11 PM, Jason Grout <span dir="ltr"><<a rel="nofollow">ja...@jasongrout.org</a>></span> wrote:<br></span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div><div><div dir="ltr"><br><div class="gmail_quote"><span class="">---------- Forwarded message ----------<br>From: <b class="gmail_sendername">Jonathan Frederic</b> <span dir="ltr"><<a rel="nofollow">jon.f...@gmail.com</a>></span><br>Date: Tue, Jan 5, 2016 at 11:42 AM<br>Subject: Re: [sage-devel] Re: Jupyter notebook by default?<br></span><span class="">To: Jason Grout <<a rel="nofollow">grout...@gmail.com</a>><br>Cc: sage-devel <<a rel="nofollow">sage-...@googlegroups.com</a>><br><br><br><div dir="ltr">Jason,<div><br></div><div>Thanks for pulling me in on this. </div><div><br></div><div>William,</div><div><br></div><div>I agree, getting a bunch of people to agree on stuff can seem impossible. However, you mention Sage offers a couple options to mitigate output overflows, can you point me to those options? The Jupyter Notebook should provide multiple options too - this will also make it easier for everyone to agree.</div><div><br></div><div>Also, in you experience, which of these options work the best? </div><div><br></div><div>I was thinking initially of doing something simple, like hard limiting data/time, then printing an error if that's exceeded. In the Jupyter Notebook, we have to worry about</div><div>- Too many messages sent on the websocket</div><div>- The notebook json file growing too large and consequently becoming unopenable</div><div>- Too much data being appended to the DOM, crashing the browser</div><div><br></div><div><br></div><div>Thanks!</div><div>-Jon</div></div></span><span class=""><div><div><div><br><div class="gmail_quote">On Tue, Jan 5, 2016 at 10:19 AM, Jason Grout <span dir="ltr"><<a rel="nofollow">grout...@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br><br>On Tuesday, January 5, 2016 at 8:17:45 AM UTC-7, William wrote:<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><br>One example of a subtle feature in Sage (notebook and worksheets) not
<br>in Jupyter, which I was just reminded of, is output limiting. In Sage
<br>there are numerous rules/options to deal with people doing stuff like:
<br>
<br>while True:
<br> print "hi!"
<br>
<br>... which is exactly what students will tend to do by accident...
<br>Jupyter doesn't deal with this, but it might not be too hard to
<br>implement in theory. One of the main problems is figuring out what
<br>the arbitrary rate limiting defaults "should" be; it's arbitrary, and
<br>depends a lot on whether everything is local, over the web, etc. so
<br>getting a bunch of people to agree is hard, which might mean they will
<br>never implement anything.
<br></blockquote><div><br></div><div><br></div><div>William,</div><div><br></div><div>Jon Frederic in the Jupyter dev meeting happening right now said that he will be working on output limiting as one of his next things.</div><span><font color="#888888"><div><br></div><div>Jason</div></font></span></blockquote></div><br></div>
</div></div></span></div><br></div>
</div></div></blockquote></div><br></div></div></div>
</blockquote></div></div></div><br>_______________________________________________<br>
IPython-dev mailing list<br>
<a href="mailto:IPython-dev@scipy.org">IPython-dev@scipy.org</a><br>
<a href="https://mail.scipy.org/mailman/listinfo/ipython-dev" rel="noreferrer" target="_blank">https://mail.scipy.org/mailman/listinfo/ipython-dev</a><br>
<br></blockquote><p></p></div><p style="margin:1.2em 0px!important"></p>
<div title="MDH:PGJyPjxkaXYgY2xhc3M9ImdtYWlsX2V4dHJhIj48YnI+PGRpdiBjbGFzcz0iZ21haWxfcXVvdGUi
Pk9uIFdlZCwgSmFuIDYsIDIwMTYgYXQgMTA6MDUgQU0sIFZvbGtlciBCcmF1biA8c3BhbiBkaXI9
Imx0ciI+Jmx0OzxhIGhyZWY9Im1haWx0bzp2YnJhdW4ubmFtZUBnbWFpbC5jb20iIHRhcmdldD0i
X2JsYW5rIj52YnJhdW4ubmFtZUBnbWFpbC5jb208L2E+Jmd0Ozwvc3Bhbj4gd3JvdGU6PGJyPjxi
bG9ja3F1b3RlIGNsYXNzPSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1hcmdpbjogMHB4IDBweCAwcHgg
MC44ZXg7IGJvcmRlci1sZWZ0LXdpZHRoOiAxcHg7IGJvcmRlci1sZWZ0LWNvbG9yOiByZ2IoMjA0
LCAyMDQsIDIwNCk7IGJvcmRlci1sZWZ0LXN0eWxlOiBzb2xpZDsgcGFkZGluZy1sZWZ0OiAxZXg7
Ij48ZGl2IGRpcj0ibHRyIj5JTUhPIG91dHB1dCBjYXB0dXJlIGludG8gYSB3ZWIgYnJvd3NlciBp
c24ndCByZWFsbHkgZGlmZmVyZW50IGZyb20gdGhlIHNjcm9sbGJhY2sgYnVmZmVyIG9mIGEgdGVy
bWluYWwuIFdlIG9idmlvdXNseSBlbmpveSB0aGUgaW5maW5pdGUgc2Nyb2xsYmFjayBidXQgZG8g
bm90IHdhbnQgYW4gdW5ib3VuZGVkIGRyYXdpbmcgc3VyZmFjZSBpbiB0aGUgdGVybWluYWwgKD0g
ZG9tIG5vZGVzIGluIHRoZSB3ZWIgYnJvd3NlcikuIEFuZCBjZXJ0YWlubHkgbm9ib2R5IHdhbnRz
IGEgcGllY2Ugb2YgdGhlaXIgb3V0cHV0IGRpc2NhcmRlZCBpbiBhIGxvbmctcnVubmluZyBjb21w
dXRhdGlvbi4mbmJzcDs8ZGl2Pjxicj48L2Rpdj48ZGl2PlRoZSB0ZWNobmljYWwgaW1wbGVtZW50
YXRpb24gaXMgdmlydHVhbCBzY3JvbGxpbmcsIHRoaXMgaXMgd2hhdCB0aGUgdGVybWluYWwgZG9l
cyBhbmQgdGhpcyBpcyBob3cgdGhlIGJyb3dzZXIgc2hvdWxkIGRvIGl0LCB0b28uPC9kaXY+PC9k
aXY+PC9ibG9ja3F1b3RlPjxkaXY+PGJyPjwvZGl2PjxkaXY+Sm9uIG1lbnRpb25lZCB0aGF0IHRo
ZXJlIGFyZSBhIGZldyBsZXZlbHMgZm9yIGxhcmdlIG91dHB1dCB0byBjYXVzZSBwcm9ibGVtcy4g
VGhlIGxvd2VzdCBiYXIgaXMgcHV0dGluZyB0aGUgb3V0cHV0IG9uIHRoZSBwYWdlLCB3aGljaCBp
cyBieSBmYXIgdGhlIGVhc2llc3QgdG8gaGl0LCBjYXVzaW5nIGFuIHVucmVzcG9uc2l2ZSBicm93
c2VyLiBUaGlzIGlzIHRoZSBsZXZlbCB0aGF0IGNhbiBiZSBhZGRyZXNzZWQgYnkgdmlydHVhbCBz
Y3JvbGxpbmcgLyB0cnVuY2F0aW5nIG91dHB1dCBpbiBVSS4gRm9ydHVuYXRlbHksIGl0J3MgYWxz
byB0aGUgZWFzaWVzdCBvbmUgdG8gaW1wbGVtZW50LjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+
SWYgd2UgdHJ1bmNhdGUgaW5zdGVhZCBvZiB2aXJ0dWFsLXNjcm9sbCwgdGhlbiB3ZSBoYXZlIGEg
Y2hvaWNlIGZvciB3aGV0aGVyIHRydW5jYXRlZCBvdXRwdXQgaXMgaW5jbHVkZWQgaW4gdGhlIGRv
Y3VtZW50IG9yIG5vdCwgd2hpY2ggYWxsZXZpYXRlcyB0aGUgcHJvYmxlbSBvZiBvcGVuaW5nIG5v
dGVib29rcyB0aGF0IGhhdmUgYSBwcm9ibGVtYXRpYyBhbW91bnQgb2Ygb3V0cHV0LiBCdXQgaXQn
cyBwdXR0aW5nIHRoYXQgb24gdGhlIHBhZ2UgdGhhdCdzIH5hbHdheXMgdGhlIHByb2JsZW0sIG5v
dCBsb2FkaW5nIHRoZSBub3RlYm9vayBKU09OIGl0c2VsZiwgc28gSSdtIHNvbWV3aGF0IGxlc3Mg
Y29uY2VybmVkIGFib3V0IHRoYXQuPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5UaGUgbmV4dCBs
ZXZlbCB3aGVyZSBpdCBjYW4gY2F1c2UgcHJvYmxlbXMgaXMgdGhlIG91dHB1dCBjb21pbmcgb3Zl
ciB0aGUgbmV0d29yayBpbiB0aGUgZmlyc3QgcGxhY2UuIFdlIGNhbiB0aHJvdHRsZSB0aGlzIGlu
IHRoZSBub3RlYm9vayBzZXJ2ZXIsIGFzIHdhcyBpbXBsZW1lbnRlZCBbZm9yIDQuMl0oaHR0cHM6
Ly9naXRodWIuY29tL2p1cHl0ZXIvbm90ZWJvb2svcHVsbC81MDYpIG1vbnRocyBhZ28uIEFnYWlu
LCB0aGlzIG1vdmVzIHRoZSBiYXIgZm9yIHdoZW4gb3V0cHV0IGNhdXNlcyB0cm91YmxlLCBidXQg
aXNuJ3QgYSBjb21wbGV0ZSBzb2x1dGlvbi4gRHVtcGluZyB0cnVuY2F0ZWQgb3V0cHV0IHRvIGEg
ZmlsZSBpcyBjb21wbGljYXRlZCBhIGJpdCBieSB0aGUgc2VwYXJhdGlvbnMgd2UgaGF2ZSBpbiBw
bGFjZSwgYnV0IGl0IHNob3VsZCBiZSBkb2FibGUuPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj4t
TWluUks8L2Rpdj48ZGl2PiZuYnNwOzwvZGl2PjxibG9ja3F1b3RlIGNsYXNzPSJnbWFpbF9xdW90
ZSIgc3R5bGU9Im1hcmdpbjogMHB4IDBweCAwcHggMC44ZXg7IGJvcmRlci1sZWZ0LXdpZHRoOiAx
cHg7IGJvcmRlci1sZWZ0LWNvbG9yOiByZ2IoMjA0LCAyMDQsIDIwNCk7IGJvcmRlci1sZWZ0LXN0
eWxlOiBzb2xpZDsgcGFkZGluZy1sZWZ0OiAxZXg7Ij48ZGl2IGRpcj0ibHRyIj48ZGl2PjxkaXY+
PHNwYW4gY2xhc3M9IiI+PGJyPjxicj5PbiBUdWVzZGF5LCBKYW51YXJ5IDUsIDIwMTYgYXQgODoy
MTo1MyBQTSBVVEMrMSwgSmFzb24gR3JvdXQgd3JvdGU6PC9zcGFuPjxibG9ja3F1b3RlIGNsYXNz
PSJnbWFpbF9xdW90ZSIgc3R5bGU9Im1hcmdpbjogMHB4IDBweCAwcHggMC44ZXg7IGJvcmRlci1s
ZWZ0LXdpZHRoOiAxcHg7IGJvcmRlci1sZWZ0LWNvbG9yOiByZ2IoMjA0LCAyMDQsIDIwNCk7IGJv
cmRlci1sZWZ0LXN0eWxlOiBzb2xpZDsgcGFkZGluZy1sZWZ0OiAxZXg7Ij48ZGl2IGRpcj0ibHRy
Ij48c3BhbiBjbGFzcz0iIj48ZGl2Pihjcm9zcy1wb3N0aW5nIHRvIGlweXRob24tZGV2KTwvZGl2
PjxkaXY+PGJyPjwvZGl2Pkpvbiw8ZGl2Pjxicj48L2Rpdj48ZGl2PkF0IHRoZSByZWNlbnQgU2Fu
IEZyYW5jaXNjbyBtZWV0aW5ncywgd2UgdGFsa2VkIGFib3V0IHRoaXMuJm5ic3A7IFdoYXQgZG8g
eW91IHRoaW5rIGFib3V0OjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+MS4ga2VlcGluZyB0cmFj
ayBvZiB0aGUgc2l6ZSBvZiB0aGUgaW8gbWVzc2FnZXMgc2VudCBmcm9tIGFueSBzcGVjaWZpYyBr
ZXJuZWwgZXhlY3V0aW9uPC9kaXY+PGRpdj4yLiBXaGVuIHRoZSB0b3RhbCBzaXplIG9mIGlvIHJl
YWNoZXMgc29tZSBzcGVjaWZpYyBzaXplICh1c2VyLWNvbmZpZ3VyYWJsZSksIHRyYW5zbWl0dGlu
ZyBhIHNwZWNpYWwgInRocm93aW5nIGF3YXkgb3V0cHV0LCBidXQgaGVyZSdzIGhvdyB0byBzYXZl
IHRoZSBvdXRwdXQgdG8gYSBmaWxlIGlmIHlvdSB3YW50IGluIHRoZSBmdXR1cmUsIG9yIGhvdyB0
byBpbmNyZWFzZSB0aGUgbGltaXQiIG1lc3NhZ2U8L2Rpdj48ZGl2PjMuIGtlZXAgYSBydW5uaW5n
IGJ1ZmZlciBvZiB0aGUgbGFzdCBiaXQgb2Ygb3V0cHV0IGF0dGVtcHRlZCB0byBiZSBzZW50LCBh
bmQgc2VuZCBpdCB3aGVuIHRoZSBleGVjdXRpb24gZmluaXNoZXMgKHNvIGJhc2ljYWxseSBhIHJp
bmcgYnVmZmVyIHRoYXQgb3ZlcndyaXRlcyB0aGUgb2xkZXN0IG1lc3NhZ2UpPC9kaXY+PGRpdj48
YnI+PC9kaXY+PGRpdj5UaGlzOjwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+KiBhbGxvd3Mgc21h
bGwgb3V0cHV0IHRocm91Z2g8L2Rpdj48ZGl2PiogcHJvdmlkZXMgYW4gZXhwbGFuYXRvcnkgbWVz
c2FnZTwvZGl2PjxkaXY+KiBwcm92aWRlcyB0aGUgbGFzdCBiaXQgb2Ygb3V0cHV0IGFzIHdlbGw8
L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2Pk9uZSB0aGluZyB0byBmaWd1cmUgb3V0OiBhIGxpbWl0
IG9uIHNpemUgb2Ygb3V0cHV0IHRoYXQgaXMgdGV4dCBtYXkgbm90IGJlIGFwcHJvcHJpYXRlIGZv
ciBvdXRwdXQgdGhhdCBpcyBpbWFnZXMsIGV0Yy48L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2PlRo
YW5rcyw8L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2Pkphc29uPC9kaXY+PC9zcGFuPjxkaXY+PGJy
PjxkaXY+PGJyPjxkaXYgY2xhc3M9ImdtYWlsX3F1b3RlIj48c3BhbiBjbGFzcz0iIj5PbiBUdWUs
IEphbiA1LCAyMDE2IGF0IDEyOjExIFBNLCBKYXNvbiBHcm91dCA8c3BhbiBkaXI9Imx0ciI+Jmx0
OzxhIHJlbD0ibm9mb2xsb3ciPmphLi4uQGphc29uZ3JvdXQub3JnPC9hPiZndDs8L3NwYW4+IHdy
b3RlOjxicj48L3NwYW4+PGJsb2NrcXVvdGUgY2xhc3M9ImdtYWlsX3F1b3RlIiBzdHlsZT0ibWFy
Z2luOiAwcHggMHB4IDBweCAwLjhleDsgYm9yZGVyLWxlZnQtd2lkdGg6IDFweDsgYm9yZGVyLWxl
ZnQtY29sb3I6IHJnYigyMDQsIDIwNCwgMjA0KTsgYm9yZGVyLWxlZnQtc3R5bGU6IHNvbGlkOyBw
YWRkaW5nLWxlZnQ6IDFleDsiPjxkaXY+PGRpdj48ZGl2IGRpcj0ibHRyIj48YnI+PGRpdiBjbGFz
cz0iZ21haWxfcXVvdGUiPjxzcGFuIGNsYXNzPSIiPi0tLS0tLS0tLS0gRm9yd2FyZGVkIG1lc3Nh
Z2UgLS0tLS0tLS0tLTxicj5Gcm9tOiA8YiBjbGFzcz0iZ21haWxfc2VuZGVybmFtZSI+Sm9uYXRo
YW4gRnJlZGVyaWM8L2I+IDxzcGFuIGRpcj0ibHRyIj4mbHQ7PGEgcmVsPSJub2ZvbGxvdyI+am9u
LmYuLi5AZ21haWwuY29tPC9hPiZndDs8L3NwYW4+PGJyPkRhdGU6IFR1ZSwgSmFuIDUsIDIwMTYg
YXQgMTE6NDIgQU08YnI+U3ViamVjdDogUmU6IFtzYWdlLWRldmVsXSBSZTogSnVweXRlciBub3Rl
Ym9vayBieSBkZWZhdWx0Pzxicj48L3NwYW4+PHNwYW4gY2xhc3M9IiI+VG86IEphc29uIEdyb3V0
ICZsdDs8YSByZWw9Im5vZm9sbG93Ij5ncm91dC4uLkBnbWFpbC5jb208L2E+Jmd0Ozxicj5DYzog
c2FnZS1kZXZlbCAmbHQ7PGEgcmVsPSJub2ZvbGxvdyI+c2FnZS0uLi5AZ29vZ2xlZ3JvdXBzLmNv
bTwvYT4mZ3Q7PGJyPjxicj48YnI+PGRpdiBkaXI9Imx0ciI+SmFzb24sPGRpdj48YnI+PC9kaXY+
PGRpdj5UaGFua3MgZm9yIHB1bGxpbmcgbWUgaW4gb24gdGhpcy4gJm5ic3A7PC9kaXY+PGRpdj48
YnI+PC9kaXY+PGRpdj5XaWxsaWFtLDwvZGl2PjxkaXY+PGJyPjwvZGl2PjxkaXY+SSBhZ3JlZSwg
Z2V0dGluZyBhIGJ1bmNoIG9mIHBlb3BsZSB0byBhZ3JlZSBvbiBzdHVmZiBjYW4gc2VlbSBpbXBv
c3NpYmxlLiZuYnNwOyBIb3dldmVyLCB5b3UgbWVudGlvbiBTYWdlIG9mZmVycyBhIGNvdXBsZSBv
cHRpb25zIHRvIG1pdGlnYXRlIG91dHB1dCBvdmVyZmxvd3MsIGNhbiB5b3UgcG9pbnQgbWUgdG8g
dGhvc2Ugb3B0aW9ucz8mbmJzcDsgVGhlIEp1cHl0ZXIgTm90ZWJvb2sgc2hvdWxkIHByb3ZpZGUg
bXVsdGlwbGUgb3B0aW9ucyB0b28gLSB0aGlzIHdpbGwgYWxzbyBtYWtlIGl0IGVhc2llciBmb3Ig
ZXZlcnlvbmUgdG8gYWdyZWUuPC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5BbHNvLCBpbiB5b3Ug
ZXhwZXJpZW5jZSwgd2hpY2ggb2YgdGhlc2Ugb3B0aW9ucyB3b3JrIHRoZSBiZXN0PyAmbmJzcDs8
L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2Pkkgd2FzIHRoaW5raW5nIGluaXRpYWxseSBvZiBkb2lu
ZyBzb21ldGhpbmcgc2ltcGxlLCBsaWtlIGhhcmQgbGltaXRpbmcgZGF0YS90aW1lLCB0aGVuIHBy
aW50aW5nIGFuIGVycm9yIGlmIHRoYXQncyBleGNlZWRlZC4mbmJzcDsgSW4gdGhlIEp1cHl0ZXIg
Tm90ZWJvb2ssIHdlIGhhdmUgdG8gd29ycnkgYWJvdXQ8L2Rpdj48ZGl2Pi0gVG9vIG1hbnkgbWVz
c2FnZXMgc2VudCBvbiB0aGUgd2Vic29ja2V0PC9kaXY+PGRpdj4tIFRoZSBub3RlYm9vayBqc29u
IGZpbGUgZ3Jvd2luZyB0b28gbGFyZ2UgYW5kIGNvbnNlcXVlbnRseSBiZWNvbWluZyB1bm9wZW5h
YmxlPC9kaXY+PGRpdj4tIFRvbyBtdWNoIGRhdGEgYmVpbmcgYXBwZW5kZWQgdG8gdGhlIERPTSwg
Y3Jhc2hpbmcgdGhlIGJyb3dzZXI8L2Rpdj48ZGl2Pjxicj48L2Rpdj48ZGl2Pjxicj48L2Rpdj48
ZGl2PlRoYW5rcyE8L2Rpdj48ZGl2Pi1Kb248L2Rpdj48L2Rpdj48L3NwYW4+PHNwYW4gY2xhc3M9
IiI+PGRpdj48ZGl2PjxkaXY+PGJyPjxkaXYgY2xhc3M9ImdtYWlsX3F1b3RlIj5PbiBUdWUsIEph
biA1LCAyMDE2IGF0IDEwOjE5IEFNLCBKYXNvbiBHcm91dCA8c3BhbiBkaXI9Imx0ciI+Jmx0Ozxh
IHJlbD0ibm9mb2xsb3ciPmdyb3V0Li4uQGdtYWlsLmNvbTwvYT4mZ3Q7PC9zcGFuPiB3cm90ZTo8
YnI+PGJsb2NrcXVvdGUgY2xhc3M9ImdtYWlsX3F1b3RlIiBzdHlsZT0ibWFyZ2luOiAwcHggMHB4
IDBweCAwLjhleDsgYm9yZGVyLWxlZnQtd2lkdGg6IDFweDsgYm9yZGVyLWxlZnQtY29sb3I6IHJn
YigyMDQsIDIwNCwgMjA0KTsgYm9yZGVyLWxlZnQtc3R5bGU6IHNvbGlkOyBwYWRkaW5nLWxlZnQ6
IDFleDsiPjxicj48YnI+T24gVHVlc2RheSwgSmFudWFyeSA1LCAyMDE2IGF0IDg6MTc6NDUgQU0g
VVRDLTcsIFdpbGxpYW0gd3JvdGU6PGJsb2NrcXVvdGUgY2xhc3M9ImdtYWlsX3F1b3RlIiBzdHls
ZT0ibWFyZ2luOiAwcHggMHB4IDBweCAwLjhleDsgYm9yZGVyLWxlZnQtd2lkdGg6IDFweDsgYm9y
ZGVyLWxlZnQtY29sb3I6IHJnYigyMDQsIDIwNCwgMjA0KTsgYm9yZGVyLWxlZnQtc3R5bGU6IHNv
bGlkOyBwYWRkaW5nLWxlZnQ6IDFleDsiPjxicj5PbmUgZXhhbXBsZSBvZiBhIHN1YnRsZSBmZWF0
dXJlIGluIFNhZ2UgKG5vdGVib29rIGFuZCB3b3Jrc2hlZXRzKSBub3QKPGJyPmluIEp1cHl0ZXIs
IHdoaWNoIEkgd2FzIGp1c3QgcmVtaW5kZWQgb2YsIGlzIG91dHB1dCBsaW1pdGluZy4mbmJzcDsg
SW4gU2FnZQo8YnI+dGhlcmUgYXJlIG51bWVyb3VzIHJ1bGVzL29wdGlvbnMgdG8gZGVhbCB3aXRo
IHBlb3BsZSBkb2luZyBzdHVmZiBsaWtlOgo8YnI+Cjxicj53aGlsZSBUcnVlOgo8YnI+Jm5ic3A7
ICZuYnNwO3ByaW50ICJoaSEiCjxicj4KPGJyPi4uLiB3aGljaCBpcyBleGFjdGx5IHdoYXQgc3R1
ZGVudHMgd2lsbCB0ZW5kIHRvIGRvIGJ5IGFjY2lkZW50Li4uCjxicj5KdXB5dGVyIGRvZXNuJ3Qg
ZGVhbCB3aXRoIHRoaXMsIGJ1dCBpdCBtaWdodCBub3QgYmUgdG9vIGhhcmQgdG8KPGJyPmltcGxl
bWVudCBpbiB0aGVvcnkuJm5ic3A7IE9uZSBvZiB0aGUgbWFpbiBwcm9ibGVtcyBpcyBmaWd1cmlu
ZyBvdXQgd2hhdAo8YnI+dGhlIGFyYml0cmFyeSByYXRlIGxpbWl0aW5nIGRlZmF1bHRzICJzaG91
bGQiIGJlOyBpdCdzIGFyYml0cmFyeSwgYW5kCjxicj5kZXBlbmRzIGEgbG90IG9uIHdoZXRoZXIg
ZXZlcnl0aGluZyBpcyBsb2NhbCwgb3ZlciB0aGUgd2ViLCBldGMuIHNvCjxicj5nZXR0aW5nIGEg
YnVuY2ggb2YgcGVvcGxlIHRvIGFncmVlIGlzIGhhcmQsIHdoaWNoIG1pZ2h0IG1lYW4gdGhleSB3
aWxsCjxicj5uZXZlciBpbXBsZW1lbnQgYW55dGhpbmcuCjxicj48L2Jsb2NrcXVvdGU+PGRpdj48
YnI+PC9kaXY+PGRpdj48YnI+PC9kaXY+PGRpdj5XaWxsaWFtLDwvZGl2PjxkaXY+PGJyPjwvZGl2
PjxkaXY+Sm9uIEZyZWRlcmljIGluIHRoZSBKdXB5dGVyIGRldiBtZWV0aW5nIGhhcHBlbmluZyBy
aWdodCBub3cgc2FpZCB0aGF0IGhlIHdpbGwgYmUgd29ya2luZyBvbiBvdXRwdXQgbGltaXRpbmcg
YXMgb25lIG9mIGhpcyBuZXh0IHRoaW5ncy48L2Rpdj48c3Bhbj48Zm9udCBjb2xvcj0iIzg4ODg4
OCI+PGRpdj48YnI+PC9kaXY+PGRpdj5KYXNvbjwvZGl2PjwvZm9udD48L3NwYW4+PC9ibG9ja3F1
b3RlPjwvZGl2Pjxicj48L2Rpdj4KPC9kaXY+PC9kaXY+PC9zcGFuPjwvZGl2Pjxicj48L2Rpdj4K
PC9kaXY+PC9kaXY+PC9ibG9ja3F1b3RlPjwvZGl2Pjxicj48L2Rpdj48L2Rpdj48L2Rpdj4KPC9i
bG9ja3F1b3RlPjwvZGl2PjwvZGl2PjwvZGl2Pjxicj5fX19fX19fX19fX19fX19fX19fX19fX19f
X19fX188d2JyPl9fX19fX19fX19fX19fX19fPGJyPgpJUHl0aG9uLWRldiBtYWlsaW5nIGxpc3Q8
YnI+CjxhIGhyZWY9Im1haWx0bzpJUHl0aG9uLWRldkBzY2lweS5vcmciPklQeXRob24tZGV2QHNj
aXB5Lm9yZzwvYT48YnI+CjxhIGhyZWY9Imh0dHBzOi8vbWFpbC5zY2lweS5vcmcvbWFpbG1hbi9s
aXN0aW5mby9pcHl0aG9uLWRldiIgcmVsPSJub3JlZmVycmVyIiB0YXJnZXQ9Il9ibGFuayI+aHR0
cHM6Ly9tYWlsLnNjaXB5Lm9yZy88d2JyPm1haWxtYW4vbGlzdGluZm8vaXB5dGhvbi1kZXY8L2E+
PGJyPgo8YnI+PC9ibG9ja3F1b3RlPjwvZGl2Pjxicj48L2Rpdj4=" style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0"></div></div></div>