Skip to content

Instantly share code, notes, and snippets.

@tautologicc
tautologicc / gist:ae97524b8a935e9ffa81c1f7e2fc408d
Created September 11, 2020 05:43 — forked from chanks/gist:7585810
Turning PostgreSQL into a queue serving 10,000 jobs per second

Turning PostgreSQL into a queue serving 10,000 jobs per second

RDBMS-based job queues have been criticized recently for being unable to handle heavy loads. And they deserve it, to some extent, because the queries used to safely lock a job have been pretty hairy. SELECT FOR UPDATE followed by an UPDATE works fine at first, but then you add more workers, and each is trying to SELECT FOR UPDATE the same row (and maybe throwing NOWAIT in there, then catching the errors and retrying), and things slow down.

On top of that, they have to actually update the row to mark it as locked, so the rest of your workers are sitting there waiting while one of them propagates its lock to disk (and the disks of however many servers you're replicating to). QueueClassic got some mileage out of the novel idea of randomly picking a row near the front of the queue to lock, but I can't still seem to get more than an an extra few hundred jobs per second out of it under heavy load.

So, many developers have started going straight t

1. Separation of immutable and mutable logic

Quite a lot of different people have been on the same trail of thought. Gary Bernhardt's formulation of a "functional core, imperative shell" seems to be the most voiced.

"Boundaries" - Gary Bernhardt

"Imperative shell" that wraps and uses your "functional core".. The result of this is that the shell has fewer paths, but more dependencies. The core contains no dependencies, but encapsulates the different logic paths. So we’re encapsulating dependencies on one side, and business logic on the other side. Or put another way, the way to figure out the separation is by doing as much as you can without mutation, and then encapsulating the mutation separately. Functional core — Many fast unit tests. Imperative shell — Few integration tests

https://www.youtube.com/watch?v=yTkzNHF6rMs

@tautologicc
tautologicc / presentation-tips.md
Created May 28, 2021 16:10 — forked from macintux/presentation-tips.md
Public speaking tips
@tautologicc
tautologicc / lmdb.tcl
Created April 6, 2022 14:48 — forked from antirez/lmdb.tcl
LMDB -- First version of Redis written in Tcl
# LVDB - LLOOGG Memory DB
# Copyriht (C) 2009 Salvatore Sanfilippo <antirez@gmail.com>
# All Rights Reserved
# TODO
# - cron with cleanup of timedout clients, automatic dump
# - the dump should use array startsearch to write it line by line
# and may just use gets to read element by element and load the whole state.
# - 'help','stopserver','saveandstopserver','save','load','reset','keys' commands.
# - ttl with milliseconds resolution 'ttl a 1000'. Check ttl in dump!
@tautologicc
tautologicc / x11_forwarding_macos_docker.md
Created November 7, 2022 01:00 — forked from sorny/x11_forwarding_macos_docker.md
X11 forwarding with macOS and Docker

X11 forwarding on macOS and docker

A quick guide on how to setup X11 forwarding on macOS when using docker containers requiring a DISPLAY.

This guide was tested on:

  • macOS Catalina 10.15.4
  • docker desktop 2.2.0.5 (43884) - stable release
  • XQuartz 2.7.11 (xorg-server 1.18.4)

Step-By-Step Guide

@tautologicc
tautologicc / README.md
Created December 4, 2022 21:27 — forked from lithdew/README.md
Differences between Linux and Mac for sockets.
  1. A listening socket blocked on accept() can be unblocked by calling shutdown(socket_fd, SHUT_RD) on Linux. On Mac, calling shutdown(socket_fd, SHUT_RD) on a listening socket that is blocked on accept() will return an error ENOTCONN. To unblock a listening socket blocked on accept() on Mac requires calling close(socket_fd), which will cause the blocking accept() call to return an error EBADF.

Therefore, in order to unblock a socket on accept() on both Mac/Linux, shutdown() should not be relied on. Rather, an async cancellation scheme (such as cancellation tokens in .NET) should be used instead to unblock the call to accept().

  1. When a socket is instantiated and subsequently registered to epoll, or when a socket is shut down (via. shutdown() or setsockopt(SO_LINGER)) on Linux, epoll will be notified with EPOLLHUP on the socket. On Mac, kqueue will only notify when a socket is shut down (via. shutdown() or setsockopt(SO_LINGER)) by sending a EV_EOF notification on filters EVFILT_READ, and EVFILT_WRITE.

Thi

@tautologicc
tautologicc / wb_alloc.h
Created September 22, 2023 18:43 — forked from WilliamBundy/wb_alloc.h
A single-file header allocation library for C (probably bugs out in C++, sorry)
/* This is free and unencumbered software released into the public domain. */
/* Check the bottom of this file for the remainder of the unlicense */
/* wb_alloc.h
*
* Three custom allocators that can (hopefully) safely allocate a very large
* amount of memory for you. Check the warnings below for an explanation
*
* Version 0.0.1 Testing Alpha
*/
@tautologicc
tautologicc / apihash.c
Created October 4, 2023 00:47 — forked from rad9800/apihash.c
Using macros and constexpr to make API hashing a bit more friendly
#include <Windows.h>
#include <winternl.h>
#pragma comment(linker, "/ENTRY:entry")
// Define hashing algorithm to use
#define HASHALGO HashStringDjb2
// Define how large you'd like cache to be
#define CACHE 50
@tautologicc
tautologicc / gui.md
Created October 4, 2023 15:44 — forked from vurtun/gui.md

Graphical User Interfaces

For the last few weeks I spend some time coding, writing and cleaning up my notes from almost a year since I published nuklear.

Basically this is a possible implementation for a graphical user interface builder backend with support for an immediate mode style API. So it provides a way to define non-mutating UI state, an immediate mode style API for dynamic UI components (lists,trees,...) and a combination of both.

The core implementation is ~800 LOC without any kind of default widgets or extensions. At first this seems quite counter intuitive. However since the inherent design allows for lots of different ways to define any widget like buttons it does not make sense to provide a specific default implementation. The way this code was architectured furthermore removes the need for style/skinning configurations used in Nuklear since widget painting is just calling a small

Graphical User Interfaces

Last time I wrote a little bit about my current GUI research progress. There are some things that were misunderstood so I want to clarify some fundamental design decisions and finally write up some current problems and their solutions.

First up I want to clarify a component is not another term for what is usually refered to as widget. Instead wigets in this implementation are made out of n >= 1 components. Components themself are just rectangles with attributes left, right, top, bottom, center_x, center_y, width and height some behavior flags and an optional surface to draw into. For example a scroll regions is made up out of at least three