Skip to content

Commit

Permalink
Minor
Browse files Browse the repository at this point in the history
  • Loading branch information
teivah committed Sep 27, 2023
1 parent 08e9329 commit d99b4c0
Show file tree
Hide file tree
Showing 21 changed files with 15 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/20-slice.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ comments: true

# Not understanding slice length and capacity

![](img/20-slice.png)

It’s pretty common for Go developers to mix slice length and capacity or not understand them thoroughly. Assimilating these two concepts is essential for efficiently handling core operations such as slice initialization and adding elements with append, copying, or slicing. This misunderstanding can lead to using slices suboptimally or even to memory leaks.

In Go, a slice is backed by an array. That means the slice’s data is stored contiguously in an array data structure. A slice also handles the logic of adding an element if the backing array is full or shrinking the backing array if it’s almost empty.
Expand Down
2 changes: 2 additions & 0 deletions docs/28-maps-memory-leaks.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ comments: true

# Maps and memory leaks

![](img/28-maps-memory-leaks.png)

When working with maps in Go, we need to understand some important characteristics of how a map grows and shrinks. Let’s delve into this to prevent issues that can cause memory leaks.

First, to view a concrete example of this problem, let’s design a scenario where we will work with the following map:
Expand Down
2 changes: 2 additions & 0 deletions docs/56-concurrency-faster.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ comments: true

# Thinking concurrency is always faster

![](img/56-concurrency-faster.png)

A misconception among many developers is believing that a concurrent solution is always faster than a sequential one. This couldn’t be more wrong. The overall performance of a solution depends on many factors, such as the efficiency of our code structure (concurrency), which parts can be tackled in parallel, and the level of contention among the computation units. This post reminds us about some fundamental knowledge of concurrency in Go; then we will see a concrete example where a concurrent solution isn’t necessarily faster.

## Go Scheduling
Expand Down
2 changes: 2 additions & 0 deletions docs/89-benchmarks.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ comments: true

# Writing inaccurate benchmarks

![](img/89-benchmarks.png)

In general, we should never guess about performance. When writing optimizations, so many factors may come into play that even if we have a strong opinion about the results, it’s rarely a bad idea to test them. However, writing benchmarks isn’t straightforward. It can be pretty simple to write inaccurate benchmarks and make wrong assumptions based on them. The goal of this post is to examine four common and concrete traps leading to inaccuracy:

* Not resetting or pausing the timer
Expand Down
2 changes: 2 additions & 0 deletions docs/98-profiling-execution-tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ comments: true

# Not using Go diagnostics tooling

![](img/98-profiling-execution-tracing.png)

Go offers a few excellent diagnostics tools to help us get insights into how an application performs. This post focuses on the most important ones: profiling and the execution tracer. Both tools are so important that they should be part of the core toolset of any Go developer who is interested in optimization. First, let’s discuss profiling.

## Profiling
Expand Down
Binary file added docs/img/20-slice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/28-maps-memory-leaks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/56-concurrency-faster.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/89-benchmarks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/98-profiling-execution-tracing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions site/20-slice/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,7 @@


<h1 id="not-understanding-slice-length-and-capacity">Not understanding slice length and capacity</h1>
<p><a class="glightbox" href="../img/20-slice.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/20-slice.png" /></a></p>
<p>It’s pretty common for Go developers to mix slice length and capacity or not understand them thoroughly. Assimilating these two concepts is essential for efficiently handling core operations such as slice initialization and adding elements with append, copying, or slicing. This misunderstanding can lead to using slices suboptimally or even to memory leaks.</p>
<p>In Go, a slice is backed by an array. That means the slice’s data is stored contiguously in an array data structure. A slice also handles the logic of adding an element if the backing array is full or shrinking the backing array if it’s almost empty.</p>
<p>Internally, a slice holds a pointer to the backing array plus a length and a capacity. The length is the number of elements the slice contains, whereas the capacity is the number of elements in the backing array, counting from the first element in the slice. Let’s go through a few examples to make things clearer. First, let’s initialize a slice with a given length and capacity:</p>
Expand Down
1 change: 1 addition & 0 deletions site/28-maps-memory-leaks/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,7 @@


<h1 id="maps-and-memory-leaks">Maps and memory leaks</h1>
<p><a class="glightbox" href="../img/28-maps-memory-leaks.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/28-maps-memory-leaks.png" /></a></p>
<p>When working with maps in Go, we need to understand some important characteristics of how a map grows and shrinks. Let’s delve into this to prevent issues that can cause memory leaks.</p>
<p>First, to view a concrete example of this problem, let’s design a scenario where we will work with the following map:</p>
<div class="language-go highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nx">m</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">int</span><span class="p">][</span><span class="mi">128</span><span class="p">]</span><span class="kt">byte</span><span class="p">)</span>
Expand Down
1 change: 1 addition & 0 deletions site/56-concurrency-faster/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,7 @@


<h1 id="thinking-concurrency-is-always-faster">Thinking concurrency is always faster</h1>
<p><a class="glightbox" href="../img/56-concurrency-faster.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/56-concurrency-faster.png" /></a></p>
<p>A misconception among many developers is believing that a concurrent solution is always faster than a sequential one. This couldn’t be more wrong. The overall performance of a solution depends on many factors, such as the efficiency of our code structure (concurrency), which parts can be tackled in parallel, and the level of contention among the computation units. This post reminds us about some fundamental knowledge of concurrency in Go; then we will see a concrete example where a concurrent solution isn’t necessarily faster.</p>
<h2 id="go-scheduling">Go Scheduling</h2>
<p>A thread is the smallest unit of processing that an OS can perform. If a process wants to execute multiple actions simultaneously, it spins up multiple threads. These threads can be:</p>
Expand Down
1 change: 1 addition & 0 deletions site/89-benchmarks/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,7 @@


<h1 id="writing-inaccurate-benchmarks">Writing inaccurate benchmarks</h1>
<p><a class="glightbox" href="../img/89-benchmarks.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/89-benchmarks.png" /></a></p>
<p>In general, we should never guess about performance. When writing optimizations, so many factors may come into play that even if we have a strong opinion about the results, it’s rarely a bad idea to test them. However, writing benchmarks isn’t straightforward. It can be pretty simple to write inaccurate benchmarks and make wrong assumptions based on them. The goal of this post is to examine four common and concrete traps leading to inaccuracy:</p>
<ul>
<li>Not resetting or pausing the timer</li>
Expand Down
1 change: 1 addition & 0 deletions site/98-profiling-execution-tracing/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,7 @@


<h1 id="not-using-go-diagnostics-tooling">Not using Go diagnostics tooling</h1>
<p><a class="glightbox" href="../img/98-profiling-execution-tracing.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/98-profiling-execution-tracing.png" /></a></p>
<p>Go offers a few excellent diagnostics tools to help us get insights into how an application performs. This post focuses on the most important ones: profiling and the execution tracer. Both tools are so important that they should be part of the core toolset of any Go developer who is interested in optimization. First, let’s discuss profiling.</p>
<h2 id="profiling">Profiling</h2>
<p>Profiling provides insights into the execution of an application. It allows us to resolve performance issues, detect contention, locate memory leaks, and more. These insights can be collected via several profiles:</p>
Expand Down
Binary file added site/img/20-slice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added site/img/28-maps-memory-leaks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added site/img/56-concurrency-faster.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added site/img/89-benchmarks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added site/img/98-profiling-execution-tracing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified site/sitemap.xml.gz
Binary file not shown.

0 comments on commit d99b4c0

Please sign in to comment.