<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aleksey Reprintsev</title>
    <description>The latest articles on DEV Community by Aleksey Reprintsev (@reprintsev).</description>
    <link>https://dev.to/reprintsev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F677648%2F0762ffa5-e1c3-4697-83c0-084997a946d6.jpg</url>
      <title>DEV Community: Aleksey Reprintsev</title>
      <link>https://dev.to/reprintsev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/reprintsev"/>
    <language>en</language>
    <item>
      <title>My favorite tmux prefix</title>
      <dc:creator>Aleksey Reprintsev</dc:creator>
      <pubDate>Wed, 26 Apr 2023 17:20:39 +0000</pubDate>
      <link>https://dev.to/reprintsev/my-favorite-tmux-prefix-2618</link>
      <guid>https://dev.to/reprintsev/my-favorite-tmux-prefix-2618</guid>
      <description>&lt;p&gt;For a long time I used &lt;code&gt;screen&lt;/code&gt;, but now &lt;code&gt;tmux&lt;/code&gt; is my favorite terminal multiplexer. But my fingers could not get used to the &lt;code&gt;Ctrl+b&lt;/code&gt; combination, so I decided to please them. An internet search revealed that the most popular prefix combinations are &lt;code&gt;Ctrl+a&lt;/code&gt;, &lt;code&gt;Ctrl+Space&lt;/code&gt;, &lt;code&gt;Backtic&lt;/code&gt;, &lt;code&gt;CapsLock&lt;/code&gt; followed by many others.&lt;/p&gt;

&lt;p&gt;My wishes: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the keys for the prefix were located side by side;&lt;/li&gt;
&lt;li&gt;it was not necessary to twist the fingers to press them; &lt;/li&gt;
&lt;li&gt;there were two symmetrical combinations for the right and left hand. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most promising combination at first seemed to be &lt;code&gt;Ctrl+Space&lt;/code&gt;, and at first it even seemed convenient, but after experimenting I found it.&lt;/p&gt;

&lt;p&gt;So my favorites: &lt;code&gt;Alt+z&lt;/code&gt; and &lt;code&gt;Ctrl+/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;My usual &lt;code&gt;tmux&lt;/code&gt; workflow is: open multiple panes, select a layout, switch between panes, expand/collapse a pane, minimize &lt;code&gt;tmux&lt;/code&gt;, expand &lt;code&gt;tmux&lt;/code&gt;, detach the session.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;LAlt+z&lt;/code&gt;, &lt;code&gt;LShift+'&lt;/code&gt;, &lt;code&gt;LAlt+z&lt;/code&gt;, &lt;code&gt;LShift+'&lt;/code&gt;, &lt;code&gt;RCtrl+/&lt;/code&gt;, &lt;code&gt;RAlt+2&lt;/code&gt;, &lt;code&gt;LAlt+z&lt;/code&gt; &lt;code&gt;z&lt;/code&gt;, &lt;code&gt;LAlt+z&lt;/code&gt; &lt;code&gt;z&lt;/code&gt; ,  &lt;code&gt;LAlt+🠕&lt;/code&gt;, &lt;code&gt;LAlt+🠗&lt;/code&gt;, &lt;code&gt;LAlt+z&lt;/code&gt; &lt;code&gt;RCtrl+z&lt;/code&gt;, &lt;code&gt;fg&lt;/code&gt;, &lt;code&gt;RCtrl+z&lt;/code&gt; &lt;code&gt;d&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Almost like playing the piano :)&lt;/p&gt;

&lt;p&gt;Explanation:&lt;br&gt;
(&lt;code&gt;LAlt&lt;/code&gt; - left Alt key, &lt;code&gt;LShift&lt;/code&gt; - left Shift key, &lt;code&gt;RCtrl&lt;/code&gt; - right Ctrl key, &lt;code&gt;RAlt&lt;/code&gt; - right Alt key)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LAlt+z&lt;/code&gt;, &lt;code&gt;LShift+'&lt;/code&gt;   # Split the current pane into two, top and bottom&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LAlt+z&lt;/code&gt;, &lt;code&gt;LShift+'&lt;/code&gt;   # Split the current pane into two, top and bottom&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RCtrl+/&lt;/code&gt;, &lt;code&gt;RAlt+2&lt;/code&gt;   # Arrange panes even-vertical&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LAlt+z&lt;/code&gt; &lt;code&gt;z&lt;/code&gt;   # Zoom current pane&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LAlt+z&lt;/code&gt; &lt;code&gt;z&lt;/code&gt;   # Unzoom current pane&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LAlt+🠕&lt;/code&gt;   # Switch to pane above&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LAlt+🠗&lt;/code&gt;   # Switch to pane below&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LAlt+z&lt;/code&gt; &lt;code&gt;RCtrl+z&lt;/code&gt;   # Suspend the &lt;code&gt;tmux&lt;/code&gt; client&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fg&lt;/code&gt;   # Bring &lt;code&gt;tmux&lt;/code&gt; to foreground (&lt;code&gt;bash&lt;/code&gt; command)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RCtrl+/&lt;/code&gt; &lt;code&gt;d&lt;/code&gt;   # Detach the current client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is my config file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# reload config after changes&lt;/span&gt;
&lt;span class="c"&gt;# tmux source-file ~/.tmux.conf&lt;/span&gt;

&lt;span class="c"&gt;# colors&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; default-terminal &lt;span class="s2"&gt;"screen-256color"&lt;/span&gt;
&lt;span class="c"&gt;# set -g default-terminal "tmux-256color"&lt;/span&gt;

&lt;span class="c"&gt;# prefix keys&lt;/span&gt;
unbind C-b
set-option &lt;span class="nt"&gt;-g&lt;/span&gt; prefix C-_                &lt;span class="c"&gt;# Ctrl+/&lt;/span&gt;
set-option &lt;span class="nt"&gt;-g&lt;/span&gt; prefix2 M-z
bind-key C-_ send-prefix
bind-key M-z send-prefix &lt;span class="nt"&gt;-2&lt;/span&gt;

&lt;span class="c"&gt;# mouse mode on&lt;/span&gt;
set-option &lt;span class="nt"&gt;-g&lt;/span&gt; mouse on

&lt;span class="c"&gt;# key bindings&lt;/span&gt;
&lt;span class="nb"&gt;bind &lt;/span&gt;r source-file ~/.tmux.conf         &lt;span class="c"&gt;# reload config&lt;/span&gt;

&lt;span class="c"&gt;# switch panes using Alt-arrow without prefix&lt;/span&gt;
&lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; M-Left &lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="nt"&gt;-pane&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt;
&lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; M-Right &lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="nt"&gt;-pane&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt;
&lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; M-Up &lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="nt"&gt;-pane&lt;/span&gt; &lt;span class="nt"&gt;-U&lt;/span&gt;
&lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; M-Down &lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="nt"&gt;-pane&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope this proves useful to someone.&lt;/p&gt;

</description>
      <category>tmux</category>
      <category>prefix</category>
    </item>
    <item>
      <title>How to limit the number of simultaneously running goroutines and wait for their completion</title>
      <dc:creator>Aleksey Reprintsev</dc:creator>
      <pubDate>Sat, 05 Nov 2022 16:17:51 +0000</pubDate>
      <link>https://dev.to/reprintsev/how-to-limit-the-number-of-simultaneously-running-goroutines-and-wait-for-their-completion-12pf</link>
      <guid>https://dev.to/reprintsev/how-to-limit-the-number-of-simultaneously-running-goroutines-and-wait-for-their-completion-12pf</guid>
      <description>&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Launching goroutines&lt;/li&gt;
&lt;li&gt;Starting goroutines with a delay in completing &lt;code&gt;main()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Waiting for the completion of all goroutines&lt;/li&gt;
&lt;li&gt;Limiting the number of simultaneously running goroutines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes there is a task to limit the number of simultaneously running goroutines to comply with some limits. For example, by the number of CPU cores or by the memory consumed, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Launching goroutines &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To begin with, let's see how to run goroutines. Let's run 5 gorutins in a loop, we simulate the work of the goroutine through &lt;code&gt;time.Sleep()&lt;/code&gt;, we will set the delay as &lt;code&gt;i * 100ms&lt;/code&gt;. The string &lt;code&gt;i := i&lt;/code&gt; is needed to localize the value of the loop counter for iteration, without this, each goroutine will get the value 5. Read more &lt;a href="https://github.com/golang/go/wiki/CommonMistakes"&gt;here&lt;/a&gt; and &lt;a href="https://eli.thegreenplace.net/2019/go-internals-capturing-loop-variables-in-closures/"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"START main"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  START #%d (delay %v)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  END #%d (delay %v)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"END main"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;START main
END main

Program exited.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://go.dev/play/p/xDte-VcNzcn"&gt;Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It follows from the output of the program that not a single goroutine was executed. This happened because the execution of the program (function &lt;code&gt;main()&lt;/code&gt;) ended immediately after the completion of the &lt;code&gt;for&lt;/code&gt; loop, so all running goroutines were also completed almost immediately after their execution began.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting goroutines with a delay in completing &lt;code&gt;main()&lt;/code&gt; &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Let's see what happens if some delay is introduced before the program ends, for example 250ms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"START main"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  START #%d (delay %v)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  END #%d (delay %v)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// Let's add some delay&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;250&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"END main"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;START main
  START #4 (delay 500ms)
  START #0 (delay 100ms)
  START #1 (delay 200ms)
  START #2 (delay 300ms)
  START #3 (delay 400ms)
  END #0 (delay 100ms)
  END #1 (delay 200ms)
END main

Program exited.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://go.dev/play/p/LCnSLSCg8f1"&gt;Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, after adding a delay to the &lt;code&gt;main()&lt;/code&gt; function, two goroutines (with duration of 100ms and 200ms) managed to be executed. If the delay is increased to 500ms or more, then all the goroutines will have time to be executed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Waiting for the completion of all goroutines &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In real life, it is rarely possible to determine the execution time of goroutines, therefore, to wait for the completion of all goroutines, you can use &lt;code&gt;WaitGroup&lt;/code&gt; from the &lt;code&gt;sync&lt;/code&gt; module. From &lt;a href="https://pkg.go.dev/sync#WaitGroup"&gt;documentation&lt;/a&gt; module:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished. At the same time, Wait can be used to block until all goroutines have finished.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In our example, we will call &lt;code&gt;Add(1)&lt;/code&gt; before each start of the goroutine, and &lt;code&gt;Done()&lt;/code&gt; when the goroutine is completed via &lt;code&gt;defer&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"START main"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  START #%d (delay %v)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  END #%d (delay %v)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"END main"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;START main
  START #4 (delay 500ms)
  START #2 (delay 300ms)
  START #3 (delay 400ms)
  START #1 (delay 200ms)
  START #0 (delay 100ms)
  END #0 (delay 100ms)
  END #1 (delay 200ms)
  END #2 (delay 300ms)
  END #3 (delay 400ms)
  END #4 (delay 500ms)
END main

Program exited.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://go.dev/play/p/U7DNztI4ETH"&gt;Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We see that all the goroutines have time to complete, but the problem of simultaneous launch of all goroutines has not yet been solved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limiting the number of simultaneously running goroutines &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To limit the number of simultaneously running goroutines, a buffered channel can be used. The feature of the buffered channel is that after the buffer is filled, the next write to the channel is blocked until at least one value is read from the channel.&lt;/p&gt;

&lt;p&gt;The constant &lt;code&gt;grMax&lt;/code&gt; contains the number of simultaneously executed goroutines. After the channel buffer is full, execution will be blocked on the command &lt;code&gt;ch &amp;lt;- 1&lt;/code&gt; and will continue after reading from it with the command &lt;code&gt;&amp;lt;-ch&lt;/code&gt;. It is better to place the command to read from the channel in &lt;code&gt;defer&lt;/code&gt; so that when errors occur in the gorutin, the entire program does not hang.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;grMax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"START main"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
    &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grMax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="p"&gt;}()&lt;/span&gt;
            &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  START #%d (delay %v)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  END #%d (delay %v)&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"END main"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;START main
  START #2 (delay 300ms)
  START #0 (delay 100ms)
  START #1 (delay 200ms)
  END #0 (delay 100ms)
  START #3 (delay 400ms)
  END #1 (delay 200ms)
  START #4 (delay 500ms)
  END #2 (delay 300ms)
  END #3 (delay 400ms)
  END #4 (delay 500ms)
END main

Program exited.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://go.dev/play/p/EDgLh1A9tMR"&gt;Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, 3 goroutines were immediately launched &lt;code&gt;#0&lt;/code&gt;, &lt;code&gt;#1&lt;/code&gt;, &lt;code&gt;#2&lt;/code&gt;, then, after completing one of them (&lt;code&gt;#0&lt;/code&gt;), the next one is started (&lt;code&gt;#3&lt;/code&gt;) and so on.&lt;/p&gt;

&lt;p&gt;The problem is solved.&lt;/p&gt;

</description>
      <category>go</category>
      <category>goroutine</category>
    </item>
    <item>
      <title>Low performance of Ruby on Rails in Docker under Windows</title>
      <dc:creator>Aleksey Reprintsev</dc:creator>
      <pubDate>Sun, 12 Dec 2021 09:52:05 +0000</pubDate>
      <link>https://dev.to/reprintsev/low-performance-of-ruby-on-rails-in-docker-under-windows-1f1f</link>
      <guid>https://dev.to/reprintsev/low-performance-of-ruby-on-rails-in-docker-under-windows-1f1f</guid>
      <description>&lt;p&gt;You can improve the performance of Ruby on Rails in Docker under Windows 10 if you run &lt;code&gt;docker-compose&lt;/code&gt; not from Windows, but from WSL.&lt;/p&gt;

&lt;p&gt;For example, if the source code of the project is in &lt;code&gt;C:\Users\user\projects\myproject&lt;/code&gt;, you need to copy it to WSL - &lt;code&gt;/home/user/projects/myproject&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The WSL file system from under Windows is accessible via &lt;code&gt;\\wsl$&lt;/code&gt;, you can copy &lt;code&gt;myproject&lt;/code&gt; via File Explorer or terminal from &lt;code&gt;C:\Users\user\projects\myproject&lt;/code&gt; to &lt;code&gt;\\wsl$\Ubuntu-20.04\home\user\projects\&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, using your favorite distribution, run WSL, go to the directory with the copied code and run &lt;code&gt;docker-compose&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/projects/myproject
docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To edit code from Windows, you can open the &lt;code&gt;\\wsl$\Ubuntu-20.04\home\user\projects\myproject&lt;/code&gt; directory in your favorite editor&lt;/p&gt;

&lt;p&gt;In my case, the rendering speed has increased by about 10 times.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>docker</category>
      <category>windows</category>
    </item>
  </channel>
</rss>
