<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Iskander (Alex) Sharipov technical blog</title>
    <link>https://quasilyte.dev/blog/</link>
    <description>Recent content on Iskander (Alex) Sharipov technical blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 13 Oct 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://quasilyte.dev/blog/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Zero alloc pathfinding in Go</title>
      <link>https://quasilyte.dev/blog/post/pathfinding/</link>
      <pubDate>Fri, 13 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/pathfinding/</guid>
      <description>Intro Algorithms are important. The problem is you can implement the same algorithm so differently.
The implementation performance can range from blazing fast to barely acceptable.
 Tutorial: if you see an underlined text that is not a link, hover over it to read a tooltip.
 If you like optimizations, specialized data structures and bit tricks then this article is for you.
We&amp;rsquo;ll concentrate on two algorithms today: A-star and greedy BFS.</description>
    </item>
    
    <item>
      <title>Generations-based array</title>
      <link>https://quasilyte.dev/blog/post/gen-map/</link>
      <pubDate>Fri, 22 Sep 2023 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/gen-map/</guid>
      <description>Intro I was intrigued by the sparse map/set described in Russ Cox&amp;rsquo;s article.
And I&amp;rsquo;m not the only one: this exact implementation is used in Go source code more than once! The compiler uses it for many ID-like maps and sets; regexp package uses it for a queue.
But there is one thing that is still bugging me: it&amp;rsquo;s hard to make it very efficient. All operations I care about are O(1), but get and set operations clearly become slower in comparison with a straightforward slice approach.</description>
    </item>
    
    <item>
      <title>A simpler scheme than SSA</title>
      <link>https://quasilyte.dev/blog/post/naive-ssa-alternative/</link>
      <pubDate>Sat, 26 Mar 2022 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/naive-ssa-alternative/</guid>
      <description>The SSA complexities Let&amp;rsquo;s suppose that you&amp;rsquo;re working on some small compiler-like project. At some point, you may start thinking about adding optimizations to the code generated by your compiler.
Then you realize that it&amp;rsquo;s not enough to just have some IR that is suitable for modifications. It&amp;rsquo;s important to apply only those optimizations that keep the code correct (or at least don&amp;rsquo;t make it more broken than it was before).</description>
    </item>
    
    <item>
      <title>Profile-guided code search</title>
      <link>https://quasilyte.dev/blog/post/profile-guided-gogrep/</link>
      <pubDate>Tue, 21 Dec 2021 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/profile-guided-gogrep/</guid>
      <description>If you found a typo or a misspelling, please [file an issue](https://github.com/quasilyte/blog-src/issues/new) or send a PR that fixes it.  Original (ru): https://habr.com/ru/post/596755/.
 If you combine a structural code search of gogrep and CPU profile filtering with perf-heatmap, you&amp;rsquo;ll get a profile-guided code search.
This combo lets you find complex code patterns that occur only on the &amp;ldquo;hot&amp;rdquo; code path, so optimizing them can be worthwhile.
perf-heatmap can also be used by a text editor to display the source code lines performance heat levels as shown below.</description>
    </item>
    
    <item>
      <title>A single point of exit</title>
      <link>https://quasilyte.dev/blog/post/single-exit/</link>
      <pubDate>Tue, 15 Jun 2021 00:48:18 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/single-exit/</guid>
      <description>There are other similar articles, like Why you shouldn&amp;rsquo;t use func main in Go. This post addresses the issue from a slightly different angle.
 tl;dr: You program should probably have only one os.Exit() call, if any.
That includes all indirect calls: log.Fatal() and any other function that calls os.Exit() at some point.
If your main looks like this, then this article is for you:
func main() { x, err := doSomething() defer x.</description>
    </item>
    
    <item>
      <title>ruleguard rules package management</title>
      <link>https://quasilyte.dev/blog/post/ruleguard-modules/</link>
      <pubDate>Mon, 21 Dec 2020 00:54:25 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/ruleguard-modules/</guid>
      <description>Bundles is a new feature coming to the ruleguard. It&amp;rsquo;ll make it possible to re-use third-party rules without having to copy/paste them.
Creating an importable bundle A package that exports rules must define a Bundle object:
package gorules import &amp;#34;github.com/quasilyte/go-ruleguard/dsl&amp;#34; // Bundle holds the rules package metadata. // // In order to be importable from other gorules package, // a package must define a Bundle variable. var Bundle = dsl.Bundle{} func boolComparison(m dsl.</description>
    </item>
    
    <item>
      <title>YAML is your JSON5</title>
      <link>https://quasilyte.dev/blog/post/yaml5/</link>
      <pubDate>Thu, 10 Sep 2020 22:01:24 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/yaml5/</guid>
      <description>TL;DR:
 Write YAML as JSON5 (but use # for comments) Enforce this style with yaml5 lint  # JSON5? YAML? {a: 1, b: [&amp;#39;x&amp;#39;, &amp;#39;y&amp;#39;]} What you see above is a valid YAML 1.2 document.
It uses the flow-style syntax for objects and arrays.
If you look at the JSON5 feature list, you can deduce that YAML is a superset of JSON5.
The only difference is the single-line comment syntax.</description>
    </item>
    
    <item>
      <title>Calling Go funcs from asm and JITed code</title>
      <link>https://quasilyte.dev/blog/post/call-go-from-jit/</link>
      <pubDate>Sat, 20 Jun 2020 10:41:50 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/call-go-from-jit/</guid>
      <description>If you found a typo or a misspelling, please [file an issue](https://github.com/quasilyte/blog-src/issues/new) or send a PR that fixes it.  Original (ru): https://habr.com/ru/post/489482/.
 Intro As long as your assembler code does something simple, you&amp;rsquo;re golden.
As soon as you&amp;rsquo;ll need to call a Go function from it, the first suggestion that you&amp;rsquo;ll probably get: don&amp;rsquo;t do it. Perhaps you would like to follow that advice, especially if you&amp;rsquo;re unsure why you needed it in the first place.</description>
    </item>
    
    <item>
      <title>gogrep: structural search and replace</title>
      <link>https://quasilyte.dev/blog/post/gogrep/</link>
      <pubDate>Sun, 07 Jun 2020 14:11:49 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/gogrep/</guid>
      <description>If you found a typo or a misspelling, please [file an issue](https://github.com/quasilyte/blog-src/issues/new) or send a PR that fixes it.  Original (ru): https://habr.com/post/481696/.
 gogrep is one of my favorite tools. It gives you the ability to search Go code using syntax patterns, filter matches by expression types, and perform structural replace.
Today I&amp;rsquo;ll talk about how to use gogrep and about VS Code extension that integrates gogrep into the editor.</description>
    </item>
    
    <item>
      <title>Let&#39;s Go write Pratt parsers!</title>
      <link>https://quasilyte.dev/blog/post/pratt-parsers-go/</link>
      <pubDate>Fri, 27 Mar 2020 17:08:04 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/pratt-parsers-go/</guid>
      <description>If you found a typo or a misspelling, please [file an issue](https://github.com/quasilyte/blog-src/issues/new) or send a PR that fixes it.  Original (ru): https://habr.com/ru/post/494316/.
 Recursive descent parsing works well when you can continue parsing using the current context and a given token.
Some expressions make parsing harder: postfix, infix and other. They introduce a problem: you don&amp;rsquo;t know which kind of expression you&amp;rsquo;re processing until you&amp;rsquo;ve already parsed half of it.</description>
    </item>
    
    <item>
      <title>ruleguard: dynamic inspection rules for Go</title>
      <link>https://quasilyte.dev/blog/post/ruleguard/</link>
      <pubDate>Wed, 08 Jan 2020 21:54:02 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/ruleguard/</guid>
      <description>If you found a typo or a misspelling, please [file an issue](https://github.com/quasilyte/blog-src/issues/new) or send a PR that fixes it.  Original (ru): https://habr.com/post/481696/.
 This article introduces a new static analysis library (and CLI utility) go-ruleguard. It&amp;rsquo;s like a gogrep that is adapted for the use inside your CI pipeline.
You describe static analysis rules in terms of a special Go-like DSL. During the startup, ruleguard turns these definitions into a set of inspections to be executed.</description>
    </item>
    
    <item>
      <title>Step driven evaluation</title>
      <link>https://quasilyte.dev/blog/post/step-pattern/</link>
      <pubDate>Wed, 27 Feb 2019 22:15:32 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/step-pattern/</guid>
      <description>If you heard about table driven tests, the idea described in this article will be easier to grasp, since it&amp;rsquo;s the same technique, but used outside of the tests.
Suppose you have a function that executes a lot of other functions. This function probably does two main things:
 It checks for all returned errors as they occur. It passes one function outputs as the inputs for another.  // process is an example pipeline-like function.</description>
    </item>
    
    <item>
      <title>log.Fatal vs log.Panic</title>
      <link>https://quasilyte.dev/blog/post/log-fatal-vs-log-panic/</link>
      <pubDate>Tue, 08 Jan 2019 01:46:18 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/log-fatal-vs-log-panic/</guid>
      <description>Update: probably the best alternative to log.Fatalf inside main is log.Printf followed by a return statement. If your main function contains a lot of such exit points, consider using a step driven evaluation pattern.
 I personally don&amp;rsquo;t like log.Fatal/Fatalf/Fatalln. I feel sad because of their ubiquity in Go examples as a form of reaction to an error. I personally prefer log.Panic.
The log.Panic vs log.Fatal is essentially panic vs os.</description>
    </item>
    
    <item>
      <title>Go compiler: SSA optimization rules description language</title>
      <link>https://quasilyte.dev/blog/post/go_ssa_rules/</link>
      <pubDate>Sat, 30 Jun 2018 18:53:25 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/go_ssa_rules/</guid>
      <description>Original (ru): https://habr.com/post/415771/.
 Go compiler uses its own Lisp-like domain-specific language (DSL) for Static Single Assignment (SSA) optimization rules description.
Lets dig into that language, its peculiarities and limitations. As an excercise, we&amp;rsquo;ll add a new optimization rule into Go compiler that would optimize expressions like a*b+c using new operations we&amp;rsquo;re going to implement along the way.
This is the first article in the series about Go compiler SSA backend, this is why I&amp;rsquo;ve included some fundamental and architectural info besides DSL overview.</description>
    </item>
    
    <item>
      <title>Go AVX-512 support</title>
      <link>https://quasilyte.dev/blog/post/go-avx512/</link>
      <pubDate>Fri, 08 Jun 2018 13:46:49 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/go-avx512/</guid>
      <description>About this document This article is going to be up-to-date source of AVX-512 information in Go context.
It references other posts, official documentation and other useful resources.
It&amp;rsquo;s short. By purpose.
Only English content is referenced (original + translated).
Documentation   AVX-512 support in Go assembler: short reference that focuses on Go-specific implementation of AVX-512. It describes how to use all AVX-512 special features in Go assembly syntax as well as some encoder details.</description>
    </item>
    
    <item>
      <title>Disassembling Go AVX-512</title>
      <link>https://quasilyte.dev/blog/post/disassembling-go-avx512/</link>
      <pubDate>Fri, 08 Jun 2018 13:29:13 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/disassembling-go-avx512/</guid>
      <description>The problem Go 1.11 got updated assembler that supports AVX-512, but disassembler is left unchanged.
In other words, go tool asm speaks AVX-512, go tool objdump does not.
Suppose we have this avx.s file:
TEXT ·avxCheck(SB), 0, $0 VPOR X0, X1, X2 //; AVX1 VPOR Y0, Y1, Y2 //; AVX2 VPORD.BCST (DX), Z1, K2, Z2 //; AVX-512 RET You will be surprised after assemble+disassemble attempt:
$ go tool asm avx.s $ go tool objdump avx.</description>
    </item>
    
    <item>
      <title>Dispatch tables in Go asm</title>
      <link>https://quasilyte.dev/blog/post/go-asm-dispatch-tables/</link>
      <pubDate>Thu, 31 May 2018 01:39:59 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/go-asm-dispatch-tables/</guid>
      <description>Dispatch tables When you want to execute particular code path depending on some kind of tag/opcode or other integer value that can be easily mapped into index, dispatch tables can speed things up compared to the sequence of comparisons and conditional jumps.
In interpreters, this technique is often used as an alternative to switch-based dispatch.
It&amp;rsquo;s called direct threading in that domain. Each opcode corresponds to table index that contains machine code address that can execute operation specified by the opcode.</description>
    </item>
    
    <item>
      <title>Goism objects layout model</title>
      <link>https://quasilyte.dev/blog/post/goism-objects-layout-mode/</link>
      <pubDate>Sun, 14 Jan 2018 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/goism-objects-layout-mode/</guid>
      <description>Introduction Goism project requires Go pointers emulation inside Emacs Lisp code.
This document describes how to achive (almost) full functionality with potential to have optimizations that eliminate some of the emulation-related overhead.
The actual implementation can diverge. Only initial design is outlined.
Struct representation Go structures represented by lists.
Empty struct run-time value is unspecified, but it satisfies Go spec requirements.
type a1 struct { f1 int } // a1{1} // (list 1)  type a2 struct { f1, f2, f3, f4 int } // a2{1, 2, 3, 4} // (list 1 2 3 4) For the very small (1-3 fields) objects lists are a better choice than vectors, but generally, vectors are more memory-efficient and provide faster random access.</description>
    </item>
    
    <item>
      <title>Writing Emacs Lisp compiler intrinsics</title>
      <link>https://quasilyte.dev/blog/post/writing-emacs-lisp-compiler-intrinsics/</link>
      <pubDate>Sat, 23 Sep 2017 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/writing-emacs-lisp-compiler-intrinsics/</guid>
      <description>The problem Given a particular programming task in Emacs Lisp, you almost always should implement it with function. Sometimes, macro is a proper tool.
Even more rarely, cl-define-compiler-macro may be your choice.
All these methods are safe to use. They almost certanly will not break with newer Emacs versions.
One interesting task that can not be implemented efficiently with approaches that are outlined above is imperative return statement.
Emacs Lisp lacks this kind of flow control and this is a problem we are goind to attack today.</description>
    </item>
    
    <item>
      <title>Go assembly language complementary reference</title>
      <link>https://quasilyte.dev/blog/post/go-asm-complementary-reference/</link>
      <pubDate>Wed, 20 Sep 2017 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/go-asm-complementary-reference/</guid>
      <description>Third flavour of x86 assembly language This article is heavily inspired by AT&amp;amp;T VS Intel/Microsoft assembly syntax comparison page. It helped me very much in the past.
Many tools understand both AT&amp;amp;T and Intel style assembly. Go derived Plan9 toolchain, so you should learn third kind of assembly language. It will not accept anything else.
In this document:
 Comparison of Plan9/Go and AT&amp;amp;T/GNU assembly; Some non-obvious details that are not described anywhere else; Links to useful resources;  Check external resources for information that is missing here.</description>
    </item>
    
    <item>
      <title>Go nested functions and static locals</title>
      <link>https://quasilyte.dev/blog/post/go-nested-functions-and-static-locals/</link>
      <pubDate>Mon, 18 Sep 2017 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/go-nested-functions-and-static-locals/</guid>
      <description>Symbol visibility Default symbol visibility should be as narrow as possible. This means that you use globals with internal linkage instead of external, local variables rather than globals, hide class-related constants inside it&amp;rsquo;s scope, and so on.
If function is only called inside particular function, it should become a nested function.
Most of these rely on the language support.
Go has quite simple model of scopes and symbol visibility. User-defined identifier can be local or package-local (global).</description>
    </item>
    
    <item>
      <title>Path to convenient C FFI in Go</title>
      <link>https://quasilyte.dev/blog/post/cgo-funcall/</link>
      <pubDate>Fri, 18 Aug 2017 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/cgo-funcall/</guid>
      <description>DWIM-style FFI CGo is a widely adopted way of calling C functions from Go: low level C FFI which does many things behind the scene, but exposes only minimal functionality that is required to interact with C.
CGo does no implicit conversions or data copying during C functions call, even int and C.int are not compatible. Code that uses this mechanism without wrappers (bindings) will be polluted with explicit slice/array copies and type conversions.</description>
    </item>
    
    <item>
      <title>RISC-V: custom instruction and its simulation</title>
      <link>https://quasilyte.dev/blog/post/riscv32-custom-instruction-and-its-simulation/</link>
      <pubDate>Wed, 21 Jun 2017 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/riscv32-custom-instruction-and-its-simulation/</guid>
      <description>Agenda This article shows how to add a new instruction to RISC-V and simulate it.
These topics are covered along the way:
 Whole GNU riscv toolchain installation; Implementation of a new instruction for spike RISC-V ISA simulator; Manual instruction encoding in C/C++; Custom instruction simulation (with visible output); [riscv32-]GCC plugin development;  You may find associated repository useful.
Many things can go wrong. Be prepared to fix upcoming issues by yourself.</description>
    </item>
    
    <item>
      <title>Emacs Lisp multi return values</title>
      <link>https://quasilyte.dev/blog/post/elisp-multi-return-values/</link>
      <pubDate>Fri, 19 May 2017 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/elisp-multi-return-values/</guid>
      <description>The missing feature Did you ever wrote a function in Emacs Lisp which should return more than one result?
Emacs Lisp has no native support for multiple return values, but provides cl-lib that emulates it in a Common Lisp style.
In this article I will show that cl-values is suboptimal and can be replaced without any sacrifices to the convenience.
Naive solution cl-lib implements cl-values in terms of list. This approach is naive because each time you return with that, an allocation is involved.</description>
    </item>
    
    <item>
      <title>C broken defaults</title>
      <link>https://quasilyte.dev/blog/post/c-broken-defaults/</link>
      <pubDate>Mon, 26 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/c-broken-defaults/</guid>
      <description>State of the C C fits its niche quite well. If you want relatively simple, ubiquitous and efficient language there is no much room for selection.
It &amp;ldquo;evolves so slowly&amp;rdquo; because it is already quite complete. Most of the parts that can be improved without making C yet another bloated language require breaking changes.
 C could be designed better if we accept older code invalidation.
 &amp;hellip;but in reallity it is impossible to achieve.</description>
    </item>
    
    <item>
      <title>FAQ</title>
      <link>https://quasilyte.dev/blog/post/faq/</link>
      <pubDate>Thu, 01 Dec 2016 00:00:00 +0000</pubDate>
      
      <guid>https://quasilyte.dev/blog/post/faq/</guid>
      <description>Report an issue If you:
 Found a typo; Think some material is inappropriate or incorrect; Want to propose a new article;  &amp;hellip; or you looking for a way to contact author,
just open new Github issue.
Try to be polite and precise in your words, please.
Subscribe Currently, the only way to &amp;ldquo;subscribe&amp;rdquo; for blog updates is to watch blog-src repository.
Go to the linked repository and locate displayed button in the top-right part of the window.</description>
    </item>
    
  </channel>
</rss>
