Leandro Proença
low-level curiosity, high-level pragmatism
- Taming non-determinism: from logic gates to LLMs
Or: how engineering keeps turning chaos into reliable computation. And why agentic AI still hasn't solved this. There's a pattern that repeats across the entire history of computing: we take something fundamentally non-deterministic and engineer enough layers on top of it until it behaves
- Understanding Recursion Fundamentals
If for you: Recursion is an obscure topic or you want to understand it a bit better; Tail call and TCO are alien communication methods and; Trampoline is a medicine name Then this article is for you. Here, I'll explain what these terms are in a didactic way and the problems they solve, with
- Arrays in x86 Assembly
Originally posted in Portuguese Recently I wrote a 6-article series about x86 Assembly (written in Portuguese, but I'm planning to translate the guide to English soon), covering fundamental concepts of computer architecture and low-level programming while building a minimalist multi-threaded web
- You don't need Kafka: Building a message queue with only two UNIX signals
Have you ever asked yourself what if we could replace any message broker with a very simple one using only two UNIX signals? Well, I'm not surprised if you didn't. But I did. And I want to share my journey of how I achieved it. If you want to learn about UNIX signals, binary operations the easy
- Um resumo do meu 2024
31 de Dezembro de 2024. Sentado no sofá e assistindo Frozen, tive a ideia de escrever sobre minha retrospectiva deste ano. Nunca fiz isso antes, então bora lá, porque acho que foi muita coisa. Mas antes, um aftermath de 2023 2023 foi um ano bastante agitado pra mim. Passei por uma tireoidectomia
- Voltando às raízes de blogueiro
Já faz um tempo que não escrevo aqui no blog. E também já faz bastante tempo que tenho o interesse em voltar a escrever mais como fazia antigamente, quando tudo o que tinha era algo na mente e simplesmente convertia em um punhado de texto solto no meu blog, como essa relíquia aqui. Gosto de
- Arrays em Assembly x86
Recentemente escrevi uma saga de 6 artigos sobre Assembly x86, abordando conceitos fundamentais de arquitetura de computadores e programação low-level enquanto ia desenvolvendo um web server minimalista multi-threaded. Durante o processo, acabei deixando de lado alguns conceitos importantes para
- Construindo um web server em Assembly x86, the grand finale, multi-threading
Uma vez que temos um web server funcional , podemos dar o próximo (e último) passo, que é deixar o servidor minimamente escalável fazendo uso de uma pool de threads. Neste artigo, vamos mergulhar nas entranhas da implementação de uma pool de threads com sincronização através de locks, e
- Construindo um web server em Assembly x86, parte V, finalmente o server
No artigo anterior , passamos pelos fundamentos de Assembly, onde foi possível entender alguns conceitos básicos tais como tipos de registradores, stack , loops, FLAGS etc, tudo sendo feito com debugging via GDB . Agora, vamos de fato construir um web server muito simples que devolve um HTML com
- Construindo um web server em Assembly x86, parte IV, um assembly modesto
Uma vez que temos uma compreensão sobre sistema binário, hexadecimal, ASCII e código de máquina, chegou o grande momento de entrarmos no assunto principal desta saga: assembly . Vamos iniciar transportando o "Hello, World" feito em código de máquina para assembly x86 e, posteriormente,
- Construindo um web server em Assembly x86, parte III, código de máquina
Agora que já temos uma base de entendimento sobre hierarquia de memória, arquitetura de CPU e registradores, vamos aplicar estes conceitos em exemplos práticos: construindo programas de computador. Mas o que é um programa de computador? Teremos a resposta para esta pergunta ao longo deste
- Construindo um web server em Assembly x86, parte II, história e arquitetura
No artigo anterior demos uma introdução não-técnica sobre o que será esta saga de Assembly x86 conforme avançamos na construção de um web server. Agora, chegou o momento de começarmos a de fato falar sobre coisas técnicas. Como de costume, não gosto de esgormitar termos complexos sem a
- Construindo um web server em Assembly x86, parte I, introdução
Assembly . Para alguns, um monstrinho. Pra outros, algo antiquado. Mas pra quem tem curiosidade em entender como as coisas funcionam, oportunidade . Nesta saga que será uma série de artigos, vamos explorar Assembly com NASM para arquitetura x86-64 em GNU/Linux enquanto desenvolvemos um web server
- Superficial, básico e avançado
Ufa, finalmente meu primeiro artigo de 2024. Criei vergonha na cara coragem e resolvi sentar e escrever um pouco. Vou voltar a escrever coisas técnicas com frequência, prometo Mas antes de tudo, queria deixar claro que este bait post aqui é mais uma reflexão do que algo técnico. Não tem
- Building a dead simple background job in Rust
In today's post we'll explore how to create a basic background job in Rust, simulating Rust channels with a Vector-based queue. First things first Generally, a background job operates on one or more threads that continuously consume messages from a queue. In this post, we'll use a Vector to
- Understanding the basics of Smart Pointers in Rust
In today's post we'll delve into the basics of smart pointers in Rust, while we build from scratch a simple linked list - starting from a singly linked list and then evolving to a doubly one. Prelude, intro to Rust It's not intended to be an introduction about Rust. For that, you can follow along
- Compiladores, trampolim, deque e thread pool
Faz alguns dias que não escrevo. Minha rotina mudou um pouco e também tenho focado em estudar algumas coisas que eu não tinha tanto domínio. Entretanto tenho algumas coisas pra compartilhar. Vamos a isso. Rinha de compiladores Em Setembro de 2023 aconteceu na tal #bolhaDev uma outra
- Rust, Go, Rinha e I/O
Este artigo é o início de um formato diferente de conteúdo que quero experimentar, um apanhado (ou resumão, ou dump, como queiram chamar) de coisas que tenho visto nos últimos dias, com uma pegada informal e um leve toque de didática como de costume. Rust, Go e background jobs Em 2022 eu
- Entendendo fundamentos de recursão
Se pra você: Recursão é um tema obscuro ou quer entender mais um pouco sobre; Tail call e TCO são meios de comunicação alienígena e; Trampoline é nome de remédio Então este artigo é pra você. Aqui, vou explicar o que são estes termos de forma didática e os problemas que resolvem, com
- Vencendo os números de ponto flutuante: um guia de sobrevivência
TL;DR Se quer poupar tempo e ir direto ao assunto, para cálculos precisos, prefira decimais de precisão arbitrária ou equivalentes como BigDecimal em vez de números de ponto flutuante. Além disso, evite arredondamentos desnecessários. Quando necessário, limite o arredondamento apenas na
- Winning at floating-point issues: a survival guide
TL;DR For precise calculations, favor arbitrary-precision decimals or equivalents like BigDecimal over floating-point numbers. Additionally, avoid unnecessary rounding. When required, limit rounding to the final step to maintain as much accuracy as possible. Table of contents Prologue First things
- [pt-BR] Fundamentos do Git, um guia completo
Se você já trabalha com Git diariamente, mas deseja ter uma boa compreensão dos fundamentos do Git, então este post é para você. Aqui, você terá a chance de verdadeiramente entender a arquitetura do Git e como comandos como add, checkout, reset, commit, merge, rebase, cherry-pick, pull,
- AI & Ruby: an introduction to neural networks
Currently we find ourselves in the middle of the hype surrounding Artificial Intelligence (AI) and all its buzzwords. ai hype It's natural to feel that terms related to AI can be complex and overwhelming to many individuals. This article aims to demystify AI applications, delve into Machine
- Kubernetes 101, part VIII, networking fundamentals
So far, we have gained an understanding of the primary workload objects in Kubernetes. These objects enable us to effectively run and manage multiple applications within the cluster. Additionally, we can get benefits from various deployment strategies, create stateful applications, as well as
- Kubernetes 101, part VII, jobs and cronjobs
Our previous article, we learned how DaemonSets can effectively collect data from Kubernetes nodes, allowing data to be structured and sent to appropriate tooling. In this post, we'll delve into the topic of running a single job in Kubernetes through the use of Kubernetes Jobs . Furthermore, we'll
- A comprehensive introduction to Ruby
Another tutorial for learning Ruby? Absolutely not . This guide is different from the typical tutorials you'll find online. As someone new to Ruby, you've likely already completed a few tutorials. Instead of providing yet another tutorial, this guide aims to offer unique insights and valuable
- Kubernetes 101, part VI, daemonsets
For most use cases, deploying core business apps in Kubernetes using Deployments for stateless applications and StatefulSets for stateful applications is good enough. Not rare, we need to deploy components that will not perform the core business work but will support the core business instead. Core
- Kubernetes 101, part V, statefulsets
In the previous article , we explored ways to handle pod updates without affecting availability , using Deployments . This article will cover stateful applications in Kubernetes and how StatefulSets fit in such scenario. Moreover, you'll have the chance to understand how volumes work in Kubernetes
- SQL JOIN explained
In this post we're going to see how the SQL JOIN works, guided by a practical example while covering SQL and Set theory basics. Even though you're not familiar with SQL, you can follow along as this post covers the very basics. A little disclaimer As you may already know, every time I want to
- Git fundamentals, a complete guide
If you already work with Git daily but want to have a good comprehension of Git fundamentals , then this post is for you. Here, you'll have the chance to truly understand the Git architecture and how commands such as add, checkout, reset, commit, merge, rebase, cherry-pick, pull, push and tag work
- Kubernetes 101, part III, controllers and self-healing
The second part of this series explained how Pods work while building a Pod having two containers communicating to each other using FIFO and a shared volume. In this post we'll learn about self-healing systems and what we can achieve by leveraging Pod management to Kubernetes workload resources so
- Kubernetes 101, part IV, deployments
In the third part , we went a bit further and learned how Kubernetes employs self-healing capabilities by using the controller pattern through the utilisation of workload resources such as ReplicaSets . However, it's well-known that most applications require to be updated frequently . ReplicaSets
- Kubernetes 101, part II, pods
In the previous post we've seen the fundamentals of Kubernetes as well as an introduction to its main architecture . Once we got introduced, it's time to explore how we can run an application in Kubernetes. A wrapper for containers In Kubernetes, we aren't able to create single containers directly.
- Kubernetes 101, part I, the fundamentals
It's been a while I wanted to take a time to sit down and write about Kubernetes . The time has come. In short, Kubernetes is an open-source system for automating and managing containerized applications . Kubernetes is all about containers. :exclamation: If you don't have much idea of what a
- Tekton CI/CD, the grand finale, interceptors
We learned in the previous article how to delivery applications using Tekton and the Task being part of our Pipeline. But let's think about our process a little bit: We open/update some Pull Request The Event Listener listens to the Github event The pipeline is triggered The pipeline runs 3 tasks:
- Tekton CI/CD, part IV, continuous delivery
The previous post demonstrated how to listen to Github events and trigger a pipeline based on such event. So far, the pipeline consists in: fetching the source code (from Github) building a Docker image (using dind) and running unit tests We're still missing the delivery , i.e deploying our
- CI/CD in a nutshell
CI/CD is a popular practice that many companies and projects use today. However, sometimes we use these terms mistakenly, but in this article we'll dive into the CI/CD fundamentals, understanding the problem that these practices solve as well as analysing how they fit in today's cloud architecture.
- Tekton CI, part I, a gentle introduction
In another post I talked about CI/CD in a nutshell and its fundamentals, before going further on Tekton . In case you need, I suggest you reading that post before . Now that we understand CI/CD practices, the importance of Cloud Delivery Foundation (CDF) as community and that Tekton is a graduated
- Tekton CI, part II, sharing information
In the previous post , we viewed an introduction to Tekton and a brief overview through its main components: Steps, Tasks and Pipelines . Now, let's keep exploring the Tekton building blocks as we see a complete journey from development to production . :bulb: First things first We've been using the
- Tekton CI, part III, listen to Github events
For this guide I'm assuming you are running a local Kubernetes cluster. In the previous article we've seen how to share information across a Pipeline using Workspaces , leading to a task for cloning a Github repository then ending with anoter task for listing the source files in the cloned
- Seu dinheiro não é infinito
Se você tem algum tipo de influência nas decisões arquiteturais de software no local onde trabalha, e a empresa ou instituição não tem dinheiro infinito, aqui vão 10 insights e lições aprendidas da minha parte tendo tido alguma experiência nesta indústria vital. 💰 O dinheiro não é
- Liderança começa com confiança: minha trajetória
Neste post, quero compartilhar um pouco da minha trajetória e alguns valores sobre trabalho em equipe e liderança que costumo aplicar no meu dia-dia. Há diversos estudos, livros e práticas catalogadas sobre o assunto, mas eu prefiro me apoiar em valores vindo de pessoas com as quais trabalhei e
- Thinking like containers
We can't deny how popular Docker containers became on the daily basis of many software developers around the world. Moreover, it is a mainstream technology behind cloud-native applications such as Kubernetes and it's used as the deployment engine at various production systems. However, its learning
- Simulating OOP in Bash
Everyone knows that OOP stands for "Object-oriented programming". But what is in fact OOP? Is it a Class ? Is it inheritance and polymorphism like we learned across hundreds of tutorials? Indeed, despite inheritance and polymorphism being important traits that complement OOP languages, none of them
- Building a Web server in Bash, part I - sockets
Have you ever wondered how a Web server works under the hood ? Moreover, would you be willing to sharpen your Shell scripting skills? Maybe this guide is for you. Throughout the guide we are going to build, step-by-step, a simple Web server only using bash , as we go further across fundamental
- Building a Web server in Bash, part II - parsing HTTP
In the first part of this guide, we walked through the basics of netcat command, from basic UNIX sockets to TCP sockets, all the way writing an HTML content inside the HTTP response body . Now, let's go further on writing some ShellScript, towards a more sophisticated Web server that delivers
- Building a Web server in Bash, part III - Login
In the previous posts we've seen how to manipulate sockets using netcat . Moreover, we learned how to start reading and parsing an HTTP message using ShellScript. Time to definitely improve our app . App requirements Since our application is a Web application, we should respond in a more
- Building a Web server in Bash, the grand finale
What a journey. In the previous post we experienced a refactoring in our ShellScrpit web server, adding a complete login/logout system to it. Now, let's finish this guide and enhance our web server with more HTML, styling CSS and dynamic behaviour with modern Javascript . What's CSS? CSS is a
- Inter-process communication: pipes
After learning how OS processes can use file descriptors for IPC, it's time to analyse another IPC approach: pipes. Let's recap the following example: the program sends data to the redirected STDOUT the output is used as the redirected STDIN for the program Note the pattern here: it looks like a
- Inter-process communication: files
In the previous post we learned that computers evolved to tackle concurrency , the reason why operating systems were created in order to share computer resources with running computer programs. The main concurrency unit primitive of an operating system is a process . Therefore, OS processes are
- A brief history of modern computers, multitasking and operating systems
In this article I'll try to write a brief history of modern computers, multitasking and how operating systems tackle concurrency. 40s The first modern computers in the 40's were capable of running programs built in punched cards . At that moment, computers used to load one program at a time , and
- Métricas cAdvisor no Kubernetes com Prometheus e Grafana
No último artigo vimos o funcionamento básico do Prometheus e como configurar um servidor Prometheus em um cluster Kubernetes . (lembrando que estou utilizando um cluster local com Docker Desktop for Mac ) Neste artigo, vamos explorar mais métricas para monitoramento: porcentagem de uso da CPU
- Prometheus on Kubernetes 101
Prometheus é um projeto open-source escrito em Go, criado em 2012 e utilizado para monitoramento e sistema de alerta de aplicações. Foi desenvolvido originalmente pela empresa SoundCloud, sendo mais tarde em 2016 admitido pela CNCF e graduado, depois do Kubernetes, como o segundo projeto
- Mastering the Docker networking
Few months ago I demonstrated through a practical example the reasons to understand and take advantage of Docker volumes. In this one, I'll try to do the same in regarding the Docker networking. If you want to master the Docker Networking , this post is for you. Containers live in a network Because
- Entendendo UNIX pipes
Basicamente, a todo comando UNIX é atribuído um conjunto de streams , que são canais de comunicação. Ou seja, um comando pode enviar dados para uma stream de saída (STDOUT), ler dados de uma stream de entrada (STDIN) e escrever dados em uma stream de falhas/erros (STDERR). Cada stream é
- Implementando um simples background job com UNIX named pipes
No último artigo vimos o funcionamento de UNIX streams, pipes e mais precisamente, anonymous pipes . E que estes canais são uma das bases de comunicação entre diferentes processos. Neste artigo vamos explorar "pipes nomeados", ou named pipes , e como este modelo de dados pode ajudar a entender
- Resolvendo problema de performance no PostgreSQL com CTE
Spoiler : a query ficou 23x mais rápida com CTE's apenas transformando o problema quadrático em linear. Sem índices . Um dos cenários mais comuns de problemas de performance em software é o famoso nested loop . Com o banco de dados não é diferente. Por vezes podemos acabar por escrever
- A very simple GraphQL tutorial in Ruby
According to Wikipedia GraphQL is an open-source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data. [ 2 ] GraphQL was developed internally by Facebook in 2012 before being publicly released in 2015 Unlike REST , GraphQL aims to allow query
- Mastering Docker Volumes
For those just starting with Docker, I've written some posts on how to think like containers , which I believe to be an important mindset to using Docker, as well as using Docker in development, the right way . However, if you want to move one step further on mastering Docker, it's important to
- How to reduce the time complexity of nested loops
In this post I'll demonstrate a way to understand, analyse and reduce the time complexity on algorithms, specially on nested loops . The examples will use Ruby but it can be translated to any programming language. Problem Working throughout a variety of projects, it's not rare to stumble on pieces
- A powerful full-text search in PostgreSQL in less than 20 lines
This blogpost will guide you to understand the fundamental pieces needed to implement a good enough full-text search using PostgreSQL . Spoiler alert : for those curious people looking for a "okay, just show me a full-text search with ranking and fuzzy search in Postgres in less than 20 lines", so
- A CRUD journey in Haskell, part II, Socket programming
Assuming that we've got some introduction to Haskell, let's start doing some Socket programming in order to build a simple TCP server. Requirements For the purpose of this article, I'll expect that you have some knowledge in client-server architecture, basic networking protocols and TCP/IP. You can
- A CRUD journey in Haskell, part I, introduction
In the past few days, I've been learning some Haskell after years of seeing people praising this programming language, be it about its expressiveness on writing programs or its pureness of being a "pure" functional programming language free of side-effects. Expressiveness After playing a bit with
- Using Docker in development the right way
If you are not proficient in Docker, or that topics like containers and virtual machines are still a bit "fuzzy", have problems working with Docker in development but want to learn and work using containers, this article is for you. Few weeks ago I wrote an article on Thinking like containers ,
- Web basics: sending HTML, CSS and Javascript content through HTTP
Now that we have an HTTP server sending plain text content, it's time to enhance the server so it can respond in a more appropriate content type for Web browsers. Web standards In the very beginning of Web, websites did not follow a standard, besides such constraints could take users to a bad
- Web basics: a simple HTTP Server in Ruby
In the previous article , we learned the very basics of networking and how to write a simple TCP server in Ruby. Here, we'll see a simple implementation of an HTTP server in Ruby. Dynamic response As of our example, the TCP server responds with a static message, . What if we wanted a dynamic
- Web basics: a TCP Server in Ruby
This series guide covers the very basics of Web and the building blocks of a Web server. If you have ever wondered on how a Web server works and have a basic knowledge of Ruby, this guide is for you. Essentially, the main elementary units of a web server are: Client-server architecture model TCP -
- Boilerplate for a containerized plain Ruby application
Recently I've been poking around automation in order to experiment and build software on destroyable environments, so that I won't mess up with my operating system host. That's where virtualization and containerization can help: I want to stand on a fast and destroyable environment which can be
- Quicksort, a Ruby implementation using Test-driven development
Quicksort is a sorting algorithm designed to have a reasonable time complexity . In average, most implementations of this algorithm are capable of coming to O(n log(n)) . It is implemented by many programming languages and platforms, being one of the most important algorithms for sorting. Image
- Deploy to Kubernetes using Github Actions (including Slack notification)
In this guide we'll cover the full cycle of deploying to Kubernetes using Github Actions . Batteries included: Kubernetes cluster running in AWS EKS Docker images stored in AWS ECR Bonus: notification to Slack The Github workflow will be triggered at every commit on pull request , and its steps are
- Ruby blocks made easy, part I, methods and procs
Blocks in Ruby are powerful structures that are part of our daily basis as Ruby developers. We see them being used across a variety of standard classes as well as in almost every popular gem. A few examples: The examples could go beyond. Blocks enable flexibility and extensibility . It's
- Ruby blocks made easy, part II, curry and procs as arguments
In the previous post , we learned that methods can be transformed into procs to be evaluated later . One thing worth to mention is that, the method itself can be used like a proc: every structure has a method called : Given that, the structure is good enough to be used in later evaluations . In
- Ruby blocks made easy, part III ~grand finale~, blocks and syntactic sugar
In this series of posts, we already covered that methods can be transformed into procs and as such, can be evaluated later . Furthermore, we've seen that procs can be used as arguments to another methods and that such procs can optionally use curried arguments. Until now, we have been using methods