<?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: Mark Nefedov</title>
    <description>The latest articles on DEV Community by Mark Nefedov (@marknefedov).</description>
    <link>https://dev.to/marknefedov</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%2F1048826%2Fe81054f0-9e37-4fc5-b627-c9d950dada93.jpeg</url>
      <title>DEV Community: Mark Nefedov</title>
      <link>https://dev.to/marknefedov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/marknefedov"/>
    <language>en</language>
    <item>
      <title>Debugging Containers Without Shell Access: Quick Tips</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Sat, 25 Jan 2025 16:31:35 +0000</pubDate>
      <link>https://dev.to/marknefedov/debugging-containers-without-shell-access-quick-tips-41p1</link>
      <guid>https://dev.to/marknefedov/debugging-containers-without-shell-access-quick-tips-41p1</guid>
      <description>&lt;h3&gt;
  
  
  1. &lt;strong&gt;Run Commands Inside the Container’s Namespace&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Every container runs in isolated namespaces. Use &lt;code&gt;nsenter&lt;/code&gt; to "enter" these namespaces from the host:&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;# Get the container’s PID (Docker example)&lt;/span&gt;
&lt;span class="nv"&gt;PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;docker inspect &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s1"&gt;'{{.State.Pid}}'&lt;/span&gt; your_container&lt;span class="si"&gt;)&lt;/span&gt;  

&lt;span class="c"&gt;# Inspect processes inside the container’s PID namespace&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;nsenter &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nv"&gt;$PID&lt;/span&gt; ps aux  

&lt;span class="c"&gt;# Check network sockets in the container’s network namespace&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;nsenter &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nv"&gt;$PID&lt;/span&gt; ss &lt;span class="nt"&gt;-tnlp&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;ps&lt;/code&gt; or &lt;code&gt;ss&lt;/code&gt; with any host-installed tool (e.g., &lt;code&gt;tcpdump&lt;/code&gt;, &lt;code&gt;strace&lt;/code&gt;).  &lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Access Container Files via &lt;code&gt;/proc&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Container filesystems are mounted under &lt;code&gt;/proc/$PID/root&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="c"&gt;# View container files&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; /proc/&lt;span class="nv"&gt;$PID&lt;/span&gt;/root/etc/nginx/  

&lt;span class="c"&gt;# Edit configs directly from the host&lt;/span&gt;
vim /proc/&lt;span class="nv"&gt;$PID&lt;/span&gt;/root/app/config.yaml  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why This Works
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.man7.org/linux/man-pages/man7/namespaces.7.html" rel="noopener noreferrer"&gt;https://www.man7.org/linux/man-pages/man7/namespaces.7.html&lt;/a&gt;  &lt;/p&gt;

</description>
      <category>containers</category>
      <category>linux</category>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>Understanding {:via, Registry, {...}} vs Registry.register/3 in Elixir</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Sun, 03 Nov 2024 17:55:33 +0000</pubDate>
      <link>https://dev.to/marknefedov/understanding-via-registry-vs-registryregister3-in-elixir-56go</link>
      <guid>https://dev.to/marknefedov/understanding-via-registry-vs-registryregister3-in-elixir-56go</guid>
      <description>&lt;h2&gt;
  
  
  Understanding &lt;code&gt;{:via, Registry, {...}}&lt;/code&gt; vs &lt;code&gt;Registry.register/3&lt;/code&gt; in Elixir
&lt;/h2&gt;

&lt;p&gt;If you've worked with processes and registries in Elixir, you've likely encountered both the &lt;code&gt;{:via, Registry, {...}}&lt;/code&gt; syntax and the &lt;code&gt;Registry.register/3&lt;/code&gt; function. At first glance, these two may appear to do the same thing — allowing you to register processes with a registry. However, they have different purposes and use cases. In this post, we'll explore what each of these does, how they differ, and when to use each.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background: Why Use a Registry?
&lt;/h3&gt;

&lt;p&gt;In Elixir, registries offer a way to name processes and access them by a unique identifier rather than just a process ID (PID). Instead of passing around PIDs, which can be tricky to manage and track, you can register a process under a name in a registry. This allows you to reference it more easily and enables features like process discovery and message passing.&lt;/p&gt;

&lt;p&gt;Elixir’s built-in &lt;a href="https://hexdocs.pm/elixir/1.17.3/Registry.html" rel="noopener noreferrer"&gt;&lt;code&gt;Registry&lt;/code&gt;&lt;/a&gt; module provides functions for managing named registries, and with it, you can register processes and retrieve them by a unique identifier (like a room name, session ID, etc.). Now, let’s look at the two methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 1: &lt;code&gt;{:via, Registry, {...}}&lt;/code&gt; Tuple
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://hexdocs.pm/elixir/1.17.3/Registry.html#module-using-in-via" rel="noopener noreferrer"&gt;&lt;code&gt;{:via, Registry, {...}}&lt;/code&gt;&lt;/a&gt; tuple is a special syntax used for &lt;em&gt;starting or referencing&lt;/em&gt; a process with a registry. This tuple signals to Elixir that you want to look up or register a process via a custom registry and associate it with a key.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;{:via, Registry, {...}}&lt;/code&gt; pattern is typically used as the &lt;code&gt;name&lt;/code&gt; argument when starting a process with &lt;a href="https://hexdocs.pm/elixir/1.12/GenServer.html#start_link/3" rel="noopener noreferrer"&gt;&lt;code&gt;GenServer.start_link/3&lt;/code&gt;&lt;/a&gt; or when sending a message to a process registered with a registry.&lt;/p&gt;

&lt;p&gt;Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;MyModule&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:via&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Registry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;ServerAlpha&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;RoomRegistry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;room_id&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we’re instructing the &lt;code&gt;GenServer&lt;/code&gt; to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Register its PID with the registry &lt;code&gt;ServerAlpha.RoomRegistry&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Associate the process with the key &lt;code&gt;room_id&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, any process can find or send messages to this process by referencing it through &lt;code&gt;{:via, Registry, {ServerAlpha.RoomRegistry, room_id}}&lt;/code&gt;, rather than needing the process’s PID directly.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Use It?
&lt;/h4&gt;

&lt;p&gt;Using &lt;code&gt;{:via, Registry, {...}}&lt;/code&gt; with &lt;code&gt;GenServer.start_link/3&lt;/code&gt; makes the registration part of the startup process, eliminating the need for a separate registration call. It’s a convenient and consistent way to automatically register a process in a registry upon its creation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 2: &lt;code&gt;Registry.register/3&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://hexdocs.pm/elixir/main/Registry.html#register/3" rel="noopener noreferrer"&gt;&lt;code&gt;Registry.register/3&lt;/code&gt;&lt;/a&gt; function, on the other hand, is a direct function call used to manually register the current process with a registry. You call this function within the process you want to register, typically right after it starts. &lt;/p&gt;

&lt;p&gt;Here’s how it might look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ServerAlpha&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;RoomRegistry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;room_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;somedata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This line registers the &lt;em&gt;current&lt;/em&gt; process (from where this function is called) with &lt;code&gt;ServerAlpha.RoomRegistry&lt;/code&gt; under the key &lt;code&gt;room_id&lt;/code&gt;. Typically, the &lt;code&gt;somedata&lt;/code&gt; could be any term, such as room metadata.&lt;/p&gt;

&lt;p&gt;This approach requires the process to register itself after it has been started, making it more suitable for cases where the registration process involves additional logic or metadata.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Use It?
&lt;/h4&gt;

&lt;p&gt;With &lt;code&gt;Registry.register/3&lt;/code&gt;, you can choose when and where to register the process, allowing more flexibility. This can be especially useful if you need to set custom metadata for the registered process or if the registration conditionally depends on certain initialization steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Differences: &lt;code&gt;{:via, Registry, {...}}&lt;/code&gt; vs &lt;code&gt;Registry.register/3&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now that we understand each method, let’s summarize their differences:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;&lt;code&gt;{:via, Registry, {...}}&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;Registry.register/3&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Start or reference a process with a registry.&lt;/td&gt;
&lt;td&gt;Manually register the current process.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Automatic vs. Manual Registration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automatic registration upon process start.&lt;/td&gt;
&lt;td&gt;Manual call to register after process start.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Usage Context&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use with &lt;code&gt;GenServer.start_link/3&lt;/code&gt; or similar.&lt;/td&gt;
&lt;td&gt;Call within process for conditional registration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Metadata Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not intended for custom metadata.&lt;/td&gt;
&lt;td&gt;Allows additional metadata upon registration.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  When to Use Each
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;{:via, Registry, {...}}&lt;/code&gt;&lt;/strong&gt; when you want to make the registry registration part of the process's startup flow. This method is concise and reliable for consistently registering a process upon its creation, making it a great choice for processes with predictable, uniform registration needs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;Registry.register/3&lt;/code&gt;&lt;/strong&gt; when you need more control over the registration. For example, if you need to perform some additional setup before registering or want to include custom metadata with the registration, &lt;code&gt;Registry.register/3&lt;/code&gt; offers that flexibility.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Practical Example: A Room-Based Server
&lt;/h3&gt;

&lt;p&gt;Let’s imagine a chat server where each room has its own GenServer process. You want to register each room process in a registry so that clients can look up rooms by room IDs.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;{:via, Registry, {ServerAlpha.RoomRegistry, room_id}}&lt;/code&gt;, you could start a GenServer for a room and automatically register it under its room ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_room&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;room_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;RoomServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;room_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:via&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Registry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;ServerAlpha&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;RoomRegistry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;room_id&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clients can then look up or interact with room servers directly by referencing &lt;code&gt;{:via, Registry, {ServerAlpha.RoomRegistry, room_id}}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Alternatively, if your GenServers require some initialization before they’re registered, you might start each GenServer without registering it, and then call &lt;code&gt;Registry.register/3&lt;/code&gt; once it’s fully set up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;room_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# Perform setup&lt;/span&gt;
  &lt;span class="no"&gt;Registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ServerAlpha&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;RoomRegistry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;room_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{}}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, registration only happens after the necessary setup steps are complete.&lt;/p&gt;

&lt;h3&gt;
  
  
  In Summary
&lt;/h3&gt;

&lt;p&gt;While &lt;code&gt;{:via, Registry, {...}}&lt;/code&gt; and &lt;code&gt;Registry.register/3&lt;/code&gt; may look similar at first, they have distinct roles in process management:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;{:via, Registry, {...}}&lt;/code&gt; for automatic, inline registration when starting a process.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Registry.register/3&lt;/code&gt; for more control, allowing manual registration and customization.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>elixir</category>
      <category>programming</category>
    </item>
    <item>
      <title>Go 1.20 memory arena</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Sat, 22 Jul 2023 12:05:22 +0000</pubDate>
      <link>https://dev.to/marknefedov/go-120-memory-arena-4kch</link>
      <guid>https://dev.to/marknefedov/go-120-memory-arena-4kch</guid>
      <description>&lt;h2&gt;
  
  
  Enhancing Golang Memory Management with Memory Arenas
&lt;/h2&gt;

&lt;p&gt;One of the groundbreaking features of Go, compared to other compiled languages, is its automatic memory management of unused objects through garbage collection. However, this can lead to performance degradation by handing over control to the memory management process. Until Go 1.20, no alternative mechanism was provided. With the introduction of Go 1.20, an experimental memory management solution called Memory Arena has been added. This article explores the key aspects of using Memory Arenas in Go 1.20 to combine safe dynamic memory allocation and reduce the impact of integrated memory management on application performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enabling Memory Arena Support
&lt;/h3&gt;

&lt;p&gt;To enable support for the new memory management mechanism, add the following environment variable:&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;export &lt;/span&gt;&lt;span class="nv"&gt;GOEXPERIMENT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arenas
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to allocate memory, use the new arena module:&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="s"&gt;"arena"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Lastname&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
  &lt;span class="n"&gt;Firstname&lt;/span&gt; &lt;span class="kt"&gt;string&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;mem&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewArena&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;mem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Free&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;10&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;obj&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As demonstrated, object addresses are allocated sequentially from a single memory area, and the entire allocated arena is freed after calling &lt;code&gt;Free()&lt;/code&gt;. With proper usage, this improves code performance since garbage collection will not be called for the arena. &lt;/p&gt;

&lt;h3&gt;
  
  
  Copying Data and Creating Slices
&lt;/h3&gt;

&lt;p&gt;If you need to copy data to a regular heap, use the &lt;code&gt;Clone&lt;/code&gt; method, which creates a copy of the structure from the arena to regular dynamic memory (for example, when you need to return the processing result to the main application). You can also create slices in the arena by specifying the initial size and potential capacity using &lt;code&gt;arena.MakeSlice(mem, initial, capacity)&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Allocating Memory with Reflect
&lt;/h3&gt;

&lt;p&gt;To allocate memory based on a type from &lt;code&gt;reflect&lt;/code&gt;, use the new method &lt;code&gt;reflect.ArenaNew(mem, typ)&lt;/code&gt; which returns a pointer to an object of the given type allocated in the arena stored in &lt;code&gt;mem&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error Detection and Address Sanitizers
&lt;/h3&gt;

&lt;p&gt;Detect errors when using the arena (for example, reading or writing a value to a structure after freeing the arena) using mechanisms like &lt;code&gt;go run -asan&lt;/code&gt; (Address Sanitizer) or &lt;code&gt;go run -msan&lt;/code&gt; (Memory Sanitizer). For example:&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="s"&gt;"arena"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="kt"&gt;int32&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;mem&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewArena&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When running with asan/msan, it will show an error of incorrect pointer usage after freeing the arena.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storing Strings in the Arena
&lt;/h3&gt;

&lt;p&gt;To store strings in the arena, create a memory region from a byte sequence and copy the string contents into it, like this:&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="n"&gt;src&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;"original"&lt;/span&gt;

&lt;span class="n"&gt;mem&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewArena&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;mem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;bs&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nb"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;unsafe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using the Arena for Primitive Data Types
&lt;/h3&gt;

&lt;p&gt;The arena can also be used for storing structures, primitive data types, or their sequences. In this case, the interaction is no different from working with a pointer to a variable:&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="s"&gt;"arena"&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;mem&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewArena&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;mem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
  &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;v&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;Similarly, the behavior of slices in the arena is no different from regular slices in Go:&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="s"&gt;"arena"&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;mem&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewArena&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;mem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Free&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;arena&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MakeSlice&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;int32&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="n"&gt;mem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;49&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;49&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;        &lt;span class="c"&gt;//10&lt;/span&gt;
  &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;50&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;        &lt;span class="c"&gt;//20&lt;/span&gt;
  &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;       &lt;span class="c"&gt;//51&lt;/span&gt;
  &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;       &lt;span class="c"&gt;//100&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Detecting Memory Leaks
&lt;/h3&gt;

&lt;p&gt;To detect memory leaks when using arenas, use the usual profiling mechanisms in Go (go tool pprof for visualizing memory allocation sampling, which can be saved via functions in the runtime/pprof module). From the point of view of memory allocation, working with an arena is similar to allocating a single memory block (which can grow in size). When the arena is freed, all objects allocated in it become inaccessible.&lt;/p&gt;

&lt;p&gt;Performance improvements can be expected in cases where the application intensively allocates memory (for example, when storing binary trees or other related data structures). However, it is assumed that the allocated data structures are long-lived and exist until the arena is freed entirely (the garbage collector is not applied to the arena, and allocated objects in the contiguous memory area are not cleaned up).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In summary, the introduction of Memory Arenas in Go 1.20 provides an experimental memory management solution that allows for safe dynamic memory allocation while reducing the impact of integrated memory management on application performance. Key aspects of using Memory Arenas include enabling support through an environment variable, allocating memory using the new arena module, copying data and creating slices, allocating memory with &lt;code&gt;reflect&lt;/code&gt;, error detection using Address and Memory Sanitizers, storing strings and primitive data types in the arena, and detecting memory leaks using profiling mechanisms in Go.&lt;/p&gt;

&lt;p&gt;Memory Arenas offer potential performance improvements in cases where applications intensively allocate memory, such as storing binary trees or other related data structures. However, it is important to note that the allocated data structures are expected to be long-lived and exist until the arena is freed entirely, as the garbage collector does not apply to the arena and allocated objects in the contiguous memory area are not cleaned up.&lt;/p&gt;

</description>
      <category>go</category>
      <category>performance</category>
      <category>news</category>
    </item>
    <item>
      <title>Setup screen session for interviewee monitoring</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Fri, 14 Jul 2023 12:47:31 +0000</pubDate>
      <link>https://dev.to/marknefedov/setup-screen-session-for-interviewee-monitoring-4lj8</link>
      <guid>https://dev.to/marknefedov/setup-screen-session-for-interviewee-monitoring-4lj8</guid>
      <description>&lt;p&gt;This tutorial provides a step-by-step guide on setting up a shared screen session for a Linux interview. By following these steps, you can give the interviewee access to a Linux box while monitoring their inputs. Although the steps are mostly similar for all Linux distributions, minor adjustments may be required for different shells.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create a User for the Interviewee
&lt;/h3&gt;

&lt;p&gt;First, create a new user account for the interviewee using the &lt;code&gt;useradd&lt;/code&gt; command. The &lt;code&gt;-m&lt;/code&gt; flag creates a home directory for the new user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; interviewee
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Install the &lt;code&gt;screen&lt;/code&gt; Utility
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;screen&lt;/code&gt; utility allows you to create and manage multiple terminal sessions. If it's not already installed on your system, use the appropriate package manager command for your Linux distribution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For SUSE:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zypper &lt;span class="k"&gt;in &lt;/span&gt;screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;For Debian/Ubuntu:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;For RHEL/Fedora:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnf &lt;span class="nb"&gt;install &lt;/span&gt;screen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Modify the &lt;code&gt;.profile&lt;/code&gt; File to Create a &lt;code&gt;screen&lt;/code&gt; Session at User Login
&lt;/h3&gt;

&lt;p&gt;Next, update the &lt;code&gt;.profile&lt;/code&gt; file in the interviewee's home directory to automatically create a &lt;code&gt;screen&lt;/code&gt; session when they log in. Use the &lt;code&gt;echo&lt;/code&gt; command to append the necessary line to the 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="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"screen -S interviewee-session"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /home/interviewee/.profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to replace &lt;code&gt;/home/interviewee&lt;/code&gt; with the actual path to the interviewee's home directory if it's different on your system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Access the Shared Screen Session
&lt;/h3&gt;

&lt;p&gt;Now you can give the interviewee their credentials, and they can log in to the system. To monitor their actions, switch to the user account you created and access the shared screen session using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;screen &lt;span class="nt"&gt;-x&lt;/span&gt; interviewee-session
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! You've successfully set up a shared screen session for a Linux interview.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KNHQ-iuAqbg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>linux</category>
      <category>terminal</category>
      <category>interview</category>
    </item>
    <item>
      <title>Dotnet authentication clock skew.</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Tue, 20 Jun 2023 06:39:12 +0000</pubDate>
      <link>https://dev.to/marknefedov/dotnet-authentication-clock-skew-ibi</link>
      <guid>https://dev.to/marknefedov/dotnet-authentication-clock-skew-ibi</guid>
      <description>&lt;p&gt;If you use dotnet JWT authentication check your &lt;code&gt;TokenValidationParameters&lt;/code&gt;, and make sure you have set &lt;code&gt;ClockSkew&lt;/code&gt; to reasonable values. By default, it is set to 300 seconds (5 minutes). That make your JWT tokens valid for extra 5 minutes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;/// Gets or sets the clock skew to apply when validating a time.&lt;/span&gt;
        &lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;/// &amp;lt;exception cref="ArgumentOutOfRangeException"&amp;gt;If 'value' is less than 0.&amp;lt;/exception&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;/// The default is &amp;lt;c&amp;gt;300&amp;lt;/c&amp;gt; seconds (5 minutes).&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;DefaultValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt; &lt;span class="n"&gt;ClockSkew&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;get&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_clockSkew&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;set&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Zero&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="n"&gt;LogHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogExceptionMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;LogHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FormatInvariant&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LogMessages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IDX10100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LogHelper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MarkAsNonPII&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))));&lt;/span&gt;

                &lt;span class="n"&gt;_clockSkew&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>dotnet</category>
      <category>auth</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Nginx TCP transparent proxy</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Mon, 19 Jun 2023 08:07:57 +0000</pubDate>
      <link>https://dev.to/marknefedov/nginx-tcp-transparent-proxy-4j63</link>
      <guid>https://dev.to/marknefedov/nginx-tcp-transparent-proxy-4j63</guid>
      <description>&lt;p&gt;So we have a setup like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F05tlidc1lxbxs7xsd1qx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F05tlidc1lxbxs7xsd1qx.png" alt="Nginx and upstream configuration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Set gateways to local and external networks:
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ethernets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;ens3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;192.168.229.10/24&lt;/span&gt;
      &lt;span class="na"&gt;gateway4&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.229.15&lt;/span&gt; &lt;span class="c1"&gt;# NGINX transparent proxy&lt;/span&gt;
      &lt;span class="na"&gt;nameservers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;192.168.222.8&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;192.168.222.2&lt;/span&gt;
      &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.222.0/24&lt;/span&gt;
          &lt;span class="na"&gt;via&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;192.168.229.254&lt;/span&gt; &lt;span class="c1"&gt;# Known gateway to internal network&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create a policy where all packets marked with 1 will be routed to loopback interface for nginx processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ip rule add fwmark 1 lookup 100&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Firewall marks are a feature of the Linux kernel's networking stack that allow you to "mark" packets with a certain value, which can then be used for making routing decisions. This can be useful for complex network setups where you need to route traffic differently based on criteria other than the destination IP.&lt;/p&gt;

&lt;p&gt;In this case, the rule is saying that any packets with a firewall mark of &lt;strong&gt;&lt;code&gt;1&lt;/code&gt;&lt;/strong&gt; (which would have been set by a previous step, perhaps an iptables rule) should use routing table &lt;strong&gt;&lt;code&gt;100&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ip route add local 0.0.0.0/0 dev lo table 100&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This command adds a route to table &lt;strong&gt;&lt;code&gt;100&lt;/code&gt;&lt;/strong&gt; that sends all traffic (&lt;strong&gt;&lt;code&gt;0.0.0.0/0&lt;/code&gt;&lt;/strong&gt; represents all IP addresses) to the loopback interface (&lt;strong&gt;&lt;code&gt;lo&lt;/code&gt;&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;code&gt;local&lt;/code&gt;&lt;/strong&gt; keyword is used to indicate that these packets are to be treated as local and not to be forwarded. This is typically used when the system itself will be processing the packets, rather than forwarding them on to another network.&lt;/p&gt;

&lt;p&gt;So this rule is saying that any traffic which gets directed to table &lt;strong&gt;&lt;code&gt;100&lt;/code&gt;&lt;/strong&gt; (such as by the previous &lt;strong&gt;&lt;code&gt;ip rule&lt;/code&gt;&lt;/strong&gt; command) should be sent to the local loopback interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;firewall-cmd --permanent --direct --add-rule ipv4 mangle PREROUTING 0 -p tcp -s 192.168.229.10/31 --sport 3232 -j MARK --set-xmark 0x1/0xffffffff&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This command adds a permanent direct rule to the firewalld configuration, which marks TCP packets with a source IP address in the range &lt;code&gt;192.168.229.10/31&lt;/code&gt; and a source port of &lt;code&gt;3232&lt;/code&gt; in the PREROUTING chain of the mangle table. The mark value is set to &lt;code&gt;0x1&lt;/code&gt; with a mask of &lt;code&gt;0xffffffff&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Add directives nginx configuration:&lt;/strong&gt;
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;3232&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_bind&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt; &lt;span class="s"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;sftp1&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;Enable NGINX transparent proxy handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Change gateway address to NGINX to send all responses to spoofed packets back to NGINX.&lt;/li&gt;
&lt;li&gt;Configure iptables/nftables to mark incoming traffic from upstream.&lt;/li&gt;
&lt;li&gt;Create a rule and a routing table to send marked traffic local processing for nginx to pick it up.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>devops</category>
      <category>networking</category>
    </item>
    <item>
      <title>Shard Key Best Practices: Ensuring Balanced and Efficient Data Distribution</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Mon, 12 Jun 2023 11:58:16 +0000</pubDate>
      <link>https://dev.to/marknefedov/shard-key-best-practices-ensuring-balanced-and-efficient-data-distribution-l1l</link>
      <guid>https://dev.to/marknefedov/shard-key-best-practices-ensuring-balanced-and-efficient-data-distribution-l1l</guid>
      <description>&lt;p&gt;Alright folks, we're going to dive into the nitty-gritty world of distributed databases today. You know, those complex systems that split data across multiple nodes or shards (fancy name for pieces) to ensure things run smoothly and efficiently. One of the big players in this game is the shard key. It's a specific field or fields that decides how data gets divvied up across the nodes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Importance of Shard Keys in Distributed Databases
&lt;/h2&gt;

&lt;p&gt;A shard key is a specific field or set of fields used to determine how data is partitioned across the nodes in a distributed database system. The choice of a shard key is central to ensuring a balanced distribution of data and optimizing the performance of read and write operations. Therefore, a carefully chosen shard key can lead to better utilization of resources, improved query performance, and increased scalability.&lt;/p&gt;

&lt;h2&gt;
  
  
  High Cardinality: The Key to Even Distribution
&lt;/h2&gt;

&lt;p&gt;Cardinality is a term that originates from mathematics, specifically set theory, where it's used to count the number of elements in a set. In the context of databases, however, cardinality takes on a slightly different meaning. It's still about counting, but here it refers to the number of unique values in a column or a set of columns.&lt;/p&gt;

&lt;p&gt;For example, consider a database that stores information about people. If there's a column for "gender" and you only record "male", "female", and "prefer not to say", the cardinality of the "gender" column is 3 because there are 3 unique values. But if there's a column for "social security number", the cardinality would be very high (assuming you have many records), because each person has a unique social security number.&lt;/p&gt;

&lt;p&gt;High cardinality refers to columns with values that are very uncommon or unique. A column with high cardinality would have values that are typically distinct or unusual. This could be an email address or a transaction id, where each record has a unique value.&lt;/p&gt;

&lt;p&gt;On the other hand, low cardinality refers to columns with values that are very common or repeating. For instance, a "yes/no" column has a cardinality of 2.&lt;/p&gt;

&lt;p&gt;In the context of shard keys in distributed databases, a high cardinality is preferred because it provides a greater number of potential partitions for the data, allowing for a more even distribution across the nodes in the database cluster. If you had a low cardinality shard key, you'd end up with less potential partitions, and that could lead to an uneven distribution of data, which could impact the performance of your database.&lt;/p&gt;

&lt;p&gt;In a nutshell, cardinality is all about the uniqueness of data in a column, and when choosing a shard key, going for high cardinality can help you ensure a more balanced and efficient distribution of data in a distributed database system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Low Frequency: Avoiding Shard Key Hotspotting
&lt;/h2&gt;

&lt;p&gt;Frequency, in the simplest terms, is how often a particular value occurs in a dataset. So, when we talk about low frequency in relation to databases, we're referring to values in a column that don't show up very often.&lt;/p&gt;

&lt;p&gt;Imagine you have a database table that logs the activities of users on a website. If there's a column called "activity_type" that records whether a user "logged in", "logged out", "posted a comment", "liked a post", etc., the frequency of each activity is how often it appears in that column. If "logged in" and "logged out" are very common activities, they have high frequency. On the other hand, if "deleted account" is a rare activity, it has low frequency.&lt;/p&gt;

&lt;p&gt;Now, let's bring shard keys into the picture. When selecting a shard key for a distributed database, choosing one that has low frequency values is typically beneficial. Here's why: if a shard key value appears very frequently, it means many records will have the same shard key value and they will all be directed to the same shard or node. This can create an imbalance in the data distribution, where one shard is handling a lot of data (and therefore work), while others have less data and might be under-utilized.&lt;/p&gt;

&lt;p&gt;This could also lead to "hotspotting", where one node becomes a hotspot due to a high volume of read/write requests. Hotspots can seriously degrade the performance of your database. So, selecting a shard key with low frequency values can help avoid this situation by ensuring a more even distribution of data across the shards.&lt;/p&gt;

&lt;p&gt;So, to sum it up, when we say "low frequency" in the context of shard keys, we're talking about choosing a field that has a lot of unique or less commonly occurring values, which helps to balance the load across the nodes in a distributed database system and prevent any one node from being overwhelmed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case Considerations
&lt;/h2&gt;

&lt;p&gt;While high cardinality and low frequency are general principles, the ideal shard key will also depend on the specific use case, including the nature of the data, the expected query patterns, and the read/write workload. For example, if the database mainly supports read operations and the data is not updated frequently, a different sharding strategy might be more effective. Often a composite shard key (made up of multiple fields) might be used to achieve better distribution and performance. &lt;/p&gt;

&lt;p&gt;Here are a couple of examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User ID in a User Profile Table&lt;/strong&gt;: Suppose you have a table storing user profiles, where each row represents a unique user. In this case, using 'user_id' as the partition key would be an ideal choice. Each 'user_id' is unique to an individual user (high cardinality), and since each user_id will only show up once in the user profile table, it has a low frequency. This ensures a balanced distribution of data across the Cassandra nodes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transaction ID in an E-commerce Transactions Table&lt;/strong&gt;: In an e-commerce application, you could have a table logging every transaction. Each transaction would have a unique 'transaction_id', which would be a perfect candidate for the partition key. Similar to the previous example, this provides high cardinality (each transaction is unique) and low frequency (each 'transaction_id' shows up only once).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For instance, if you frequently retrieve data based on 'user_id' and 'transaction_date', you might choose a composite partition key consisting of these two fields. This would still provide high cardinality (assuming you have many users and transactions spread across different dates), and each combination of 'user_id' and 'transaction_date' would have a low frequency, helping to evenly distribute data across your nodes.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>database</category>
      <category>distributedsystems</category>
      <category>data</category>
    </item>
    <item>
      <title>Switch statements are a lie.</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Mon, 05 Jun 2023 09:25:52 +0000</pubDate>
      <link>https://dev.to/marknefedov/switch-statements-are-a-lie-440f</link>
      <guid>https://dev.to/marknefedov/switch-statements-are-a-lie-440f</guid>
      <description>&lt;h1&gt;
  
  
  Switch Statements Are a Lie
&lt;/h1&gt;

&lt;p&gt;For those who first encounter the switch statement in their early programming journey, it might appear as a magic construct that significantly simplifies logic by allowing a multi-way branch. However, as with many things in the programming world, what you see is not always what you get. While switch statements in high-level languages like C or C++ have their syntax and semantics, the story behind the scenes, in the realm of the compiler, is far more complex. Let's unravel this mystery.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Illusion of Jump Tables
&lt;/h2&gt;

&lt;p&gt;You might have been taught or intuitively believed that the compiler translates a switch statement into a jump table in assembly, which should allow for constant-time selection of code blocks regardless of the number of cases. Indeed, in a perfect world where all case values are densely packed, starting from zero or some manageable offset, this would be a reasonable and efficient translation. Unfortunately, the real-world situations are often less ideal, and a jump table is not always the go-to solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Factors Preventing Jump Table Generation
&lt;/h2&gt;

&lt;p&gt;So, what factors can derail the creation of a jump table for a switch statement in the compiler's realm? Here are some major considerations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Density of case values&lt;/strong&gt;: If the case values are scattered over a wide range, the jump table, which usually covers all values from the lowest to the highest, could become overwhelmingly large and impractical. Consider a switch statement with two cases: 1 and 1,000,000. The jump table for this would theoretically require a million entries!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Size of the range of case values&lt;/strong&gt;: Even if the case values are densely packed, a large range of values could still make a jump table infeasible due to memory limitations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Number of cases&lt;/strong&gt;: With only a few cases, it might be more efficient to generate a series of if-else statements (also known as a binary search tree), as the overhead of creating, initializing, and using a jump table might outweigh its benefits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compiler's optimization level&lt;/strong&gt;: Depending on the optimization settings, the compiler may favor execution speed, code size, or a balance between them. Higher optimization levels are more likely to generate a jump table, prioritizing speed, while lower levels may prefer a series of comparisons to conserve memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Order of case labels&lt;/strong&gt;: Some compilers might rely on case labels being in ascending order to generate a jump table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compiler's internal heuristics&lt;/strong&gt;: Finally, compilers use complex internal heuristics that take into account all the above factors and possibly many others. These heuristics are part of the compiler's design and tend to evolve as compiler technology progresses.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Deconstructing the Lie
&lt;/h2&gt;

&lt;p&gt;So, what does a compiler do when a jump table is off the table? Often, it resorts to a series of comparisons and jumps - essentially an if-else-if chain or a binary search tree, depending on the specifics. This transformation might surprise programmers who believed in the illusion of the "switch-as-a-jump-table."&lt;/p&gt;

&lt;p&gt;Let's consider a C++ switch statement. When translated into assembly, you would see a series of &lt;code&gt;cmp&lt;/code&gt; (compare) and &lt;code&gt;je&lt;/code&gt; (jump if equal) instructions corresponding to each case. If the case matches the input value, the program jumps to the associated code block. Otherwise, it continues to the next comparison. If none of the cases match, the program reaches the equivalent of the &lt;code&gt;default&lt;/code&gt; clause. The actual instruction set and structure might vary based on the architecture and the compiler, but the principle remains the same.&lt;/p&gt;

&lt;p&gt;Let's illustrate this with a tangible example. Consider the following C++ code snippet: &lt;a href="https://godbolt.org/z/qhWrd3dP3"&gt;https://godbolt.org/z/qhWrd3dP3&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;ctime&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cstdlib&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&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;srand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 0&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 10&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 20&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 30&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 40&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 50&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 60&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 70&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 80&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 90&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is 100&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="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;default:&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Value is out of range&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="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        cmp     edx, 5
        je      .L7
        cmp     eax, 50
        jle     .L24
        cmp     edx, 8
        je      .L16
        cmp     eax, 80
        jg      .L17
        cmp     edx, 6
        je      .L18
        cmp     edx, 7
        jne     .L13
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code generates a random number between 0 and 100 and uses a switch statement to select the appropriate output message. One might expect the compiler to translate this into a jump table. However, examining the resulting assembly code reveals that the compiler actually transforms the switch into a series of comparisons and conditional jumps. &lt;/p&gt;

&lt;p&gt;In the assembly output, the &lt;code&gt;cmp&lt;/code&gt; and &lt;code&gt;je&lt;/code&gt; instructions correspond to each case. If the value matches, the program jumps to the corresponding code block. If none of the case values match, the code reaches the "default" block, which outputs the "Value is out of range" message.&lt;/p&gt;

&lt;p&gt;This serves as a potent illustration that what we imagine as a straightforward jump table can, in fact, be something quite different under the hood.&lt;/p&gt;

&lt;h2&gt;
  
  
  Embracing the Truth
&lt;/h2&gt;

&lt;p&gt;Given this understanding, does it mean switch statements are useless? Absolutely not! Regardless of how they're implemented under the hood, switch statements can still greatly enhance the readability and maintainability of your code by providing a clear, compact way of handling multiple conditions based on a single value. However, it's important for programmers to understand the truth behind switch statements and consider performance implications in critical code paths. Understanding your compiler's behavior can help you write more efficient and effective code.&lt;/p&gt;

&lt;p&gt;So, the next time you write a switch statement, remember it's not always what it seems. You're not directly commanding the hardware, but giving suggestions to a complex compiler system that's doing its best to translate your high-level intentions into efficient low-level operations. The art of programming lies not only in mastering the language syntax but also in understanding the underlying processes that bring your code to life.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>discuss</category>
      <category>programming</category>
      <category>cpp</category>
    </item>
    <item>
      <title>Interview tips I wish I've known.</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Sun, 04 Jun 2023 13:58:29 +0000</pubDate>
      <link>https://dev.to/marknefedov/interview-tips-i-wish-ive-known-4h6a</link>
      <guid>https://dev.to/marknefedov/interview-tips-i-wish-ive-known-4h6a</guid>
      <description>&lt;h2&gt;
  
  
  It is okay to be nervous.
&lt;/h2&gt;

&lt;p&gt;Many people struggle with expressing their feelings. One helpful tip is to begin your conversation with something like this: "I'm very interested in working for this company. However, I am a bit nervous, so I hope you understand". This lets the interviewer know you may need a bit more time to focus, and it also earns you extra points for communication skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explain how you think.
&lt;/h2&gt;

&lt;p&gt;I struggle with thinking quickly on the spot. If you pose an algorithm question and put me on a whiteboard, I won't be able to give you an answer right away. At work, I'm much more used to spending an entire day researching different solutions before I even come up with something. You can say: " I will try my best to answer all your questions quickly, but when I actually work, I would like to take my time thinking and looking at the problem from many different angles." A lot of people can relate to this, and they probably will give you much more time and space to think clearly. You will also get bonus points in many jobs like engineering, having patience and being methodical is a preferred quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  When encountering a difficult question, acknowledge it.
&lt;/h2&gt;

&lt;p&gt;Instead of panicking, losing focus, and worrying about making a poor impression, simply say, "This seems like a challenging question to me". This shows your interviewer that you understand the complexity of the question. Many people fail to communicate even this much. Even if you don't have the right solution right away, at least it shows that you are able to see the bigger picture. You can propose to simplify question at first and solve a bit more basic example so you can get a better understanding of the problem, and from there work towards final solution. This will give you points for critical thinking and being able to break down complex problems into a smaller chunks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Admit when you don't know an answer.
&lt;/h2&gt;

&lt;p&gt;If you don't know an answer, admit it, and try to explain a potential solution in general terms. For example, if you're asked about Spring Boot authentication, but you've only worked with ASP.NET, you could suggest a solution based on your existing knowledge: "If Spring authentication is similar to .NET's, I think the answer could be something like this…"&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask probing questions.
&lt;/h2&gt;

&lt;p&gt;In a working environment you will often first get a task that won't have all the details necessary for you to go ahead and come up with the solution, so you will be required to ask your co-workers and your superiors further questions about what we are trying to achieve with this particular task and in what way do we approach it by asking your interviewer similar questions. Let your interviewer know you can have a well thought out discussion. You will be surprised how much useful information you’ll find out from your interviewers. Keep in mind that a lot of questions are intentionally given vague, and that the expectation is for you to try and clarify them before you try to answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Talk through your thinking.
&lt;/h2&gt;

&lt;p&gt;Ensure that the interviewer has as much information as possible about how you're approaching a problem. Most of the time, even if you don't have the final solution, interviewers will be satisfied with your overall response. If you couple this with the previous advice about asking clarifying questions, you'll leave a positive impression. At the end of the day, the interviewers are trying to answer one simple question: "Would I want to work with this person?" Regardless of the problem you're working on during the interview, strive to answer that question first.&lt;/p&gt;

</description>
      <category>career</category>
      <category>interview</category>
      <category>discuss</category>
      <category>motivation</category>
    </item>
    <item>
      <title>How to find all structs that Derive known macro in Rust</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Wed, 24 May 2023 18:44:26 +0000</pubDate>
      <link>https://dev.to/marknefedov/how-to-find-all-structs-that-derive-known-macro-in-rust-3j1</link>
      <guid>https://dev.to/marknefedov/how-to-find-all-structs-that-derive-known-macro-in-rust-3j1</guid>
      <description>&lt;p&gt;I've recently embarked on an endeavor to add migration generation to my favorite Rust ORM &lt;a href="https://github.com/weldsorm/welds"&gt;Welds&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Rust's powerful macro system allows us to extend the language in ways that can greatly enhance productivity and maintainability. In this article, I'll focus on a specific use case: finding all the structs in a codebase that derive a particular macro, in this case the &lt;code&gt;WeldsModel&lt;/code&gt; macro.&lt;/p&gt;

&lt;p&gt;The solution provided in the question uses the &lt;code&gt;syn&lt;/code&gt; crate, a parsing library for Rust syntax, and the &lt;code&gt;walkdir&lt;/code&gt; crate, which provides an iterator over the files in a directory and its subdirectories. Here, we'll walk through this solution and explain how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Main Function
&lt;/h2&gt;

&lt;p&gt;First, let's look at the main function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&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;entry&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nn"&gt;walkdir&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;WalkDir&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"welds/examples"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.into_iter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.filter_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="nf"&gt;.path&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="nf"&gt;.is_file&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="nf"&gt;.extension&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"rs"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;File&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unable to open file"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="nf"&gt;.read_to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unable to read file"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;syntax_tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;syn&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;parse_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;weldsmodel_structs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;find_weldsmodel_structs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syntax_tree&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;weldsmodel_struct&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;weldsmodel_structs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Found struct: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weldsmodel_struct&lt;/span&gt;&lt;span class="py"&gt;.ident&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="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;The &lt;code&gt;main&lt;/code&gt; function here uses the &lt;code&gt;WalkDir&lt;/code&gt; iterator from the &lt;code&gt;walkdir&lt;/code&gt; crate to iterate over all the files in the &lt;code&gt;welds/examples&lt;/code&gt; directory and its subdirectories. It filters out directories and non-Rust files (&lt;code&gt;path.extension().unwrap() == "rs"&lt;/code&gt;), then reads the contents of each Rust file into a &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;syn::parse_file&lt;/code&gt; function is then used to parse this string into a syntax tree, which represents the structure of the Rust code in the file. This syntax tree is passed to the &lt;code&gt;find_weldsmodel_structs&lt;/code&gt; function, which returns a &lt;code&gt;Vec&amp;lt;ItemStruct&amp;gt;&lt;/code&gt; containing all structs in the file that derive the &lt;code&gt;WeldsModel&lt;/code&gt; macro. &lt;a href="https://docs.rs/syn/latest/syn/struct.ItemStruct.html"&gt;ItemStruct&lt;/a&gt; is a &lt;code&gt;syn&lt;/code&gt; data model that describes &lt;code&gt;struct&lt;/code&gt; in a Rust AST, they will be used later in the project as a data source to build schema from.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;main&lt;/code&gt; function prints out the name of each struct found.&lt;/p&gt;

&lt;h2&gt;
  
  
  The find_weldsmodel_structs Function
&lt;/h2&gt;

&lt;p&gt;Next, let's look at the &lt;code&gt;find_weldsmodel_structs&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;find_weldsmodel_structs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syntax_tree&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;syn&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ItemStruct&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;weldsmodel_structs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Vec&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&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;item&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;syntax_tree&lt;/span&gt;&lt;span class="py"&gt;.items&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nn"&gt;syn&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;Struct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_struct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;has_weldsmodel_derive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;item_struct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;weldsmodel_structs&lt;/span&gt;&lt;span class="nf"&gt;.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_struct&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="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;weldsmodel_structs&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function iterates over all items in the syntax tree, checks if each item is a struct, and if so, checks if the struct derives the &lt;code&gt;WeldsModel&lt;/code&gt; macro using the &lt;code&gt;has_weldsmodel_derive&lt;/code&gt; function. If both conditions are met, the struct is added to the &lt;code&gt;weldsmodel_structs&lt;/code&gt; vector.&lt;/p&gt;

&lt;h2&gt;
  
  
  The has_weldsmodel_derive Function
&lt;/h2&gt;

&lt;p&gt;Finally, the &lt;code&gt;has_weldsmodel_derive&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;has_weldsmodel_derive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item_struct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ItemStruct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;item_struct&lt;/span&gt;&lt;span class="py"&gt;.attrs&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;attr&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;attr&lt;/span&gt;&lt;span class="py"&gt;.meta&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="nf"&gt;.path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.is_ident&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"derive"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;nested&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attr&lt;/span&gt;
                &lt;span class="nf"&gt;.parse_args_with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Punctuated&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;Meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nd"&gt;Token!&lt;/span&gt;&lt;span class="p"&gt;[,]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;parse_terminated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nf"&gt;.unwrap&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;nested_meta&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;nested&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;nested_meta&lt;/span&gt;&lt;span class="nf"&gt;.path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.is_ident&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"WeldsModel"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;true&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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function checks if a given struct item has the &lt;code&gt;WeldsModel&lt;/code&gt; derive attribute. It does this by looking at each attribute of the struct, and if the attribute's path is "derive", it parses the arguments of the attribute with &lt;code&gt;parse_args_with&lt;/code&gt;. This gives a &lt;code&gt;Punctuated&lt;/code&gt; list of &lt;code&gt;Meta&lt;/code&gt; items, each representing an argument of the derive attribute. If any of these arguments' path is "WeldsModel", the function returns &lt;code&gt;true&lt;/code&gt;, otherwise &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;p&gt;That's the overall solution: use &lt;code&gt;WalkDir&lt;/code&gt; to iterate over all Rust files in a directory, use &lt;code&gt;syn::parse_file&lt;/code&gt; to parse the contents of each file into a syntax tree, and then check each ATS node attributes and meta to find structures you need.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Integrate Elxir Phoenix client with JS app.</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Tue, 16 May 2023 16:54:23 +0000</pubDate>
      <link>https://dev.to/marknefedov/integrate-elxir-phoenix-client-with-js-app-352</link>
      <guid>https://dev.to/marknefedov/integrate-elxir-phoenix-client-with-js-app-352</guid>
      <description>&lt;p&gt;If you have an existing JavaScript or TypeScript application, and you’d like to add a Phoenix JavaScript client to it, you can do so by following these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the Phoenix JavaScript client by running the following command in your React project’s directory:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; phoenix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;In your React application, you’ll need to import the &lt;code&gt;Socket&lt;/code&gt; and &lt;code&gt;LongPoll&lt;/code&gt; modules from the &lt;code&gt;phoenix&lt;/code&gt; package, as well as the &lt;code&gt;phoenix&lt;/code&gt; package itself. For example:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Socket&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;phoenix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create a new instance of the &lt;code&gt;Socket&lt;/code&gt; class, passing in the URL of your Phoenix server’s endpoint as the first argument.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ws://localhost:4000/socket&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Connect to the socket by calling the &lt;code&gt;connect&lt;/code&gt; method on the socket object. For example:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Once the socket is connected, you can join channels and bind to events to receive messages from the server. For example, you can join a channel named “room:lobby” and listen for the “new_msg” event like this:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;room:lobby&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Joined successfully&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resp&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="nx"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unable to join&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new_msg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&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;ol&gt;
&lt;li&gt;To send a message back to the server over this channel, you can use &lt;code&gt;push&lt;/code&gt; method:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new_msg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is a test message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these steps, you should now be able to interact with your Phoenix server using the JavaScript client in your React application.&lt;/p&gt;

&lt;p&gt;Please keep in mind that you might have to modify the server side to handle &lt;code&gt;new_msg&lt;/code&gt; event, depend on your server implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typescript
&lt;/h3&gt;

&lt;p&gt;You can install the &lt;code&gt;@types/phoenix&lt;/code&gt; package, which provides the TypeScript declarations for the Phoenix client. You can do this by running the following command in your project’s directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @types/phoenix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This package provides TypeScript declarations for the Phoenix JavaScript client, so that you can take advantage of TypeScript’s type checking and editor support when working with the Phoenix client in your application.&lt;/p&gt;

&lt;p&gt;You could also use some pre-built package like phoenix-ts that is written in Typescript, but this is not an official library of phoenix.&lt;/p&gt;

&lt;p&gt;It’s also worth noting that these packages may be updated less frequently than the official phoenix package, so you may want to keep an eye on that and consider updating if necessary.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Using Vulkan without linking to it. (volk alternative for vulkan.hpp)</title>
      <dc:creator>Mark Nefedov</dc:creator>
      <pubDate>Tue, 16 May 2023 16:53:30 +0000</pubDate>
      <link>https://dev.to/marknefedov/using-vulkan-without-linking-to-it-volk-alternative-for-vulkanhpp-3amf</link>
      <guid>https://dev.to/marknefedov/using-vulkan-without-linking-to-it-volk-alternative-for-vulkanhpp-3amf</guid>
      <description>&lt;p&gt;Instead of using the full fledged Vulkan SDK, we only can use the &lt;a href="https://github.com/KhronosGroup/Vulkan-Headers"&gt;Vulkan-headers &lt;/a&gt;package and load actual Vulkan implementation from the driver.&lt;/p&gt;

&lt;p&gt;To do this, we need to enable &lt;code&gt;vulkan.hpp&lt;/code&gt; dynamic dispatcher by default by setting &lt;code&gt;VULKAN_HPP_DISPATCH_LOADER_DYNAMIC&lt;/code&gt; to 1, adding &lt;code&gt;VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE&lt;/code&gt; to the source file and updating &lt;code&gt;VULKAN_HPP_DEFAULT_DISPATCHER&lt;/code&gt; as we load in more Vulkan features.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1
#include&lt;/span&gt; &lt;span class="cpf"&gt;"vulkan/vulkan.hpp"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// Vulkan defined macro storage for dispatch loader&lt;/span&gt;
&lt;span class="n"&gt;VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&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;vk&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;DynamicLoader&lt;/span&gt; &lt;span class="n"&gt;dl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;PFN_vkGetInstanceProcAddr&lt;/span&gt; &lt;span class="n"&gt;vkGetInstanceProcAddr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getProcAddress&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PFN_vkGetInstanceProcAddr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"vkGetInstanceProcAddr"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;VULKAN_HPP_DEFAULT_DISPATCHER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vkGetInstanceProcAddr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;vk&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Instance&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vk&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;createInstance&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// initialize function pointers for instance&lt;/span&gt;
    &lt;span class="n"&gt;VULKAN_HPP_DEFAULT_DISPATCHER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// create a dispatcher, based on additional vkDevice/vkGetDeviceProcAddr&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;vk&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;PhysicalDevice&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;physicalDevices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enumeratePhysicalDevices&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
    &lt;span class="n"&gt;vk&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Device&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;physicalDevices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;createDevice&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nb"&gt;nullptr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// function pointer specialization for device&lt;/span&gt;
    &lt;span class="n"&gt;VULKAN_HPP_DEFAULT_DISPATCHER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&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;



</description>
      <category>cpp</category>
    </item>
  </channel>
</rss>
