29 May 2026
Planet Debian
Ravi Dwivedi: Budapest Travel
In September 2025, I attended the annual LibreOffice conference in Budapest, Hungary. This gave me an opportunity to explore the city, which I will cover in this post.
Let's start with the currency. Although Hungary is a part of the European Union (EU), it doesn't use the euro as its currency. Instead, it uses Hungarian forints (denoted by "Ft"). During my time in Hungary, 1 Indian rupee was equal to 4 Hungarian forints.
After reaching the Budapest airport, I bought a 15-day public transport pass. The public transport counter is after you pass customs and immigration. The pass allows unlimited use of public transport in the city. I had to show my passport and pay 5950 Ft to get the pass. The pass had my passport number mentioned on it. The public transport passes can also be bought at any of the tram stations as well.
This is the counter from where I bought my public transport pass.
My unlimited public transport pass for Budapest. I have redacted my passport number from it.
An automatic ticket machine at a tram station in Budapest.
Budapest is a union of two cities-Buda and Pest-lying on opposite sides of the Danube River. My hotel-Corvin Hotel-was on the Pest side.
Budapest had good public transport. The buses, metros, and trams complemented each other. For example, the airport didn't have metro or tram connectivity, but it was served by the bus. Most of the metro was on the Pest side, with only a couple of stations falling in Buda. However, both sides had an extensive network of trams.
Furthermore, the information about the public transport was easily accessible. For instance, the map of tram stops inside the trams also included the bus routes one could get after alighting at those stops.
From the airport, I took a bus followed by taking a metro on the M3 line to reach within walking distance of my hotel.
An M3 line metro in Budapest.
During the conference I would take the tram to the conference venue. The trams were modern and fast. They also had a smiley face at the front, which gave them a friendly look. It seemed like the trams were happily doing their job. The city also had a good pedestrian infrastructure along with separate cycling tracks.
A tram in Budapest having a smiley face at the front.
In the bathroom of my hotel room, there was a poster mentioning that the tap water was safe to drink.
On the 6th of September, I went on a sightseeing tour of Budapest with Dione. Our friend Attila, who was a local (from Hungary), joined us. We went to the central market from our hotel to the metro.
If you read my post on Vienna, I mentioned how the metros there don't have AFC gates but ticket validators instead. Budapest's metro also has the same system. If you buy individual tickets, you need to validate them using the validators on the station before boarding the metro. If you are using a public transport pass like I was, then you do not need to validate, and you can board the metro directly.
A ticket validator at a metro station in Budapest.
Attila showed us around. I bought a fridge magnet and paprika powder. I wanted a spicy one, but I didn't get that. Instead, I got the sweet version. It doesn't taste sweet, and it is mainly used for food coloring at home. I like the paprika powder and use it frequently in my omelets and other dishes.
Central market.
The building right behind the tram is the central market building.
At 12 noon, he had to join the The Document Foundation (TDF) sightseeing group, so we parted ways. The Hungarian parliament building is a tourist attraction. We were on the Pest side of Budapest, and the parliament was also on the Pest side, while other tourist attractions were on the Buda side.
So, Dione and I hopped on a tram and went to the parliament. There is a tram station just outside where we got off. The parliament is the icon of Budapest. One can buy tickets and go inside. However, we didn't have a lot of time, so we clicked pictures outside.
Hungarian Parliament building.
After spending some time there, we took a tram to the Chain Bridge. As I mentioned earlier, Budapest has two parts-Buda and Pest-separated by the Danube River. To go from one of the sides to the other requires crossing a bridge. Although Budapest has many bridges linking the two sides, the main one is the Chain Bridge.
We walked on the chain bridge to get to the other side. The bridge gave a good view of the Danube River. It also had a statue of a lion. We could see Buda Castle from the bridge.
A shot of Chain Bridge.
The lion statue on the Chain Bridge.
After reaching the other side of the bridge (the Buda side), we sat on a bench for some time and then planned on where to go next. We decided to go to Fisherman's Bastion, which is another tourist attraction.
We used the OSMAnd~ app to figure out which bus to take and hopped on one. Soon we reached Fisherman's Bastion, where we found a flight of stairs that led upwards. Upon climbing the stairs, we got a panoramic view of the city. It also gave us a good view of the Hungarian parliament across the river. Going further upstairs, we found a statue of Stephen I of Hungary. He was the first king of Hungary, which he became in the year 1000.
A view of Hungarian parliament from Fisherman's bastion.
I found Fisherman's Bastion to be the best tourist attraction in the city. As mentioned earlier, it offers a panoramic view of the city, which I liked, and it is also beautiful. If you find yourself in Budapest, I would highly recommend that you visit it.
Fisherman's Bastion.
Statue of Stephen I of Hungary at Fisherman's Bastion.
Next, we went downstairs and returned to where the bus dropped us. From here on, we walked in random streets to see the residential and non-touristy side of Budapest. It was not so random as we walked towards Batthyány tér metro station. Upon reaching the metro station, we found a café where we had coffee.
Batthyány tér metro station.
For lunch, we decided to go to Rákóczi tér metro station after reading on the internet about the food options there. Upon exiting the metro station, we found a market inside a building that had a lot of shops, but most of them were closed.
After roaming around inside a bit, we found an Italian place open and decided to eat there. The name of this place was Matteos. We ordered an eggplant parmigiana, a lasagna artichoke, and a classic tiramisu. It wasn't very tasty but filled us up for the day.
A picture of Matteos, where we had our lunch.
Budapest has four metro lines, and we had been to three of them, so we decided to try the remaining line, which was the M1 line. It is the oldest line in the city and has a different vibe than the modern lines. This line was opened in 1896, one of the oldest subway systems in the world.
We took the M1 line and got down at the last stop, Mexikói út. The coaches were much smaller than the other metro lines, and the seating was pretty different too. Upon going outside, we found out there wasn't much to do here. At this point, I checked the map and realized that Heroes' Square is just a couple of metro stations away. Heroes' Square is a tourist attraction in Budapest. It is a historically significant place in Budapest.
M1 line station and tracks. It is the oldest metro transit of Budapest and one of the oldest in the world. It started operations in 1896.
Here, our unlimited public transport pass was handy because if it was paid per trip, we would think of the stop as a "wasted" one because we would have to buy a ticket again, but in this case we could just hop on again without any regrets.
An M1 line metro train entering the station.
So we took the M1 line again and deboarded at Hősök tere station, followed by walking to the square. After roaming around for a while, we saw a trolleybus and decided to ride on that.
Heroes' Square.
This is the trolleybus we took in Budapest.
A trolleybus is an electric bus that is powered by overhead electric cables. It is like a tram but runs on roads instead of tracks. We got down at Dózsa György út metro station. Then we took a metro to our hotel.
Before going to the hotel, we went to a place to eat something. We had coffee and lángos. Lángos is a deep-fried Hungarian dish, which looks exactly like the Indian flatbread bhatura. I found it tasty, but since it was deep-fried, that was almost a given.
Lángos - adish which looks like Indian flatbread bhatura.
The next day we went to Vienna-the capital of Austria-which I have already posted about. Check it out here.
I had a good time in Budapest, and it is a beautiful city with good public transport and some amazing sites to visit. That's it for now, and see you next time!
Credits: Thanks Dione and Badri for proofreading.
29 May 2026 2:26pm GMT
Russell Coker: Zswap
Zswap vs Zram
Last year I blogged about using Zram for VMs [1]. That setup is still working well for VMs and for phones and laptops with no swap device.
I have just read Chris Down's insightful blog post about Zswap vs Zram [2] which convinced me to setup Zswap on some systems. I have had some of the problems that were described in his blog post when trying to run Zram on workstation and server systems.
One limitation of zswap is that it doesn't allow specifying the compression level. For zram I can put the following in /etc/systemd/zram-generator.conf to set the zstd compression level (this works well on my Thinkpad X1 Carbon Gen6):
[zram0] compression-algorithm=zstd(level=10)
For the BTRFS filesystem I can put "compress=zstd:13" in the mount options to specify the compression level. They really should support different compression levels in zswap. The ideal compression level depends on the speed of the CPU and new CPUs keep getting faster.
Setup
The documentation says to use something like the following on the kernel command-line to enable zswap:
zswap.enabled=1 zswap.compressor=zstd zswap.max_pool_percent=20 zswap.shrinker_enabled=1
The max_pool_percent=20 setting is the default which means to use up to 20% of system RAM for compressed data. I've seen documentation sugesting up to 50% which seems a little excessive.
Note that a lot of documentation says to use zswap.zpool=z3fold, but z3fold is going to be removed and zsmalloc (the default) is recommended [3].
There is documentation about changing the compression algorithm via command line parameters, on Debian only lzo is linked in to the kernel and zstd (my preferred option) is a module so the kernel command line can't be used to set zstd, but the following command works:
echo zstd > /sys/module/zswap/parameters/compressor
The shrinker_enabled option is to allow the kernel to evict cold pages without waiting for memory pressure.
You can enable zswap without rebooting by running commands like the following. You could even put them in /etc/rc.local or something, but I think putting it in the kernel command line is a good idea as it makes it obvious to the next sysadmin what is happening.
echo 1 > /sys/module/zswap/parameters/enabled echo zstd > /sys/module/zswap/parameters/compressor echo 1 > /sys/module/zswap/parameters/shrinker_enabled
Monitoring
The following command is documented as a way of finding out what zswap is doing:
# grep -r . /sys/kernel/debug/zswap/ /sys/kernel/debug/zswap/stored_pages:262541 /sys/kernel/debug/zswap/pool_total_size:455266304 /sys/kernel/debug/zswap/written_back_pages:384 /sys/kernel/debug/zswap/reject_compress_poor:0 /sys/kernel/debug/zswap/reject_compress_fail:160911 /sys/kernel/debug/zswap/reject_kmemcache_fail:0 /sys/kernel/debug/zswap/reject_alloc_fail:0 /sys/kernel/debug/zswap/reject_reclaim_fail:0 /sys/kernel/debug/zswap/pool_limit_hit:0
The following command gives the zswap compression level which gives a result of 2.36 for this example:
echo "scale=2; " $(</sys/kernel/debug/zswap/stored_pages) " * $(getconf PAGESIZE) /" $(</sys/kernel/debug/zswap/pool_total_size) | bc
This table documents my current understanding of the debug values. The difference between reject_compress_fail and reject_compress_poor isn't clear in a lot of the documentation, even reading the source didn't make it easy to understand.
| File | Meaning (LC is lifetime count) |
|---|---|
| pool_limit_hit | LC pool limit hit and pages are forced to the swap partition |
| pool_total_size | RAM used for zswap data |
| reject_alloc_fail | LC can't allocate memory because max_pool_percent has been reached |
| reject_compress_fail | LC of pages with a compression algorithm failure so go straight to swap partition |
| reject_compress_poor | LC of pages that can't compress so go straight to swap partition |
| reject_kmemcache_fail | LC kernel malloc failure (serious problem?) |
| reject_reclaim_fail | LC failure to move a page from compressed RAM to disk - serious problem! |
| stored_pages | Swapped pages stored by zswap |
| written_back_pages | LC of pages written back to swap partition from zswap |
All of this is not nearly as easy to understand as the following command for zram:
# zramctl NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT /dev/zram0 zstd 7.7G 2.1G 375M 386M 4 [SWAP]
Debian Wiki
The Debian Wiki page about Zswap is very brief [4] and needs more description about this, I think a lot of Debian users will use zram instead of zswap because setting up zram is just a single apt command. I'm not planning to immediately add to that wiki page because I'm not an expert on this, I would appreciate comments on this blog post from others who have got zswap working. I will update the wiki if others report matching experiences to mine.
Conclusion
I'm now using zswap on a few systems including my main home workstation which had performed poorly with zram and a swap device in the past. If that goes well I'll put it on other systems.
I wrote the following shell script to display zswap stats, consider it GPL if you want to use it:
#!/bin/bash if [ ! -f /sys/kernel/debug/zswap/stored_pages ]; then echo "ZSwap not enabled" exit 0 fi PAGES=$(</sys/kernel/debug/zswap/stored_pages) PAGESIZE=$(getconf PAGESIZE) RAM=$(echo "$PAGESIZE * " $(getconf _PHYS_PAGES) | bc) POOL=$(</sys/kernel/debug/zswap/pool_total_size) if [ "$POOL" == "0" ]; then echo "ZSwap not used yet" exit 0 fi COMP=$(</sys/module/zswap/parameters/compressor) echo -n "$COMP compression ratio: " echo "scale=2; $PAGES * $PAGESIZE / $POOL" | bc echo -n "RAM%: " echo "100 * $POOL / $RAM" | bc
- [1] https://etbe.coker.com.au/2025/08/27/zram-vms/
- [2] https://tinyurl.com/2bhknn7e
- [3] https://tinyurl.com/2bxvj3pq
- [4] https://wiki.debian.org/Zswap
29 May 2026 11:59am GMT
28 May 2026
Planet Debian
Jonathan Dowland: nvim-µwiki

In January 2025, as a pre-requisite for something else, I published a minimal neovim plugin called nvim-µwiki. It's essentially just the features from vimwiki that I regularly use, which is a small fraction them. I forgot to blog about it. I recently dusted it off and cleaned it up. You can find it here, along with a longer list of its features and how to configure it: https://github.com/jmtd/nvim-microwiki
I had a couple of design goals. I didn't want to define a new filetype, so this is designed to work with the existing markdown one. I'm using neovim, so I wanted to leverage some of its features: this plugin is written in Lua, rather than vimscript. I use the parse trees provided by TreeSitter to navigate the structure of a document. I also decided to "plug into" the existing tag stack navigation, rather than define another dimension of navigation (along with buffers, etc.) to track: Following a wiki-link pushes onto the tag stack, just as if you followed a tag.
This was my first serious bit of Lua programming, as well as my first dive into neovim (or even vim) internals. Lua is quite reasonable. Most of the vim and neovim architecture is reasonable. The emerging conventions about structuring neovim plugins are mostly reasonable. TreeSitter is, well, interesting, but the devil is very much in the details. Somehow all together the experience for me was largely just frustrating, and I didn't really enjoy writing it.
28 May 2026 8:48am GMT