<commit_before><!doctype html>
<html lang="en">

	<head>
		<meta charset="utf-8">

		<title>The curious case of slow/fast grequests code</title>

    <meta name="description" content="The curious case of slow/fast grequests code">
		<meta name="author" content="<NAME>">

		<meta name="apple-mobile-web-app-capable" content="yes">
		<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">

		<link rel="stylesheet" href="css/reveal.css">
		<link rel="stylesheet" href="css/theme/beige.css" id="theme">

		<!-- Code syntax highlighting -->
		<link rel="stylesheet" href="lib/css/zenburn.css">

		<!-- Printing and PDF exports -->
		<script>
			var link = document.createElement( 'link' );
			link.rel = 'stylesheet';
			link.type = 'text/css';
			link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
			document.getElementsByTagName( 'head' )[0].appendChild( link );
		</script>

		<!--[if lt IE 9]>
		<script src="lib/js/html5shiv.js"></script>
		<![endif]-->
	</head>

	<body>

		<div class="reveal">

			<!-- Any section element inside of this container is displayed as a slide -->
			<div class="slides">
				<section>
					<h3>The curious case of slow/fast grequests code</h3>
					<p>
						<small><a href="mailto:<EMAIL>"><EMAIL></a> / <a href="http://twitter.com/sphirani">@sphirani</a></small>
					</p>
				</section>

        <section>
          <h2>Use case</h2>
          <ul>
            <li class='fragment'>Daily reporting tool: 1000s of HTTPS GETs</li>
            <li class='fragment'>Runtime: 15-20 mins (serial requests)</li>
            <li class='fragment'>Migrate from AWS EC2 to AWS Lambda</li>
          </ul>
        </section>

				<section>
					<h2>Problem</h3>
          <ul>
            <li class='fragment'>Constraint: AWS Lambda 15 mins max runtime</li>
            <li class='fragment'>Solution: Convert serial GETs to concurrent</li>
            <li class='fragment'>requests => grequests (gevent + requests)</li>
            <li class='fragment'>Hidden trap: Execution speed varies.
            <li class='fragment'>Depends on: <b>Other</b> Python modules installed on system.</li>
          </ul>
				</section>

        <section>
					<h2>Stage-0 Demo</h3>
					<ul>
            <li class='fragment'>Same code - Python 2.7 slow, Python 3.7 fast</li>
					</ul>
				</section>

        <section>
          <img src="images/grequests-liam-if-you-run-slow-fast.jpg" style="top:0;left:0;" >
				</section>

        <section>
					<h2>Pre-requisites</h3>
						<ul>
							<li class='fragment'>TODO - Serial code flow with requests</li>
							<li class='fragment'>TODO - Concurrent code flow with grequests</li>
							<li class='fragment'>TODO - Monkey patching basics</li>
							<li class='fragment'><a href="https://blog.golang.org/concurrency-is-not-parallelism">Concurrency != Parallelism</a></li>
						</ul>
				</section>

        <section>
					<h2>Stage-1</h2>
					<ul>
						<li class='fragment'>Isolated docker container</li>
						<li class='fragment'>Minimal set of modules</li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/01/python27">Python 2.7 fast</a></li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/01/python37">Python 3.7 fast</a></li>
						<li class='fragment'>Demo</li>
					</ul>
				</section>

				<section>
					<h2>Stage-0 v/s Stage-1</h2>
					<ul>
						<li class='fragment'>Stage-0 Python2.7 slow</li>
						<li class='fragment'>Stage-1 Python2.7 fast</li>
						<li class='fragment'>Same code</li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/00#get-socket-class">Stage-0 Python2.7 socket class</a></li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/01/python27#get-socket-class">Stage-1 Python2.7 socket class</a></li>
					</ul>
				</section>

				<section>
					<h2>Stage-2</h2>
					<ul>
						<li class='fragment'>Stage-1 + <a href="https://pyopenssl.org/en/stable/introduction.html#history">pyopenssl</a></li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/02/python27">Python 2.7 slow</a></li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/02/python37">Python 3.7 slow</a></li>
					</ul>
				</section>

				<section>
					<h2>Why is pyopenssl making code slow?</h2>
					<ul>
						<li class='fragment'>grequests = gevent + requests</li>
						<li class='fragment'>requests <b>optionally</b> <a href="https://github.com/kennethreitz/requests/blob/c4d76800e8917c3fda10cb1f2dee22c8219de3e6/requests/__init__.py#L95">includes pyopenssl</a></li>
						<li class='fragment'>Changes program flow and re-patches socket</li>
					</ul>
				</section>

				<section>
					<h2>Solution</h2>
					<li class='fragment'>Uninstall pyopenssl</li>
					<li class='fragment'>OR</li>
					<li class='fragment'>Use <a href="https://github.com/mjs/gevent_openssl">gevent-openssl</a></li>
					<li class='fragment'>gevent-openssl = pyopenssl compatible with gevent</li>
				</section>

				<section>
					<h2>Stage-3</h2>
					<ul>
						<li class='fragment'>Stage-2 + <a href="https://github.com/mjs/gevent_openssl">gevent-openssl</a></li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/03/python27">Python 2.7 fast</a></li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/03/python37">Python 3.7 slow</a></li>
					</ul>
				</section>

				<section>
          <img src="images/grequests-frustration.jpg" style="top:0;left:0;" >
				</section>

        <section>
					<h2>Deep dive</h3>
          <ul>
            <li class='fragment'>Same program, different modules</li>
            <li class='fragment'>Stage-0 - Trigger - Python 2.7 =~ Python 3.7 =~ slow/fast</li>
            <li class='fragment'>Stage-1 - Baseline - Python 2.7 =~ Python 3.7 =~ fast</li>
            <li class='fragment'>Stage-2 - Detect - Python 2.7 =~ Python 3.7 =~ slow</li>
            <li class='fragment'>Stage-3 - Fix-1 - Python 2.7 =~ fast, Python 3.7 =~ slow</li>
            <li class='fragment'>Stage-4 - Fix-2 - Python 2.7 =~ fast, Python 3.7 =~ fast</li>
          </ul>
				</section>

        <section>
					<h2>Takeaways</h3>
          <ul>
            <li class='fragment'> Better understanding of:</li>
            <ul>
              <li class='fragment'>Python profiling, function tracing.</li>
              <li class='fragment'>gevent, grequests, urllib3, socket lib selective peeking.</li>
            </ul>
          </ul>
				</section>

			</div>

		</div>

		<script src="lib/js/head.min.js"></script>
		<script src="js/reveal.js"></script>

		<script><commit_msg>first draft - grequests main presentation slides<commit_after>
<html lang="en">

	<head>
		<meta charset="utf-8">

		<title>The curious case of slow/fast grequests code</title>

    <meta name="description" content="The curious case of slow/fast grequests code">
		<meta name="author" content="<NAME>">

		<meta name="apple-mobile-web-app-capable" content="yes">
		<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">

		<link rel="stylesheet" href="css/reveal.css">
		<link rel="stylesheet" href="css/theme/beige.css" id="theme">

		<!-- Code syntax highlighting -->
		<link rel="stylesheet" href="lib/css/zenburn.css">

		<!-- Printing and PDF exports -->
		<script>
			var link = document.createElement( 'link' );
			link.rel = 'stylesheet';
			link.type = 'text/css';
			link.href = window.location.search.match( /print-pdf/gi ) ? 'css/print/pdf.css' : 'css/print/paper.css';
			document.getElementsByTagName( 'head' )[0].appendChild( link );
		</script>

		<!--[if lt IE 9]>
		<script src="lib/js/html5shiv.js"></script>
		<![endif]-->
	</head>

	<body>

		<div class="reveal">

			<!-- Any section element inside of this container is displayed as a slide -->
			<div class="slides">
				<section>
					<h3>The curious case of slow/fast grequests code</h3>
					<p>
						<small><a href="mailto:<EMAIL>"><EMAIL></a> / <a href="http://twitter.com/sphirani">@sphirani</a></small>
					</p>
				</section>

        <section>
          <h2>Use case</h2>
          <ul>
            <li class='fragment'>Daily reporting tool: 1000s of HTTPS GETs</li>
            <li class='fragment'>Runtime: 15-20 mins (serial requests)</li>
            <li class='fragment'>Migrate from AWS EC2 to AWS Lambda</li>
          </ul>
        </section>

				<section>
					<h2>Problem</h3>
          <ul>
            <li class='fragment'>Constraint: AWS Lambda 15 mins max runtime</li>
            <li class='fragment'>Solution: Convert serial GETs to concurrent</li>
            <li class='fragment'>requests => grequests (gevent + requests)</li>
            <li class='fragment'>Hidden trap: Execution speed varies.
            <li class='fragment'>Depends on: <b>Other</b> Python modules installed on system.</li>
          </ul>
				</section>

        <section>
					<h2>Stage-0 - Trigger</h3>
					<ul>
            <li class='fragment'>HTTPS Demo</li>
            <li class='fragment'>HTTP Demo</li>
						<li class='fragment'>Same code - Python 2.7 slow, Python 3.7 fast</li>
					</ul>
				</section>

        <section>
          <img src="images/grequests-liam-if-you-run-slow-fast.jpg" style="top:0;left:0;" >
				</section>

        <section>
					<h2>Pre-requisites</h3>
						<ul>
							<li class='fragment'>Serial code flow (requests)</li>
							<li class='fragment'>Concurrent code flow (grequests)</li>
							<li class='fragment'>Monkey patching basics</li>
							<li class='fragment'><a href="https://blog.golang.org/concurrency-is-not-parallelism">Concurrency != Parallelism</a></li>
						</ul>
				</section>

        <section>
					<h2>Stage-1 - Baseline</h2>
					<ul>
						<li class='fragment'>Isolated docker container</li>
						<li class='fragment'>Minimal set of modules</li>
						<li class='fragment'>Demo</li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/01/python27">Python 2.7 fast</a></li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/01/python37">Python 3.7 fast</a></li>
					</ul>
				</section>

				<section>
					<h2>Stage-0 v/s Stage-1</h2>
					<ul>
						<li class='fragment'>Stage-0 Python2.7 slow</li>
						<li class='fragment'>Stage-1 Python2.7 fast</li>
						<li class='fragment'>Same code</li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/00#get-socket-class">Stage-0 Python2.7 socket class</a></li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/01/python27#get-socket-class">Stage-1 Python2.7 socket class</a></li>
					</ul>
				</section>

				<section>
					<h2>Stage-2 - Detect and Verify</h2>
					<ul>
						<li class='fragment'>Stage-1 + <a href="https://pyopenssl.org/en/stable/introduction.html#history">pyopenssl</a></li>
						<li class='fragment'>Demo</li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/02/python27">Python 2.7 slow</a></li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/02/python37">Python 3.7 slow</a></li>
					</ul>
				</section>

				<section>
					<h2>Why is pyopenssl making code slow?</h2>
					<ul>
						<li class='fragment'>grequests = gevent + requests</li>
						<li class='fragment'>requests <b>optionally</b> <a href="https://github.com/kennethreitz/requests/blob/c4d76800e8917c3fda10cb1f2dee22c8219de3e6/requests/__init__.py#L95">includes pyopenssl</a></li>
						<li class='fragment'>Changes program flow and re-patches socket</li>
					</ul>
				</section>

				<section>
					<h2>Solution</h2>
					<li class='fragment'>Uninstall pyopenssl</li>
					<li class='fragment'>OR</li>
					<li class='fragment'>Use <a href="https://github.com/mjs/gevent_openssl">gevent-openssl</a></li>
					<li class='fragment'>gevent-openssl = pyopenssl compatible with gevent</li>
				</section>

				<section>
					<h2>Stage-3 - Fix-1</h2>
					<ul>
						<li class='fragment'>Stage-2 + <a href="https://github.com/mjs/gevent_openssl">gevent-openssl</a></li>
						<li class='fragment'>Demo</li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/03/python27">Python 2.7 fast</a></li>
						<li class='fragment'><a href="https://github.com/saurabh-hirani/grequests-https-python-27-37-tests/tree/master/stages/03/python37">Python 3.7 slow</a></li>
					</ul>
				</section>

				<section>
          <img src="images/grequests-frustration.jpg" style="top:0;left:0;" >
				</section>

				<section>
					<h2>Why?</h2>
					<ul>
						<li class='fragment'>Python2.7 uses <b>recv</b></li>
						<li class='fragment'>Python3.7 uses <b>recv_into</b></li>
						<li class='fragment'>gevent-openssl does not override <a href="https://github.com/mjs/gevent_openssl/blob/645ded94710d886bce671c2f001d30643242b3cd/gevent_openssl/SSL.py">recv_into</a></li>
					</ul>
				</section>

				<section>
					<h2>Stage-4 - Fix-2</h2>
					<ul>
						<li class='fragment'>Patch gevent-openssl to add <b>recv_into</b></li>
						<li class='fragment'>Before patching demo</li>
						<li class='fragment'>After patching demo</li>
						<li class='fragment'><a href="https://github.com/mjs/gevent_openssl/pull/15">PR to fix the issue</a></li>
					</ul>
				</section>

				<section>
					<h2>Recap</h2>
					<ul>
						<li class='fragment'>Applies only to HTTPS</li>
						<li class='fragment'>grequests + pyopenssl = slow for Python2.7/Python3.7</li>
						<li class='fragment'>grequests - pyopenssl = fast for Python2.7/Python3.7</li>
						<li class='fragment'>grequests + pyopenssl + gevent-openssl = fast for Python2.7</li>
						<li class='fragment'>grequests + pyopenssl + gevent-openssl + patch = fast for Python3.7</li>
					</ul>
				</section>

			<section>
				<h2>Takeaways</h2>
				<ul>
					<li class='fragment'>Profile your code.</li>
					<li class='fragment'>Trace your code.</li>
					<li class='fragment'>Isolate scenarios.</li>
				</ul>
			</section>

			<section>
				<h2>Q & A</h2>

			</section>

		</div>

		<script src="lib/js/head.min.js"></script>
		<script src="js/reveal.js"></script>

		<script>
{'fraction_non_alphanumeric': 0.18312730142030512, 'fraction_numerical': 0.028011572856391373, 'mean_word_length': 3.00764163372859, 'pattern_counts': {'":': 0, '<': 537, '<?xml version=': 0, '>': 539, 'https://': 28, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1276326', 'n_tokens_mistral': 6404, 'n_tokens_neox': 5230, 'n_words': 958}