<?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: Yash Jadhav</title>
    <description>The latest articles on DEV Community by Yash Jadhav (@yash_jadhav_cf439de0c2991).</description>
    <link>https://dev.to/yash_jadhav_cf439de0c2991</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3703080%2Fc51c4b2b-1797-4a18-94b2-eb46dbb43d90.png</url>
      <title>DEV Community: Yash Jadhav</title>
      <link>https://dev.to/yash_jadhav_cf439de0c2991</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yash_jadhav_cf439de0c2991"/>
    <language>en</language>
    <item>
      <title>Implementing Multi-Level Feedback Queue in xv6</title>
      <dc:creator>Yash Jadhav</dc:creator>
      <pubDate>Sat, 01 Aug 2026 18:30:28 +0000</pubDate>
      <link>https://dev.to/yash_jadhav_cf439de0c2991/implementing-multi-level-feedback-queue-in-xv6-3i99</link>
      <guid>https://dev.to/yash_jadhav_cf439de0c2991/implementing-multi-level-feedback-queue-in-xv6-3i99</guid>
      <description>&lt;p&gt;So I have started learning internals of Operating System through OSTEP, and the plan is going to be implement each section from OSTEP into xv6 kernel.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is xv6
&lt;/h3&gt;

&lt;p&gt;xv6 is an educational open source operating system developed by MIT for teaching concepts of operating system.&lt;/p&gt;

&lt;p&gt;Find more here: &lt;a href="https://pdos.csail.mit.edu/6.828/2012/xv6.html" rel="noopener noreferrer"&gt;https://pdos.csail.mit.edu/6.828/2012/xv6.html&lt;/a&gt;&lt;br&gt;
Github: &lt;a href="https://github.com/mit-pdos/xv6-public" rel="noopener noreferrer"&gt;https://github.com/mit-pdos/xv6-public&lt;/a&gt;&lt;br&gt;
My implementation: &lt;a href="https://github.com/lightsigma96/xv6-riscv" rel="noopener noreferrer"&gt;https://github.com/lightsigma96/xv6-riscv&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;xv6 is minimal but contains all the important components needed to create an Operating System.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding xv6 and QEMU
&lt;/h3&gt;

&lt;p&gt;QEMU is a hypervisor and machine emulator which lets you have virtual hardware emulation required by the os.&lt;/p&gt;

&lt;p&gt;As implementation of xv6 that I am using supports RISC-V assembly instructions and my CPU is x86_64, direct execution of instructions is not possible.&lt;/p&gt;

&lt;p&gt;This is where QEMU steps in, it emulates the disk, RAM, CPU, etc and runs xv6, making xv6 think that it is actually executing RISC-V instructions on RISC-V hardware whereas in reality it is actually being executed on x86_64 system.&lt;/p&gt;

&lt;p&gt;While modifying xv6 we can think that we are on actual RISC-V hardware and do not need to worry about translation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up xv6
&lt;/h3&gt;

&lt;p&gt;Setting up xv6 is straightforward, just have to use make with correct target to compile xv6 and connect via gdb to default port given.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Level Feedback Queue (MLFQ)
&lt;/h3&gt;

&lt;p&gt;Now that xv6 is set up, what is MLFQ?&lt;/p&gt;

&lt;p&gt;MLFQ is a scheduler policy which determine which process to schedule for CPU to execute depending on various factors.&lt;/p&gt;

&lt;h4&gt;
  
  
  Turnaround time:
&lt;/h4&gt;

&lt;p&gt;This is the time which specifies the time difference between the time process arrived and the time when it completed executing.&lt;/p&gt;

&lt;p&gt;So lets say three process A,B,C arrived where time take by A &amp;gt; B &amp;gt; C, in order to maximize this factor we can schedule C first as it takes least time and A at the last as it takes the most time.&lt;/p&gt;

&lt;p&gt;Now the problem here is that unless C, B finish A can't do anything so this approach increases &lt;em&gt;response time&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If the user is waiting for A's response of any kind they would have to wait for C, B to finish.&lt;/p&gt;

&lt;h4&gt;
  
  
  Response Time:
&lt;/h4&gt;

&lt;p&gt;In order to make system more interactive, we can process all process partially so that user can at least see that the process is running and is responding.&lt;/p&gt;

&lt;p&gt;We can have a time slice which is a interval after which we switch process and execute the next one.&lt;/p&gt;

&lt;p&gt;So if A takes 10s, B takes 6s, C takes 2s, and our time slice/allocated time is 1s, then we will run all 3 processes in 3s which will make user feel that all process are interactive.&lt;/p&gt;

&lt;p&gt;But one caveat over here is, if you look at time taken by each process, then C takes 2s while A takes 10s, with our time slice it would actually take 6s to finish process C whereas running it directly would have just taken 2s.&lt;/p&gt;

&lt;p&gt;This is the trade off of optimizing for response time, we lose turnaround time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SJF (Shortest Job First) optimizes for turnaround time while Round Robin uses allotment time and optimizes for response time.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  MLFQ comes into picture
&lt;/h4&gt;

&lt;p&gt;So how can we optimize for both turnaround time and response time? MLFQ can help us with it.&lt;/p&gt;

&lt;p&gt;A MLFQ consists of multiple queues which are given different priorities as seen in the figure below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdml0s7ss0iffglrhv7b7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdml0s7ss0iffglrhv7b7.png" alt="MLFQ illustration" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The idea is that all jobs will be scheduled on the top most queue, and then will gradually be demoted to lower priority if they don't finish within the given time (aka allotment time).&lt;/p&gt;

&lt;p&gt;This idea optimizes both allotment time and turnaround time, as jobs which are longer will be demoted down to lower queue so they don't block shorter jobs optimizing for turnaround time. We also give longer process some time (allotment time) which also optimizes for response time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There is a catch, jobs which issues I/O basically are considered to be done within allotment time, but this causes problem as some bad program can issue I/O frequently causing it to stay on the same priority.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  My experience while implementing MLFQ in xv6
&lt;/h2&gt;

&lt;p&gt;When first writing code for xv6 you realize that you are modifying the kernel itself, which means there is no standard library, which means you don't have functions like &lt;code&gt;malloc()&lt;/code&gt;, &lt;code&gt;printf()&lt;/code&gt;, and most of the functions you use while writing user programs.&lt;/p&gt;

&lt;p&gt;xv6 already provides implementation for &lt;code&gt;malloc()&lt;/code&gt; as &lt;code&gt;kalloc()&lt;/code&gt;, &lt;code&gt;free()&lt;/code&gt; as &lt;code&gt;kfree()&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;There is also this weird workflow that I had to get my head around, which was that I had to assume some of the events are automatically called and are not in my control like hardware traps (which entirely depends on implementation of risc-v cpu), also I studied how context switch actually happens and how data is copied into cpu registers and into memory.&lt;/p&gt;

&lt;p&gt;There is also one thing not mentioned above, which is that, periodically all jobs are boosted to top queue, this is done to avoid &lt;strong&gt;starvation&lt;/strong&gt; where if there are a lot of short jobs, longer jobs wouldn't get CPU at all. &lt;/p&gt;

&lt;p&gt;I did this promoting by calculating the difference between CPU ticks when the jobs were last promoted to top priority queue. &lt;/p&gt;

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

&lt;p&gt;This was a good lower level dive, almost at the lowest level I guess we can get just with software.&lt;/p&gt;

&lt;p&gt;This was my attempt to implement a section of OSTEP (Operating System in Three Easy Pieces) which was cpu virtualization, up next is memory virtualization.&lt;/p&gt;

&lt;p&gt;Will try to implement such more concept from OSTEP in this project.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Recall - An AI Mystery Game built with Cognee and Ollama</title>
      <dc:creator>Yash Jadhav</dc:creator>
      <pubDate>Sat, 04 Jul 2026 12:37:07 +0000</pubDate>
      <link>https://dev.to/yash_jadhav_cf439de0c2991/recall-an-ai-mystery-game-built-with-cognee-and-ollama-c7j</link>
      <guid>https://dev.to/yash_jadhav_cf439de0c2991/recall-an-ai-mystery-game-built-with-cognee-and-ollama-c7j</guid>
      <description>&lt;p&gt;Alright, so I had this idea of letting AI (not just LLM but maybe more than that) decide world generation, dialogue and actions of NPCs so that a game could feel more natural, it's like you are actually interacting with game.&lt;/p&gt;

&lt;p&gt;So...this is my first and very small attempt towards it with Cognee and Ollama.&lt;/p&gt;

&lt;p&gt;Recall is a terminal-based AI mystery game where you play as a detective investigating a murder. Your goal is to figure out the real killer by questioning suspects and piecing together their stories.&lt;/p&gt;

&lt;p&gt;Check out the code here at Github which includes how to set it up and play:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/lightsigma96" rel="noopener noreferrer"&gt;
        lightsigma96
      &lt;/a&gt; / &lt;a href="https://github.com/lightsigma96/Recall" rel="noopener noreferrer"&gt;
        Recall
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A terminal mystery game where the truth isn't written — it's remembered. Talk to NPCs with real, persistent memory and piece together who did it, with no fixed script to follow.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Recall&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;An AI-driven murder mystery terminal game where every run creates a new story, suspects, killer, and conversations.&lt;/h4&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;Players investigate by talking to NPCs. NPCs remember previous conversations, react dynamically, and provide clues based on the generated mystery.&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/6dcb33685809d565e8474a49d41ada4da6b00d14080c3a15d3ba170a158e5098/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f676e65652d48616e676f7665725f4861636b6174686f6e2d303063386666"&gt;&lt;img src="https://camo.githubusercontent.com/6dcb33685809d565e8474a49d41ada4da6b00d14080c3a15d3ba170a158e5098/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436f676e65652d48616e676f7665725f4861636b6174686f6e2d303063386666" alt="Cognee"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/8cb14691a611599932a9eb34da7871ab86ffcbd879f6cdc5f2d3b2d0aa7ff8b9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d332e31342e362d3337373641423f6c6f676f3d707974686f6e266c6f676f436f6c6f723d7768697465"&gt;&lt;img src="https://camo.githubusercontent.com/8cb14691a611599932a9eb34da7871ab86ffcbd879f6cdc5f2d3b2d0aa7ff8b9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d332e31342e362d3337373641423f6c6f676f3d707974686f6e266c6f676f436f6c6f723d7768697465" alt="Python"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/e7ed88255f745c8c6e51285d08c1f6af9cfe11a11aba044317f06a9d775f9c7c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f526963682d436f6e736f6c655f55492d626c756576696f6c6574"&gt;&lt;img src="https://camo.githubusercontent.com/e7ed88255f745c8c6e51285d08c1f6af9cfe11a11aba044317f06a9d775f9c7c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f526963682d436f6e736f6c655f55492d626c756576696f6c6574" alt="Rich"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/lightsigma96/Recall/title.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Flightsigma96%2FRecall%2FHEAD%2Ftitle.png" alt="Recall Title"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/lightsigma96/Recall/game_screen.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Flightsigma96%2FRecall%2FHEAD%2Fgame_screen.png" alt="Recall Game Screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;AI-generated murder mystery stories&lt;/li&gt;
&lt;li&gt;Dynamic NPC personalities and conversations&lt;/li&gt;
&lt;li&gt;Persistent NPC memory system&lt;/li&gt;
&lt;li&gt;Procedurally selected killer and clues&lt;/li&gt;
&lt;li&gt;Terminal-based interactive UI&lt;/li&gt;
&lt;li&gt;Local (ollama) and cloud (Gemini) LLM support&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How It Works&lt;/h2&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;A new world and murder mystery are generated.&lt;/li&gt;
&lt;li&gt;NPCs are created with unique personalities and knowledge.&lt;/li&gt;
&lt;li&gt;Players interrogate NPCs.&lt;/li&gt;
&lt;li&gt;Conversations are stored in memory.&lt;/li&gt;
&lt;li&gt;Player uses gathered information to accuse the killer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;table&gt;

&lt;thead&gt;

&lt;tr&gt;

&lt;th&gt;Game Stage&lt;/th&gt;

&lt;th&gt;Cognee Cloud API&lt;/th&gt;

&lt;th&gt;How Recall Uses It&lt;/th&gt;

&lt;/tr&gt;

&lt;/thead&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;NPC memory creation&lt;/td&gt;

&lt;td&gt;&lt;code&gt;/api/v1/remember&lt;/code&gt;&lt;/td&gt;

&lt;td&gt;Stores each NPC's personality, secrets, relationships, and crime knowledge into a dedicated memory dataset&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;Memory isolation&lt;/td&gt;

&lt;td&gt;Cognee datasets&lt;/td&gt;

&lt;td&gt;Creates a separate dataset for every NPC (&lt;code&gt;npc_name_ds&lt;/code&gt;) so suspects only know their own memories&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;…&lt;p&gt;&lt;/p&gt;&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/lightsigma96/Recall" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;br&gt;

&lt;h3&gt;
  
  
  Building Memory of NPC
&lt;/h3&gt;

&lt;p&gt;The main theme of this hackathon was memory.&lt;/p&gt;

&lt;p&gt;An LLM only answer to the question prompted and does not retain any context.&lt;/p&gt;

&lt;p&gt;For Recall every NPC has their own persistent memory powered by Cognee.&lt;/p&gt;

&lt;p&gt;Whenever you interact with NPC, using &lt;code&gt;cognee.recall()&lt;/code&gt; cognee searches through that NPC's existing memories and retrieves the most relevant information from their past interactions and initial backstory.&lt;/p&gt;

&lt;p&gt;This information is used to answer player's question, once answered &lt;code&gt;cognee.remember()&lt;/code&gt; is used to update that NPCs memory graph.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's like Cognee is the brain and LLM is the mouth.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe68oa5n74m11b7dau7bi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe68oa5n74m11b7dau7bi.png" alt="Answer generation of NPC" width="799" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every NPC has their own cognee dataset, which is created directly by  calling &lt;code&gt;cognee.remember()&lt;/code&gt; for initializing memory with some initial memory of incident, like where was the NPC when incident occurred, what were they doing and what do they know about the incident. &lt;/p&gt;

&lt;p&gt;Additionally during initialization of NPCs each one is given a unique name, personality, and work.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Whisper Feature
&lt;/h4&gt;

&lt;p&gt;This is an experimental feature where NPCs can randomly interact with each other during the game and exchange memories.&lt;/p&gt;

&lt;p&gt;The idea was to make the world feel more alive, where characters don't only react to the player but also influence each other.&lt;/p&gt;

&lt;p&gt;This also means the criminal could eventually learn what questions you have been asking other NPCs and adapt accordingly.&lt;/p&gt;

&lt;p&gt;I was able to build the core logic for this feature, but due to time constraints I couldn't properly integrate it into the game. The implementation can still be found in the codebase.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Game Setting
&lt;/h3&gt;

&lt;p&gt;I wanted the themes to lean more towards mystery and detective settings, where the environment itself contributes to the investigation.&lt;/p&gt;

&lt;p&gt;Initially I wanted to have 4 biomes/setting but again due to time constrain I was only able to add 2.&lt;/p&gt;

&lt;p&gt;The story is generated by AI, so memory of every NPC and the story will be different on every playthrough, the only thing which is fixed is the setting of the game.&lt;/p&gt;

&lt;p&gt;The 2 biomes are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Victorian England which brings classic detective experience inspired by Sherlock Holmes, includes old buildings and characters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Forest creates a more isolated and mysterious environment, surrounded by wilderness where every character has their own secrets hidden deep within the woods.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cognee Cloud
&lt;/h3&gt;

&lt;p&gt;We were provided with $35 of free cloud credits and it was really helpful.&lt;/p&gt;

&lt;p&gt;Initially, Recall was running completely locally using Cognee along with an Ollama model. While this worked, running both memory operations and model inference locally became slow and resource-intensive, especially without access to high-end compute.&lt;/p&gt;

&lt;p&gt;With cloud credits I could increase the speed of memory ingestion and recall.&lt;/p&gt;

&lt;p&gt;Also it fixed a compatibility issue that I was having with a local ollama model by providing cloud-hosted infrastructure.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Making ASCII ARTS
&lt;/h3&gt;

&lt;p&gt;Making ASCII Art seemed interesting at first but then quickly became a bottleneck as subtleties started surfacing.  &lt;/p&gt;

&lt;p&gt;I was using an image to ASCII converter so finding the right image is also an important task.&lt;/p&gt;

&lt;p&gt;So for an ASCII art to look good it needs to have a lot of characters, and fitting them within a panel with other panel like Chat panel and header panel obviously meant decreasing the character count.&lt;/p&gt;

&lt;p&gt;So I went ahead and did that, I reduced character count to 20, lowest I could go.&lt;/p&gt;

&lt;p&gt;I was able to find correct images which were more expressive and different making them still comprehensible even with just 20 characters.&lt;/p&gt;

&lt;p&gt;Well this did give a better look to the game.&lt;/p&gt;

&lt;p&gt;Also this was the bottleneck due to which I could only make 2 levels and not 4.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7an44mph2gc3lpyefklc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7an44mph2gc3lpyefklc.png" alt="ASCII Showcase" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Some ASCII Arts...they are comprehensible and there's the overflow I was talking about&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Use of AI
&lt;/h3&gt;

&lt;p&gt;Obviously, AI was also part of the development process.&lt;/p&gt;

&lt;p&gt;Most of the code was handwritten, and the overall game design, architecture, and ideas were created by me. However, I used AI tools to speed up development when I wanted to quickly experiment, debug issues, or iterate on certain parts of the project.&lt;/p&gt;

&lt;p&gt;For this project, I used ChatGPT and Claude through their websites, without any coding agents or external development harnesses, I don't have those :(&lt;/p&gt;

&lt;h3&gt;
  
  
  Ending
&lt;/h3&gt;

&lt;p&gt;Recall is nowhere close to a complete game, but it represents an idea I wanted to experiment with, making NPCs feel less scripted and more alive.&lt;/p&gt;

&lt;p&gt;Games can be much more fun when they feel more natural, interactive, and NPCs don't forget what they just said to you and how you interacted with them.&lt;/p&gt;

&lt;p&gt;This was my first attempt at exploring that idea using Cognee and LLMs, and I am excited to see how far this approach can go.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cognee</category>
      <category>cli</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>How I Built a SQL Server From Scratch</title>
      <dc:creator>Yash Jadhav</dc:creator>
      <pubDate>Sat, 16 May 2026 19:20:06 +0000</pubDate>
      <link>https://dev.to/yash_jadhav_cf439de0c2991/how-i-built-a-sql-server-from-scratch-2fm</link>
      <guid>https://dev.to/yash_jadhav_cf439de0c2991/how-i-built-a-sql-server-from-scratch-2fm</guid>
      <description>&lt;p&gt;So I wanted to learn how to use SQL databases and what better way to than to build one and learn how things works, well couldn't cover as much as planned still touched core  components and basic queries. Here is how I started.&lt;/p&gt;

&lt;h6&gt;
  
  
  Resources that I referred to
&lt;/h6&gt;

&lt;ul&gt;
&lt;li&gt;Architecture of a Database System (majorly)&lt;/li&gt;
&lt;li&gt;database-management-systems-raghu-ramakrishnan (for query planner &amp;amp;
optimization)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Source
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/lightsigma96/db_scratch" rel="noopener noreferrer"&gt;https://github.com/lightsigma96/db_scratch&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/lightsigma96" rel="noopener noreferrer"&gt;
        lightsigma96
      &lt;/a&gt; / &lt;a href="https://github.com/lightsigma96/db_scratch" rel="noopener noreferrer"&gt;
        db_scratch
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;This is a simple single-threaded database built for learning purposes.&lt;/p&gt;
&lt;p&gt;It supports basic operations such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Creating schemas&lt;/li&gt;
&lt;li&gt;Creating tables&lt;/li&gt;
&lt;li&gt;Inserting rows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Supported data types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;INT&lt;/li&gt;
&lt;li&gt;STRING&lt;/li&gt;
&lt;li&gt;FLOAT&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Build and Run (Local)&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Build the project using CMake:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;cmake -S . -B build
cmake --build build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Run the database:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;./build/db_scratch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Using Docker&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;A Dockerfile is provided to build and run the project inside a container.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Build the image&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;docker build -t db_scratch .
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Run the container (interactive)&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;docker run -it db_scratch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Inside the container:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;./build/db_scratch
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Notes&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The Docker image includes build tools and is intended for both development and debugging.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you modify the source code, rebuild the image:&lt;/p&gt;
&lt;p&gt;docker build -t db_scratch .&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;CMake&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Uses a basic CMake setup for building the project.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/lightsigma96/db_scratch" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Storage Manager
&lt;/h3&gt;

&lt;p&gt;This is the core of disk-based database, it's function is to interact with disk,&lt;br&gt;
handle various db files and manage pages.&lt;/p&gt;

&lt;h4&gt;
  
  
  Buffer Pool
&lt;/h4&gt;

&lt;p&gt;Buffer Pool caches pages from heap files in memory (which are responsible for storage of rows), pages are small fragments of heap file which are of fixed size (4kb in my case).&lt;/p&gt;

&lt;p&gt;Reading or Writing from heap file on disk can be slow, hence pages from heap&lt;br&gt;
file are loaded into memory (RAM) through buffer pool which is much faster.&lt;/p&gt;

&lt;p&gt;Now obviously we cannot load entire file into memory, as that that can lead to out of memory error.&lt;/p&gt;

&lt;p&gt;Hence we load file in pages into buffer pool which sits in memory.&lt;/p&gt;

&lt;p&gt;Buffer Pool has a page replacement policy which evicts certain pages when buffer&lt;br&gt;
pool is full.&lt;/p&gt;

&lt;p&gt;In my case I implemented a simple FIFO replacement policy which tracks pages in&lt;br&gt;
order of insertion into buffer pool, which checks if the page is &lt;em&gt;pinned (pages which are frequently used or are being used by some component are pinned, pin count shows how many components are using that page)&lt;/em&gt;, if yes then send them back in the queue, if no then flush them (write to disk) and evict them.&lt;/p&gt;

&lt;p&gt;Buffer pools also contains a Disk Operator responsible for writing to file and&lt;br&gt;
other things (implementations can vary).&lt;/p&gt;

&lt;h3&gt;
  
  
  Access Methods
&lt;/h3&gt;

&lt;p&gt;Access Methods provides with necessary data structure and algorithms to organize&lt;br&gt;
and access data.&lt;/p&gt;

&lt;p&gt;On heap file rows are stored one after another and &lt;em&gt;heap scan&lt;/em&gt; from access methods scan each one of them to find correct row based on given SARG.&lt;/p&gt;

&lt;p&gt;SARGs (Search Arguments) describes condition for finding a row, they contain&lt;br&gt;
column, operator and constant.&lt;/p&gt;

&lt;p&gt;Heap scan may require scanning all rows across multiple pages resulting in O(n)&lt;br&gt;
search complexity, hence a &lt;em&gt;index scan&lt;/em&gt; can be implemented using B+ Trees.&lt;/p&gt;

&lt;p&gt;B+ Tree consists of leaf nodes and internal nodes, Leaf nodes store key and RID (Row Identifier) which points to the exact row in heap file, &lt;/p&gt;

&lt;p&gt;B+ Tree reduces index traversal cost from scanning many pages to traversing a small number of pages proportional to tree height, after which corresponding heap pages can be accessed using RID.&lt;/p&gt;

&lt;p&gt;The downside of index scan is that index keys are built on specific columns.If query predicates do not use indexed columns then planner may fallback to heap scan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query Planner and Optimizer
&lt;/h3&gt;

&lt;p&gt;After Buffer Pool and Access Methods, rows can be stored on disk and retrieved,&lt;br&gt;
next comes the query planner &amp;amp; optimizer which makes plan for execution of query&lt;br&gt;
and optimizes that plan.&lt;/p&gt;

&lt;h4&gt;
  
  
  Lexer &amp;amp; Parser
&lt;/h4&gt;

&lt;p&gt;Queries are tokenized into keywords, identifiers, literals and special symbols&lt;br&gt;
which are then passed to parser.&lt;/p&gt;

&lt;p&gt;Parser is responsible for checking grammar and construct AST based on tokens&lt;br&gt;
passed.&lt;/p&gt;

&lt;p&gt;Parser's implementation can vary, in my case Lexer provides a tokenizer which is&lt;br&gt;
used to iterate token forward/backward, and peek tokens.&lt;/p&gt;

&lt;p&gt;Parser uses these token to check grammar of different queries.&lt;/p&gt;

&lt;p&gt;Once this has been done Parser produces an AST specific to each query.&lt;/p&gt;

&lt;h4&gt;
  
  
  Planner and Optimizer
&lt;/h4&gt;

&lt;p&gt;The AST produced by Parser is consumed by Planner which has a plan defined for&lt;br&gt;
each query.&lt;/p&gt;

&lt;p&gt;For example plan for select query involves three steps (from top to bottom):&lt;br&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Projection : Selects specific columns from tuples returned by child operators.&lt;br&gt;&lt;br&gt;
Filter : Based on SARG matching, this steps filters out rows returned by heap scan.&lt;br&gt;&lt;br&gt;
Scan : This calls heap scan and returns the output above in the chain.&lt;br&gt;&lt;br&gt;
(Rows flow upward from Scan → Filter → Projection)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each operator pulls one tuple at a time from its child operator.&lt;/p&gt;

&lt;p&gt;Optimization depends on type of query, for example if a index for columns exists then index scan can be used instead of heap scan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Catalog Manager
&lt;/h3&gt;

&lt;p&gt;Catalog Manager is logically separate from query execution components and is&lt;br&gt;
responsible for schema metadata management.&lt;/p&gt;

&lt;p&gt;This is used to enforce schema and handle  writing and reading to/from a schema file.&lt;/p&gt;

&lt;p&gt;To write schema to a file a serializer has to be made which writes schema in&lt;br&gt;
format:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schema name size&lt;/li&gt;
&lt;li&gt;Schema name&lt;/li&gt;
&lt;li&gt;- heap page offset&lt;/li&gt;
&lt;li&gt;- heap page id&lt;/li&gt;
&lt;li&gt;- Table name size &lt;/li&gt;
&lt;li&gt;- Table name &lt;/li&gt;
&lt;li&gt;- - Column size&lt;/li&gt;
&lt;li&gt;- - Column name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only caveat here is, before every name I had to store it's size as I have used C++ string over here which stores pointer to actual string allocated in memory, so if I directly write it on file, I would be writing garbage memory address.&lt;/p&gt;

&lt;p&gt;Deserializer reads this back from file. &lt;/p&gt;

&lt;h3&gt;
  
  
  Main Server
&lt;/h3&gt;

&lt;p&gt;This initializes all the necessary objects like buffer manager, access methods,&lt;br&gt;
query planner, catalog manager.&lt;/p&gt;

&lt;p&gt;I have two pipelines, DB Pipeline, TUI Pipeline, initially I wanted to have a&lt;br&gt;
client-server architecture with a tcp server requesting DB but instead I thought&lt;br&gt;
of going with direct function calls.&lt;/p&gt;

&lt;h4&gt;
  
  
  DB Pipeline
&lt;/h4&gt;

&lt;p&gt;This function is responsible for orchestration of database pipeline (A TCP server can also be created which would be responsible for preprocessing cli input and calling db). &lt;/p&gt;

&lt;p&gt;First the input query is tokenized and checked for correctness by lexer and parser. &lt;/p&gt;

&lt;p&gt;If query is valid then AST is generated which is then goes through their respective processing (like for SELECT query it is passed through select plan and create table is passed through create table provided by catalog manager). &lt;/p&gt;

&lt;p&gt;A response is finally returned by this function, implementation for this pipeline can be different.&lt;/p&gt;

&lt;p&gt;With all the things above a database can support basic things like creating schema,table,columns executing basic queries like SELECT, INSERT, DELETE (same architecture can be extended to support JOINS and Stored Procedure).&lt;/p&gt;

&lt;p&gt;Some other core components included: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WAL (Write Ahead Log): Ensures durability and crash recovery by logging changes before modified pages are written to disk. Follows ACID properties.&lt;/li&gt;
&lt;li&gt;Lock Manager: Used to gain locks for multi-threading.&lt;/li&gt;
&lt;/ul&gt;

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