summaryrefslogtreecommitdiff
blob: e6361fe0d833043b448f8a8c81c26a2a6c26a6e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8"/>
<meta name="generator" content="AsciiDoc 8.6.7"/>
<title>Set up SSH Mulitplexing for Speed</title>
<style type="text/css">
/*<![CDATA[*/
/*
  pygmentize filter
*/
.highlight .hll { background-color: #ffffcc }
.highlight  { background: #f4f4f4; }
.highlight .c { color: #008800; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #AA22FF; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #008800; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #008800 } /* Comment.Preproc */
.highlight .c1 { color: #008800; font-style: italic } /* Comment.Single */
.highlight .cs { color: #008800; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #AA22FF; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #AA22FF } /* Keyword.Pseudo */
.highlight .kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #00BB00; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BB4444 } /* Literal.String */
.highlight .na { color: #BB4444 } /* Name.Attribute */
.highlight .nb { color: #AA22FF } /* Name.Builtin */
.highlight .nc { color: #0000FF } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #00A000 } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #B8860B } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BB4444 } /* Literal.String.Backtick */
.highlight .sc { color: #BB4444 } /* Literal.String.Char */
.highlight .sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BB4444 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BB4444 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #008000 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BB4444 } /* Literal.String.Single */
.highlight .ss { color: #B8860B } /* Literal.String.Symbol */
.highlight .bp { color: #AA22FF } /* Name.Builtin.Pseudo */
.highlight .vc { color: #B8860B } /* Name.Variable.Class */
.highlight .vg { color: #B8860B } /* Name.Variable.Global */
.highlight .vi { color: #B8860B } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */

/*]]>*/
</style>
<script type="text/javascript">
/*<![CDATA[*/
window.onload = function(){asciidoc.footnotes(); asciidoc.toc(4);}
/*]]>*/
</script>
</head>
<body class="article">
<div id="header">
<h1>Set up SSH Mulitplexing for Speed</h1>
<div id="toc">
  <div id="toctitle">Table of Contents</div>
  <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph"><p>This is one of my most convenient tricks. The slowest parts of <tt>git pull</tt> and
<tt>git push</tt> are starting up the SSH connection. However, there is a way to
eliminate this problem simply by opening a persistent tunnel, which <tt>git pull</tt>
and <tt>git push</tt> automatically reuse.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_ssh_config">1. ~/.ssh/config</h2>
<div class="sectionbody">
<div class="paragraph"><p>Enter the ControlMaster option for OpenSSH.</p></div>
<div class="quoteblock">
<div class="content">
<div class="paragraph"><p><strong>ControlMaster</strong></p></div>
<div class="paragraph"><p>Enables the sharing of multiple sessions over a single network connection.
When set to &#x201C;yes&#x201D;, ssh(1) will listen for connections on a control socket
specified using the ControlPath argument.  Additional sessions can connect to
this socket using the same <strong>ControlPath</strong> with <strong>ControlMaster</strong> set to &#x201C;no&#x201D;
(the default).</p></div>
<div class="paragraph"><p>These sessions will try to reuse the master instance&#x2019;s network connection
rather than initiating new ones, but will fall back to connecting normally if
the control socket does not exist, or is not listening.</p></div>
<div class="paragraph"><p>Setting this to &#x201C;ask&#x201D; will cause ssh to listen for control connections, but
require confirmation using the SSH_ASKPASS program before they are accepted
(see ssh-add(1) for details).  If the <strong>ControlPath</strong> cannot be opened, ssh will
continue without connecting to a master instance.</p></div>
<div class="paragraph"><p>X11 and ssh-agent(1) forwarding is supported over these multiplexed
connections, however the display and agent forwarded will be the one belonging
to the master connection i.e. it is not possible to forward multiple displays
or agents.</p></div>
<div class="paragraph"><p>Two additional options allow for opportunistic multiplexing: try to use a
master connection but fall back to creating a new one if one does not already
exist.  These options are: &#x201C;auto&#x201D; and &#x201C;autoask&#x201D;.  The latter requires
confirmation like the &#x201C;ask&#x201D; option.</p></div>
</div>
<div class="attribution">
</div></div>
<div class="paragraph"><p>So I set up my ~/.ssh/config as follows.</p></div>
<div class="listingblock">
<div class="content"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6</pre></div></td><td class="code"><div class="highlight"><pre><span class="c">#~/.ssh/config</span>
ControlMaster auto
ControlPath ~/.ssh/pool/%r@%h
ServerAliveCountMax 6
ServerAliveInterval 10
TCPKeepAlive yes
</pre></div>
</td></tr></table></div></div>
<div class="paragraph"><p>And we&#x2019;re set!.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_first_a_few_benchmarks">2. First, a few benchmarks</h2>
<div class="sectionbody">
<div class="paragraph"><p>First, lets see how fast it is without the magic:</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre>&gt; <span class="nb">time </span><span class="k">for </span>i in <span class="k">$(</span> seq 0 10 <span class="k">)</span> ; <span class="k">do </span>git fetch github; <span class="k">done</span>

real    0m47.798s
user    0m0.226s
sys     0m0.236s

&gt; <span class="nb">time </span><span class="k">for </span>i in <span class="k">$(</span> seq 0 10 <span class="k">)</span> ; <span class="k">do </span>git fetch origin; <span class="k">done</span>

real    0m48.444s
user    0m0.235s
sys     0m0.250s
</pre></div></div></div>
<div class="paragraph"><p>Averaging about 4.34s per fetch to Github, 4.40s to gentoo overlays.</p></div>
<div class="paragraph"><p>SLOOW.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_start_a_background_connection">3. Start a background connection</h2>
<div class="sectionbody">
<div class="paragraph"><p>With ControlMaster, you set up a long-lived SSH connection.</p></div>
<div class="listingblock">
<div class="content"><div class="highlight"><pre>&gt; ssh -fNn git@github.com
&gt; ssh -fNn git@git.overlays.gentoo.org
</pre></div></div></div>
<div class="paragraph"><p>And we&#x2019;re truely really to start cooking with petrol.</p></div>
</div>
</div>
<div class="sect1">
<h2 id="_post_configuration_benchmarks">4. Post Configuration Benchmarks</h2>
<div class="sectionbody">
<div class="listingblock">
<div class="content"><div class="highlight"><pre>&gt; <span class="nb">time </span><span class="k">for </span>i in <span class="k">$(</span> seq 0 10 <span class="k">)</span> ; <span class="k">do </span>git fetch github; <span class="k">done</span>

real    0m12.935s
user    0m0.093s
sys     0m0.193s

&gt; <span class="nb">time </span><span class="k">for </span>i in <span class="k">$(</span> seq 0 10 <span class="k">)</span> ; <span class="k">do </span>git fetch origin; <span class="k">done</span>

real    0m11.597s
user    0m0.099s
sys     0m0.191s
</pre></div></div></div>
<div class="paragraph"><p>O_o. Averaging about 1.175s and 1.05s respectively.</p></div>
</div>
</div>
</div>
<div id="footnotes"><hr/></div>
<div id="footer">
<div id="footer-text">
Last updated 2012-04-02 04:30:04 NZST
</div>
<div id="footer-badges">
<a href="http://validator.w3.org/check?uri=referer">
  <img style="border:0;width:88px;height:31px" src="http://www.w3.org/Icons/valid-xhtml11-blue" alt="Valid XHTML 1.1" height="31" width="88"/>
</a>
<a href="http://jigsaw.w3.org/css-validator/">
  <img style="border:0;width:88px;height:31px" src="http://jigsaw.w3.org/css-validator/images/vcss-blue" alt="Valid CSS!"/>
</a>
<a href="http://www.mozilla.org/products/firefox/">
  <img style="border:none; width:110px; height:32px;" src="http://www.spreadfirefox.com/community/images/affiliates/Buttons/110x32/safer.gif" alt="Get Firefox!"/>
</a>
</div>
</div>
</body>
</html>