<?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>Forem: Albert Zeyer</title>
    <description>The latest articles on Forem by Albert Zeyer (@albertzeyer).</description>
    <link>https://forem.com/albertzeyer</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F562392%2F16ff7223-4c47-4351-bc16-ee6e03ce31ea.png</url>
      <title>Forem: Albert Zeyer</title>
      <link>https://forem.com/albertzeyer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/albertzeyer"/>
    <language>en</language>
    <item>
      <title>OpenVPN userspace with tunsocks (without TUN devices)</title>
      <dc:creator>Albert Zeyer</dc:creator>
      <pubDate>Mon, 03 Nov 2025 23:10:31 +0000</pubDate>
      <link>https://forem.com/albertzeyer/openvpn-userspace-with-tunsocks-without-tun-devices-1d7o</link>
      <guid>https://forem.com/albertzeyer/openvpn-userspace-with-tunsocks-without-tun-devices-1d7o</guid>
      <description>&lt;p&gt;I want to connect to an OpenVPN server, from a Linux client where I don't have root access and cannot (and want not) create a TUN device. I don't really need the TUN device: I just want to connect to a SSH server within the VPN.&lt;/p&gt;

&lt;p&gt;This is possible. But it needs a patched openvpn. Specifically &lt;a href="https://github.com/bendlas/openvpn-tuna" rel="noopener noreferrer"&gt;bendlas/openvpn-tuna&lt;/a&gt; or &lt;a href="https://github.com/ValdikSS/openvpn-tunpipe" rel="noopener noreferrer"&gt;ValdikSS/openvpn-tunpipe&lt;/a&gt;. That adds the possibility to use &lt;code&gt;--dev "|&amp;lt;pipetool&amp;gt;"&lt;/code&gt; for &lt;code&gt;openvpn&lt;/code&gt;. So instead of using a TUN device, it would run some command and pipe all the data to it. Then, there is &lt;a href="https://github.com/russdill/tunsocks/" rel="noopener noreferrer"&gt;russdill/tunsocks&lt;/a&gt; which you can use as the program here. For example, &lt;code&gt;tunsocks -L [bind_address:]bind_port:host_address:host_port&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It took me a while to get this working:&lt;/p&gt;

&lt;p&gt;I first tried with bendlas/openvpn-tuna. The README suggested to use Nix. So I tried with Nix. Running &lt;code&gt;nix&lt;/code&gt; directly was not really working well as non-root (I did not knew about the custom &lt;code&gt;--store&lt;/code&gt;), so I tried it within Docker/Apptainer/Singularity. I first tried with &lt;code&gt;--fakeroot&lt;/code&gt;, which also does not work well with &lt;code&gt;nix&lt;/code&gt;. But without &lt;code&gt;--fakeroot&lt;/code&gt;, it worked. But then, the suggested commands did not really work. E.g. I tried &lt;code&gt;nix run github:bendlas/openvpn-tuna#tunsocks -- config.ovpn&lt;/code&gt;. That asked the for login, but ended up in an endless loop of &lt;code&gt;Connection reset, restarting [0]&lt;/code&gt;, &lt;code&gt;SIGUSR1[soft,connection-reset] received, process restarting&lt;/code&gt;, &lt;code&gt;Restart pause, 1 second(s)&lt;/code&gt;. I also tried the other commands but nothing really worked.&lt;/p&gt;

&lt;p&gt;Then I also compiled bendlas/openvpn-tuna directly without Apptainer and Nix, by just using autoreconf, configure and make, and could also run it. But I got just the same behavior.&lt;/p&gt;

&lt;p&gt;Btw, Gemini was not helpful at all for this generic task to use OpenVPN in user-space without a TUN device, just for some port forwarding. It basically said it is not possible. It also misunderstood the purpose of openvpn-tuna, openvpn-tunpipe, tunsocks, etc. It also misunderstood the instructions from the openvpn-tuna README. It also misunderstood any of the OpenVPN errors.&lt;/p&gt;

&lt;p&gt;However, Gemini was quite helpful in debugging random Apptainer and Nix issues (e.g. the problem with &lt;code&gt;--fakeroot&lt;/code&gt;, which was quite involved and non-trivial to figure out). It mostly understood the issues, or at least gave me very useful hints on where to look next.&lt;/p&gt;

&lt;p&gt;Then I tried the slightly older ValdikSS/openvpn-tunpipe. Now without Nix. I again did autoreconf, configure and make, and could also run it. I first tried &lt;code&gt;./src/openvpn/openvpn config.ovpn&lt;/code&gt;. And that worked, up to &lt;code&gt;ERROR: Cannot ioctl TUNSETIFF tun: Operation not permitted (errno=1)&lt;/code&gt;, which was expected. So then I wanted to try the &lt;code&gt;--dev "|tunsocks -L ..."&lt;/code&gt;. For that, I also needed to clone russdill/tunsocks and build that, which was fairly straightforward. And then it just worked!&lt;/p&gt;

&lt;p&gt;The final command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./src/openvpn/openvpn &lt;span class="nt"&gt;--config&lt;/span&gt; config.ovpn &lt;span class="nt"&gt;--script-security&lt;/span&gt; 2 &lt;span class="nt"&gt;--dev&lt;/span&gt; &lt;span class="s2"&gt;"|../tunsocks/tunsocks -L 2222:&amp;lt;sshhost&amp;gt;:22"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note, alternatively, you could also make a SOCKS proxy, or use other things from tunsocks.&lt;/p&gt;

&lt;p&gt;Note, for WireGuard, there seem to exist easier-to-use solutions for the same functionality. There is &lt;a href="https://github.com/whyvl/wireproxy" rel="noopener noreferrer"&gt;whyvl/wireproxy&lt;/a&gt;. There is &lt;a href="https://github.com/aramperes/onetun" rel="noopener noreferrer"&gt;aramperes/onetun&lt;/a&gt;. There is &lt;a href="https://github.com/noisysockets/noisysockets" rel="noopener noreferrer"&gt;noisysockets/noisysockets&lt;/a&gt;. There is &lt;a href="https://github.com/cloudflare/boringtun" rel="noopener noreferrer"&gt;cloudflare/boringtun&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>openvpn</category>
      <category>vpn</category>
    </item>
    <item>
      <title>Why game development is a great learning playgroung</title>
      <dc:creator>Albert Zeyer</dc:creator>
      <pubDate>Wed, 25 Jun 2025 21:01:50 +0000</pubDate>
      <link>https://forem.com/albertzeyer/why-game-development-is-a-great-learning-playgroung-46k9</link>
      <guid>https://forem.com/albertzeyer/why-game-development-is-a-great-learning-playgroung-46k9</guid>
      <description>&lt;p&gt;(This is copy of the article from &lt;a href="https://github.com/albertz/wiki/blob/master/coding-learning-games-why.md" rel="noopener noreferrer"&gt;here&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Game development is a great way to learn coding and computer science in general. You can learn a lot by game development. And not only about coding itself, but also about advanced algorithms of various sorts and much more. If you compare it to the learning value of working on any tool or whatever other application, in most cases you will learn more by developing a game because games include a very wide area of technics while most other applications are mostly very limited in the amount of theories and techniques involved.&lt;/p&gt;

&lt;h1&gt;
  
  
  Related resources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/albertz/Coding-Game-Intro" rel="noopener noreferrer"&gt;Coding Game Intro&lt;/a&gt;. Coding Introduction / Tutorial, mostly by writing small little fun games.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/albertz/wiki/blob/master/coding.md" rel="noopener noreferrer"&gt;On Coding&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/albertz/wiki/blob/master/debugging.md" rel="noopener noreferrer"&gt;On Debugging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/albertz/wiki/blob/master/profiling.md" rel="noopener noreferrer"&gt;On Profiling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/albertz/wiki/blob/master/coding-for-kids.md" rel="noopener noreferrer"&gt;Coding for kids&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.quora.com/Is-game-development-a-good-way-to-learn-a-programming-language" rel="noopener noreferrer"&gt;Quora: Is game development a good way to learn a programming language?&lt;/a&gt; (yes...)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@kshitijdhar12/why-video-game-programming-is-awesome-and-how-to-become-a-game-programmer-12a1cf8ebe79" rel="noopener noreferrer"&gt;Kshitij Dhar: Why Video Game Programming Is Awesome (And How to Get Started with Creating Your First Game)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/albertz/music-player/blob/master/WhatIsAMusicPlayer.md" rel="noopener noreferrer"&gt;What is a music player?&lt;/a&gt;.
In a similar manner, this article shows that a music player also covers various different aspects.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blog.jsbarretto.com/post/software-is-joy" rel="noopener noreferrer"&gt;Joshua Barretto: Writing Toy Software Is A Joy&lt;/a&gt;.
List of toy programs rated by difficulty and time required.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Programming languages
&lt;/h1&gt;

&lt;p&gt;Of course the most basic part is the coding itself.&lt;br&gt;
That includes the &lt;a href="https://en.wikipedia.org/wiki/Programming_language" rel="noopener noreferrer"&gt;programming language&lt;/a&gt; and getting used to it. Learning a programming language is not only learning the syntax and semantics - it is also about how you do it right.&lt;/p&gt;

&lt;p&gt;In a medium/big sized game (and often even in small), there are often a bunch of different languages used together.&lt;/p&gt;

&lt;p&gt;For example, in the &lt;a href="http://github.com/albertz/openlierox" rel="noopener noreferrer"&gt;OpenLieroX project&lt;/a&gt;, you will find applications of at least these languages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/C++" rel="noopener noreferrer"&gt;C++&lt;/a&gt;. Most of the game and its core is written with it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/C_(programming_language)" rel="noopener noreferrer"&gt;C&lt;/a&gt;. Some rare parts of the game are C code.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Assembly_language" rel="noopener noreferrer"&gt;Assembler&lt;/a&gt;. Some performance critical parts of the game are written in Asm.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Lua" rel="noopener noreferrer"&gt;Lua&lt;/a&gt;. We use Lua for ingame scripting.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Python_(programming_language)" rel="noopener noreferrer"&gt;Python&lt;/a&gt;. The dedicated script and a few other scripts use Python.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Bash_(Unix_shell)" rel="noopener noreferrer"&gt;Bash&lt;/a&gt; / &lt;a href="https://en.wikipedia.org/wiki/Z_shell" rel="noopener noreferrer"&gt;Zsh&lt;/a&gt;. Many scripts to do some management (like preparing release packages and distributing them) are using either Bash or Zsh.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/CMake" rel="noopener noreferrer"&gt;CMake&lt;/a&gt;. Our build system uses it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/PHP" rel="noopener noreferrer"&gt;PHP&lt;/a&gt;. Our homepage uses it and also the reference implementation of the HTTP masterserver.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But when you are just starting with coding,&lt;br&gt;
for a simpler game project, any single language is enough.&lt;/p&gt;

&lt;p&gt;The programming language doesn't really matter that much for learning. Don't be scared about C++. It isn't really that complicated. Or maybe Rust, or Nim, or some of the other newer native languages. Python is of course also a very good starting language.&lt;/p&gt;

&lt;h1&gt;
  
  
  Libraries
&lt;/h1&gt;

&lt;p&gt;Knowing programming languages is not enough.&lt;br&gt;
Most languages also come with their own standard library but in many cases, you also need some external libraries or frameworks.&lt;/p&gt;

&lt;p&gt;Here a list of libraries that the OpenLieroX core uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/C_standard_library" rel="noopener noreferrer"&gt;C standard library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/C%2B%2B_Standard_Library" rel="noopener noreferrer"&gt;C++ standard library&lt;/a&gt; (STL)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Boost_%28C%2B%2B_libraries%29" rel="noopener noreferrer"&gt;Boost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Simple_DirectMedia_Layer" rel="noopener noreferrer"&gt;SDL&lt;/a&gt;. This is for initialising the window/screen, doing graphics operations and handling user input.&lt;/li&gt;
&lt;li&gt;SDL_image. For some more image formats.&lt;/li&gt;
&lt;li&gt;GD. Another lib for various image formats and image handlings.&lt;/li&gt;
&lt;li&gt;HawkNL. For networking (TCP/UDP).&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Zlib" rel="noopener noreferrer"&gt;zlib&lt;/a&gt;. Compression.&lt;/li&gt;
&lt;li&gt;libzip. ZIP support.&lt;/li&gt;
&lt;li&gt;libxml2. XML support.&lt;/li&gt;
&lt;li&gt;libcurl. HTTP support.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/OpenAL" rel="noopener noreferrer"&gt;OpenAL&lt;/a&gt;. For sound.&lt;/li&gt;
&lt;li&gt;ALUT. For initialising the OpenAL environment and WAV support.&lt;/li&gt;
&lt;li&gt;libvorbis/libogg. For Vorbis OGG support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the other languages, mostly only the standard library is used. (&lt;a href="https://docs.python.org/3/tutorial/stdlib.html" rel="noopener noreferrer"&gt;Python has a "batteries included" philosophy&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Also see &lt;a href="https://github.com/albertz/Coding-Game-Intro?tab=readme-ov-file#useful-libraries" rel="noopener noreferrer"&gt;this list about useful game libraries&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Cross platform
&lt;/h1&gt;

&lt;p&gt;If you don't want to restrict yourself to only one platform (like Linux or MacOSX or even Windows), you need to write your code in a way that it is mostly cross platform.&lt;/p&gt;

&lt;p&gt;One important point is that the dependencies and libraries you are using are all also cross platform, i.e. available for most or all platforms. If you take a look at the list of libraries from above, you will find that this is mostly the case.&lt;/p&gt;

&lt;p&gt;In practice, this is not all. You will face problems that some things will just behave and work different depending on the platform. Also the platforms themself are by purpose somewhat different and handle things differently. So you will still end up in having different solutions and code paths in these cases for different platforms.&lt;/p&gt;

&lt;p&gt;By working on a cross platform game like OpenLieroX, you will learn how to deal with this. When you use the right libraries,&lt;br&gt;
this is not that much of a problem.&lt;/p&gt;

&lt;h1&gt;
  
  
  Architecture independence
&lt;/h1&gt;

&lt;p&gt;This is somewhat related to cross platform. If you don't want to restrict yourself to one architecture (like &lt;a href="https://en.wikipedia.org/wiki/X86" rel="noopener noreferrer"&gt;x86&lt;/a&gt; 32bit) you need to write your code in a way that it is architecture independent.&lt;br&gt;
As some platforms (like iPhone or Playstation) are naturally running on a different architecture (like &lt;a href="https://en.wikipedia.org/wiki/ARM_architecture_family" rel="noopener noreferrer"&gt;arm&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/PowerPC" rel="noopener noreferrer"&gt;ppc&lt;/a&gt;), you are often forced to write architecture independent if you want to support those.&lt;/p&gt;

&lt;p&gt;OpenLieroX should run on pretty much every architecture.&lt;br&gt;
Problems you are facing are for example about &lt;a href="https://en.wikipedia.org/wiki/Endianness" rel="noopener noreferrer"&gt;big/little endianness&lt;/a&gt; and 32bit versus 64bit.&lt;/p&gt;

&lt;h1&gt;
  
  
  Protocols and file formats
&lt;/h1&gt;

&lt;p&gt;In many cases, knowledge of protocols and file formats can be useful, even if a library is doing all the handling for you.&lt;br&gt;
In some cases, you even need to implement some basic support for yourself.&lt;/p&gt;

&lt;p&gt;Here a list of protocols or file formats you most likely will at least get a bit in touch with at OpenLieroX:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol" rel="noopener noreferrer"&gt;TCP&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol" rel="noopener noreferrer"&gt;UDP&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/HTTP" rel="noopener noreferrer"&gt;HTTP&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol" rel="noopener noreferrer"&gt;SMTP&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Domain_Name_System" rel="noopener noreferrer"&gt;DNS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;INI, &lt;a href="https://en.wikipedia.org/wiki/XML" rel="noopener noreferrer"&gt;XML&lt;/a&gt;, MP3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, OpenLieroX introduces also some own protocols (for networking) and file formats (maps and mods).&lt;/p&gt;

&lt;h1&gt;
  
  
  Algorithms and data structures
&lt;/h1&gt;

&lt;p&gt;You will need and learn all of the basic &lt;a href="https://en.wikipedia.org/wiki/Algorithm" rel="noopener noreferrer"&gt;algorithms&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Data_structure" rel="noopener noreferrer"&gt;data structures&lt;/a&gt;.&lt;br&gt;
That are at least:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;linked lists, hash maps, vectors, stacks, queues, sets, trees&lt;/li&gt;
&lt;li&gt;sort, search, ...&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Graphics
&lt;/h1&gt;

&lt;p&gt;When writing &lt;a href="https://en.wikipedia.org/wiki/Computer_graphics" rel="noopener noreferrer"&gt;graphics&lt;/a&gt; related code, you are dealing with a wide range of topics,&lt;br&gt;
many of them being mathematical. Despite the mathematical part, you are often also dealing with performance problems and optimisations because this is often the most performance critical part. So you need to learn how to optimise your code and at the same time keep it maintainable.&lt;/p&gt;

&lt;p&gt;Depending if your game is &lt;a href="https://en.wikipedia.org/wiki/2D_computer_graphics" rel="noopener noreferrer"&gt;2D&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/3D_computer_graphics" rel="noopener noreferrer"&gt;3D&lt;/a&gt;, the type of mathematics you are applying differs a bit (and probably 3D graphics need even some more deep knowledge of &lt;a href="https://en.wikipedia.org/wiki/Linear_algebra" rel="noopener noreferrer"&gt;linear algebra&lt;/a&gt;) but there is also a big intersection.&lt;/p&gt;

&lt;h1&gt;
  
  
  User interface
&lt;/h1&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/User_interface" rel="noopener noreferrer"&gt;user interface&lt;/a&gt; is e.g. the menus, the buttons, the dialogs, etc.&lt;/p&gt;

&lt;h1&gt;
  
  
  Audio
&lt;/h1&gt;

&lt;p&gt;You learn about the basic calculation and principles how to calculate the sound modifications when you want to get a 3D sound experience.&lt;/p&gt;

&lt;h1&gt;
  
  
  Physics
&lt;/h1&gt;

&lt;p&gt;Most games need some kind of &lt;a href="https://en.wikipedia.org/wiki/Physics_engine" rel="noopener noreferrer"&gt;physics engine&lt;/a&gt; to simulate physics of the game world. For simple games, this is usually often kept very simple.&lt;/p&gt;

&lt;h1&gt;
  
  
  Artificial intelligence
&lt;/h1&gt;

&lt;p&gt;The most obvious application of artificial intelligence in games is the computer enemy. AI in games and AI in general is really a topic for itself. Maybe the biggest and most important of all things which you learn by game development but that is up to your own focus.&lt;/p&gt;

&lt;p&gt;Also, the subtopics of AI you can apply in a game depends a bit on the type of game, but in general, a lot of different AI topics can be applied in games. (The actual topics you will apply in a game are usually much simpler though.)&lt;br&gt;
For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Planning" rel="noopener noreferrer"&gt;Planning&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Problem_solving" rel="noopener noreferrer"&gt;problem solving&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Search_algorithm" rel="noopener noreferrer"&gt;Searching&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Pathfinding" rel="noopener noreferrer"&gt;pathfinding&lt;/a&gt; (e.g. &lt;a href="https://en.wikipedia.org/wiki/A*_search_algorithm" rel="noopener noreferrer"&gt;A*&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Machine_learning" rel="noopener noreferrer"&gt;Machine learning&lt;/a&gt; (all kinds of: &lt;a href="https://en.wikipedia.org/wiki/Supervised_learning" rel="noopener noreferrer"&gt;supervised&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Reinforcement_learning" rel="noopener noreferrer"&gt;reinforced&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Unsupervised_learning" rel="noopener noreferrer"&gt;unsupervised&lt;/a&gt;), &lt;a href="https://en.wikipedia.org/wiki/Neural_network_(machine_learning)" rel="noopener noreferrer"&gt;neural networks&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/Genetic_algorithm" rel="noopener noreferrer"&gt;genetic algorithms&lt;/a&gt;, etc.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Knowledge_representation_and_reasoning" rel="noopener noreferrer"&gt;Knowledge representation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Pattern_matching" rel="noopener noreferrer"&gt;Pattern matching&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Pattern_recognition" rel="noopener noreferrer"&gt;recognition&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Cognitive_science" rel="noopener noreferrer"&gt;Cognitive science&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Natural_language_processing" rel="noopener noreferrer"&gt;Natural language processing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenLieroX has some advanced searching functions (variant of A* in an almost continuous space) and a bunch of hardcoded strategies and plans. There could be much more, like a self-learning bot (based on neural networks) or a genetically engineered bot. Or some basic support of natural language processing so that the bot can chat.&lt;/p&gt;

&lt;h1&gt;
  
  
  Game theory
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Game_theory" rel="noopener noreferrer"&gt;Game theory&lt;/a&gt; deals with theoretical questions about strategies and states of games. If you want to answer questions like if there is a strategy for your game where you always will win - that is game theory.&lt;/p&gt;

&lt;p&gt;Game theory also matters for some of the artificial intelligence applications.&lt;/p&gt;

&lt;h1&gt;
  
  
  Networking
&lt;/h1&gt;

&lt;p&gt;If you want to support some sort of multiplayer over a network (like the Internet), you need to know a bit about &lt;a href="https://en.wikipedia.org/wiki/Computer_network" rel="noopener noreferrer"&gt;networking&lt;/a&gt;.&lt;br&gt;
It is not just about encoding and serializing your data and transfer it somehow over network. A game often needs very low latency. You are usually dealing with problems like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Clock_synchronization" rel="noopener noreferrer"&gt;synchronisation of time&lt;/a&gt; (and events in time)&lt;/li&gt;
&lt;li&gt;synchronisation of the game world state&lt;/li&gt;
&lt;li&gt;unreliable data channel&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Operating systems
&lt;/h1&gt;

&lt;p&gt;How &lt;a href="https://en.wikipedia.org/wiki/Operating_system" rel="noopener noreferrer"&gt;operating systems&lt;/a&gt; work is also a whole huge topic for itself. You will scratch many parts of this because a game often has many low level parts in its code where you must know some basics about operating systems. Esp, that is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File operations and &lt;a href="https://en.wikipedia.org/wiki/File_system" rel="noopener noreferrer"&gt;file systems&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Pipeline_(computing)" rel="noopener noreferrer"&gt;Pipes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Thread_(computing)" rel="noopener noreferrer"&gt;Multithreading&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/Computer_memory" rel="noopener noreferrer"&gt;Memory&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Memory handling
&lt;/h1&gt;

&lt;p&gt;In case you need to handle with huge amounts of memory, you need to know about memory optimisations and how a computer program usually handles the &lt;a href="https://en.wikipedia.org/wiki/Memory_management" rel="noopener noreferrer"&gt;memory allocations&lt;/a&gt; on a low level. See the &lt;a href="https://en.wikipedia.org/wiki/C_dynamic_memory_allocation" rel="noopener noreferrer"&gt;malloc() function&lt;/a&gt;,&lt;br&gt;
or &lt;a href="https://people.freebsd.org/~jasone/jemalloc/bsdcan2006/jemalloc.pdf" rel="noopener noreferrer"&gt;jemalloc (popular efficient malloc implementation)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;OpenLieroX provides a build with a custom malloc implementation for debugging. See &lt;a href="https://github.com/albertz/openlierox/blob/0.59/src/common/memstats.cpp" rel="noopener noreferrer"&gt;file memstats.cpp&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Parallel computing
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Parallel_computing" rel="noopener noreferrer"&gt;Parallel computing&lt;/a&gt; is where many computations are done simultaneously in parallel.&lt;br&gt;
Games often need to make a lot of very heavy and intense calculations. The trend of computers is to have &lt;a href="https://en.wikipedia.org/wiki/Multiprocessing" rel="noopener noreferrer"&gt;multiple CPUs&lt;/a&gt; (or &lt;a href="https://en.wikipedia.org/wiki/Multi-core_processor" rel="noopener noreferrer"&gt;cores&lt;/a&gt;) instead of having a single one. To use them all, it is mandatory to write your code in a way that several parts can be executed in parallel. Despite the need for it, it also often leads to more clean code (if you do it right).&lt;/p&gt;

&lt;p&gt;So, what you will learn is how to do parallel computing in general. That is both theoretic knowledge and practical knowledge. In the practice, parallel computing is often solved via &lt;a href="https://en.wikipedia.org/wiki/Thread_(computing)" rel="noopener noreferrer"&gt;multiple threads, i.e. multithreading&lt;/a&gt;.&lt;br&gt;
The interesting parts are about how you synchronise your threads and how you communicate your data from one thread to another in a &lt;a href="https://en.wikipedia.org/wiki/Thread_safety" rel="noopener noreferrer"&gt;safe way&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Version control
&lt;/h1&gt;

&lt;p&gt;You will learn how to work with some kind of &lt;a href="https://en.wikipedia.org/wiki/Version_control" rel="noopener noreferrer"&gt;version control&lt;/a&gt; system which manages all your source code files and often also other resources of your project. It will keep track over all changes in all files and will make it possible that multiple people can work on the same code. With the history of the changes, you will be able to see what person has done what changes and you can hunt down bugs to specific changes. You can also see what person has written which parts of a source file and thus ask him about some details.&lt;/p&gt;

&lt;p&gt;Such a system is even very helpful and nice to have if you work alone on a project. And it is absolutely mandatory once you work in a team.&lt;/p&gt;

&lt;p&gt;In OpenLieroX, we use &lt;a href="https://en.wikipedia.org/wiki/Git" rel="noopener noreferrer"&gt;Git&lt;/a&gt; - a very powerful &lt;a href="https://en.wikipedia.org/wiki/Distributed_version_control" rel="noopener noreferrer"&gt;distributed version control system&lt;/a&gt;.&lt;br&gt;
Learning Git is really a whole topic for itself.&lt;br&gt;
You might want to use a platform like &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; to host your code and to make it available for others.&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing
&lt;/h1&gt;

&lt;p&gt;You might want to setup some kind of &lt;a href="https://en.wikipedia.org/wiki/Software_testing" rel="noopener noreferrer"&gt;testing&lt;/a&gt; for your code, e.g. &lt;a href="https://en.wikipedia.org/wiki/Unit_testing" rel="noopener noreferrer"&gt;unit tests&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Integration_testing" rel="noopener noreferrer"&gt;integration tests&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Continuous integration
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Continuous_integration" rel="noopener noreferrer"&gt;Continuous integration&lt;/a&gt; is a way to automate the testing and building of your code.&lt;br&gt;
E.g. GitHub supports this with &lt;a href="https://docs.github.com/en/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Debugging
&lt;/h1&gt;

&lt;p&gt;You will stumble upon bugs and problems in your code. You will need to learn how to find and fix them. This is called &lt;a href="https://en.wikipedia.org/wiki/Debugging" rel="noopener noreferrer"&gt;debugging&lt;/a&gt;. Fortunately, there are many tools available to help you with debugging, such as &lt;a href="https://en.wikipedia.org/wiki/Debugger" rel="noopener noreferrer"&gt;debuggers&lt;/a&gt;. See &lt;a href="https://github.com/albertz/wiki/blob/master/debugging.md" rel="noopener noreferrer"&gt;here for a list&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Profiling
&lt;/h1&gt;

&lt;p&gt;Your code might be too slow (or hang) or use too much memory.&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Profiling_(computer_programming)" rel="noopener noreferrer"&gt;Profiling&lt;/a&gt; is a way to find out where your code is slow or uses too much memory. There are many tools available to help you with profiling, usually called profilers. See &lt;a href="https://github.com/albertz/wiki/blob/master/profiling.md" rel="noopener noreferrer"&gt;here for a list&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Media design
&lt;/h1&gt;

&lt;p&gt;A game usually needs graphics, sounds, levels or other media. Those need to be created and designed.&lt;/p&gt;

&lt;p&gt;There are also many existing assets available online&lt;br&gt;
(see &lt;a href="https://github.com/albertz/Coding-Game-Intro?tab=readme-ov-file#assets--artwork--graphics--sounds-for-your-game" rel="noopener noreferrer"&gt;this list&lt;/a&gt;).&lt;/p&gt;

&lt;h1&gt;
  
  
  Story and game design
&lt;/h1&gt;

&lt;p&gt;Depending on the type of game, you need a story.&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Game_design" rel="noopener noreferrer"&gt;Game design&lt;/a&gt; is a whole topic for itself.&lt;/p&gt;

&lt;h1&gt;
  
  
  Teamwork
&lt;/h1&gt;

&lt;p&gt;A project of the size of OpenLieroX needs teamwork. Various people doing various different tasks (coding, designing, distribution, support, testing) need to coordinate. This is even more important for the coding which can be the biggest of those tasks. Once there are multiple people working on the same code, they need to coordinate. The source code version control management system is very central for this&lt;br&gt;
(see version control)&lt;br&gt;
(but this is useful even if you are working alone on a project).&lt;/p&gt;

&lt;h1&gt;
  
  
  Project management
&lt;/h1&gt;

&lt;p&gt;Once the project is getting bigger, you need to manage the project, e.g. keep track of the tasks, bugs, features, etc.&lt;br&gt;
Platforms like GitHub provide some tools for this&lt;br&gt;
such as an &lt;a href="https://docs.github.com/en/issues" rel="noopener noreferrer"&gt;issue tracker&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Software_project_management" rel="noopener noreferrer"&gt;Project management&lt;/a&gt; is again a whole topic for itself.&lt;/p&gt;

&lt;h1&gt;
  
  
  Where to start
&lt;/h1&gt;

&lt;p&gt;See &lt;a href="https://github.com/albertz/Coding-Game-Intro" rel="noopener noreferrer"&gt;Coding Game Intro&lt;/a&gt;. You could start some own simple game project&lt;br&gt;
(&lt;a href="https://github.com/albertz/Coding-Game-Intro?tab=readme-ov-file#some-simple-game-ideas" rel="noopener noreferrer"&gt;some ideas&lt;/a&gt;),&lt;br&gt;
or take an existing open source game and modify it&lt;br&gt;
(&lt;a href="https://github.com/albertz/Coding-Game-Intro?tab=readme-ov-file#existing-open-source-games-as-a-good-project-base" rel="noopener noreferrer"&gt;examples&lt;/a&gt;), or contribute to an existing open source game project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading code of existing games
&lt;/h2&gt;

&lt;p&gt;To be able to do something useful with the code, it is very helpful / mandatory that you have a rough overview over the code. Many projects have an overview document. Also see &lt;a href="https://github.com/albertz/wiki/blob/master/coding.md#reading-code-of-existing-projects" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributing to an existing project
&lt;/h2&gt;

&lt;p&gt;Many projects have a document like &lt;code&gt;CONTRIBUTING.md&lt;/code&gt; describing how to contribute. It usually also makes sense to speak to someone from the project first. Also see &lt;a href="https://github.com/albertz/wiki/blob/master/coding.md#contributing-to-existing-projects" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up a development environment
&lt;/h2&gt;

&lt;p&gt;For a beginner, this is often the most complicated part.&lt;br&gt;
It is often not straightforward how you setup an &lt;a href="https://en.wikipedia.org/wiki/Integrated_development_environment" rel="noopener noreferrer"&gt;IDE&lt;/a&gt; / editor / compiler to build the source code.&lt;br&gt;
This is somewhat silly but you have to get through that.&lt;br&gt;
(The compiler will convert the source code into an executable binary; on Windows, that is an EXE-file.)&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Integrated_development_environment" rel="noopener noreferrer"&gt;IDE&lt;/a&gt; is the editor where you edit the code. In theory, you could also use a simple text editor; however, an IDE will be mure more helpfull and easy to use.&lt;/p&gt;

&lt;p&gt;In some cases (like MSVC), the IDE is bundled together with the compiler. In some other cases (on Linux), they are highly separate and independent from each other. That means that setting up the compiling is in some cases (like MSVC or Xcode) the same as setting up the IDE, in some cases (like on Linux) independent.&lt;/p&gt;

&lt;p&gt;However, compiling the source code is the most important thing you need to be able to do. You cannot do anything if you are not able to do this.&lt;/p&gt;

&lt;p&gt;Projects usually provide some documentation how to set up the development environment.&lt;/p&gt;

&lt;p&gt;When you start a new project, it makes sense to see some simple examples how to set up the development environment.&lt;br&gt;
Usually you would create a new version control repository, which is then an empty directory, and you would put your stuff into it. Also see &lt;a href="https://github.com/albertz/wiki/blob/master/coding.md#coding-environment" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It might also make sense to setup some generic playground environment to test minimal ideas, code snippets, etc.&lt;br&gt;
See &lt;a href="https://github.com/albertz/wiki/blob/master/coding.md#playground" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>gamedev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Playing around with Ultra HDR</title>
      <dc:creator>Albert Zeyer</dc:creator>
      <pubDate>Sat, 27 Jan 2024 14:43:03 +0000</pubDate>
      <link>https://forem.com/albertzeyer/playing-around-with-ultra-hdr-37md</link>
      <guid>https://forem.com/albertzeyer/playing-around-with-ultra-hdr-37md</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/albertz/playground/blob/master/ultrahdr.py"&gt;This is the ultrahdr.py script&lt;/a&gt;, which generates &lt;a href="https://github.com/albertz/playground/wiki/HDR-demo"&gt;this HDR-demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;(Check &lt;a href="https://gregbenzphotography.com/hdr/"&gt;gregbenzphotography.com/hdr/&lt;/a&gt; whether you can display HDR properly.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/High_dynamic_range"&gt;High-dynamic range (HDR)&lt;/a&gt; is to extend the usual color range (Standard Dynamic Range (SDR)) and usually also extends the common 8bit color depth to 10bit or more.&lt;/p&gt;

&lt;p&gt;Some modern displays (~2021) (e.g. MacBook M1, some OLED TVs) support HDR, but it is still a rare feature.&lt;/p&gt;

&lt;p&gt;There are multiple formats for HDR images, e.g.:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenEXR&lt;/li&gt;
&lt;li&gt;AVIF&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/JPEG_XT"&gt;JPEG XT&lt;/a&gt;
embedded in &lt;a href="https://en.wikipedia.org/wiki/JPEG_XL"&gt;JPEG XL&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/JPEG_XR"&gt;JPEG XR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ultra HDR (used here)
embedded in standard JPEG&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ultra HDR uses the JPEG multi-picture format (MPF). It stores the normal SDR JPEG image as the first image, so all existing JPEG decoders can display the normal image. Then it stores a HDR gain map embedded in MPF which can be used to reconstruct the HDR image.&lt;/p&gt;

&lt;p&gt;Currently, (end of 2023), Google Chrome stable (end of 2023) supports this format.&lt;br&gt;
(Another alternative in Google Chrome is AVIF.)&lt;br&gt;
(Firefox currently does not support it.)&lt;/p&gt;

&lt;p&gt;Currently, (end of 2023), Google Pixel phones can capture Ultra HDR images (e.g. when they use night mode).&lt;/p&gt;

&lt;p&gt;(Note, many websites, e.g. Twitter, will reencode JPEGs after you upload them, and often they don't support Ultra HDR yet, so then it will be lost, and you will just see the normal SDR JPEG image.)&lt;/p&gt;

&lt;p&gt;About the Ultra HDR format:&lt;br&gt;
&lt;a href="https://developer.android.com/media/platform/hdr-image-format"&gt;https://developer.android.com/media/platform/hdr-image-format&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This document defines the behavior of a new file format that encodes a logarithmic range gain map image in a JPEG image file. Legacy readers that don't support the new format read and display the conventional low dynamic range image from the image file. Readers that support the format combine the primary image with the gain map and render a high dynamic range image on compatible displays.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To use the simple script here, for preparation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, build this: &lt;a href="https://github.com/google/libultrahdr"&gt;https://github.com/google/libultrahdr&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Make sure FFMpeg is installed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This script does nothing fancy: It just upscales the input JPEG color range (FFmpeg does that here currently) and then encodes the HDR gain map using Google's Ultra HDR encoder (libultrahdr). The effect is that the image will display brighter on HDR displays.&lt;/p&gt;

&lt;p&gt;Some related issues:&lt;br&gt;
&lt;a href="https://github.com/ImageMagick/ImageMagick/issues/6377"&gt;https://github.com/ImageMagick/ImageMagick/issues/6377&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/libvips/libvips/issues/3799"&gt;https://github.com/libvips/libvips/issues/3799&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hdr</category>
      <category>python</category>
      <category>demo</category>
      <category>computervision</category>
    </item>
    <item>
      <title>Python Preloaded</title>
      <dc:creator>Albert Zeyer</dc:creator>
      <pubDate>Sun, 09 Oct 2022 12:01:51 +0000</pubDate>
      <link>https://forem.com/albertzeyer/python-preloaded-4ef0</link>
      <guid>https://forem.com/albertzeyer/python-preloaded-4ef0</guid>
      <description>&lt;h1&gt;
  
  
  Python Preloaded
&lt;/h1&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/albertz/python-preloaded"&gt;https://github.com/albertz/python-preloaded&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Problem:&lt;/p&gt;

&lt;p&gt;The startup time of CPython including loading big libraries like PyTorch or TensorFlow is too slow. In case of slow file systems, I have seen startup times including such import of 10-20 seconds.&lt;/p&gt;

&lt;p&gt;Very simple idea:&lt;/p&gt;

&lt;p&gt;Keep the state of CPython right after we imported the big libraries and make it available instantly when needed. When loading the state, we can continue to run any random Python script (we can use &lt;a href="https://docs.python.org/3/library/runpy.html"&gt;runpy&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install preloaded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Method 1: Fork server
&lt;/h2&gt;

&lt;p&gt;Start CPython and import the libraries. Then keep the process running as a fork server. Whenever a new instance it needed, we make a fork (&lt;code&gt;os.fork&lt;/code&gt;), and apply a similar logic as &lt;a href="https://github.com/nelhage/reptyr"&gt;reptyr&lt;/a&gt;. Some technical details are &lt;a href="https://github.com/albertz/python-preloaded/blob/main/docs/pty-details.md"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This solution is very portable across Unix. I tested it so far on Linux and MacOSX, but it should run on most other Unixes as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Create the starter script &lt;code&gt;python-tf.bin&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ py-preloaded-bundle-fork-server.py tensorflow -o python-tf.bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starter script is supposed to be a dropin replacement to &lt;code&gt;python&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;For testing, there is &lt;code&gt;demo-import-tensorflow.py&lt;/code&gt;, with only the following content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tensorflow&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"TF:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__version__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now try to run it directly, and measure the time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ time python3 demo-import-tensorflow.py
TF: 2.3.0

________________________________________________________
Executed in    8.31 secs    fish           external
   usr time    3.39 secs  278.00 micros    3.39 secs
   sys time    0.67 secs   83.00 micros    0.67 secs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is on a slow filesystem, NFS specifically. This is already after the files are cached (I just ran the same command immediately before). Otherwise, the startup time is even over 14 seconds.&lt;/p&gt;

&lt;p&gt;The starter script was not run yet, so the first start is just as slow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ time ./python-tf.bin demo-import-tensorflow.py
Existing socket but can not connect: [Errno 111] Connection refused
Import module: tensorflow
TF: 2.3.0

________________________________________________________
Executed in    8.35 secs    fish           external
   usr time    3.19 secs  768.00 micros    3.19 secs
   sys time    0.72 secs  228.00 micros    0.72 secs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it is running in the background. It is in no way fixed to &lt;code&gt;demo-import-tensorflow.py&lt;/code&gt; but could also run any other script now. However, we continue the demo with the same script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ time ./python-tf.bin demo-import-tensorflow.py
Existing socket, connected
Open new PTY
Send PTY fd to server
Wait for server to be ready
Entering PTY proxy loop
TF: 2.3.0

________________________________________________________
Executed in  261.56 millis    fish           external
   usr time   64.24 millis  542.00 micros   63.70 millis
   sys time   33.59 millis  163.00 micros   33.43 millis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see, the startup time is now very fast. This is also just as fast when executed at a later time, when the files are not cached anymore.&lt;/p&gt;

&lt;p&gt;Interactively test the starter script environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./python-tf.bin -m IPython
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Method 2: Process pool
&lt;/h2&gt;

&lt;p&gt;We always keep some pool (e.g. N=10 instances) of CPython + preloaded libraries alive in the background, and once we need a new instance, we just pick one from the pool.&lt;/p&gt;

&lt;p&gt;This shares a lot of logic with the fork server. The main difference basically is that we use &lt;code&gt;subprocess.Popen&lt;/code&gt; instead of &lt;code&gt;os.fork&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;(Currently not implemented)&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 3: Program checkpoint on disk
&lt;/h2&gt;

&lt;p&gt;Use some checkpointing tool (&lt;a href="https://criu.org/"&gt;CRIU&lt;/a&gt;) to store the state of CPython right after we imported the libraries. Then later we can load this checkpoint (very fast).&lt;/p&gt;

&lt;p&gt;CRIU currently needs root access for dump/restore. However, there is ongoing work to support a non-root option in &lt;a href="https://github.com/checkpoint-restore/criu/pull/1930"&gt;https://github.com/checkpoint-restore/criu/pull/1930&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Or maybe &lt;a href="https://github.com/dmtcp/dmtcp/"&gt;DMTCP&lt;/a&gt; is a better alternative to CRIU?&lt;/p&gt;

&lt;p&gt;(Currently incomplete)&lt;/p&gt;

</description>
      <category>python</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Managing paper bibliography, reading list</title>
      <dc:creator>Albert Zeyer</dc:creator>
      <pubDate>Sun, 23 Jan 2022 10:46:06 +0000</pubDate>
      <link>https://forem.com/albertzeyer/managing-paper-bibliography-reading-list-2l0g</link>
      <guid>https://forem.com/albertzeyer/managing-paper-bibliography-reading-list-2l0g</guid>
      <description>&lt;p&gt;(Meta question: Maybe this community not the right place to ask, as this question is more about academic research, less about software development. But I really don't know where to ask. StackExchange will close this as opinion-based. Quora is only for short questions (asked &lt;a href="https://www.quora.com/unanswered/How-do-you-manage-your-paper-library-bibliography-and-reading-list-So-far-I-did-that-mostly-by-hand-collecting-papers-in-a-bib-file-and-Google-Doc-with-higher-level-notes-I-now-consider-Zotero-as-an-easier-way-to"&gt;here&lt;/a&gt;). Reddit maybe but not sure where exactly. Twitter maybe, as this would reach some relevant people, but this is again only for short questions.)&lt;/p&gt;

&lt;p&gt;So far, when I stumbled upon a nice paper (all the time when I open my Twitter timeline), I put it on a reading list, which is a Google Doc, or leave the paper open in a tab until I get time to read it later. That's how I easily end up with 100s of open tabs. Some of them I read, and then I also put them in other Google Docs for some specific research field which I work on where it relates to. I also have a huge Bibtex file which I edit by hand, where I put papers in which I cite in own papers. I further have some scripts which organize, unify and deduplicate entries in that Bibtex file. &lt;/p&gt;

&lt;p&gt;Google Doc is online, and the Bibtex file in some Git repo, so everything is properly synchronized. This is an important requirement.&lt;/p&gt;

&lt;p&gt;However, it doesn't scale well, and is annoying to organize. I have all these tabs open because it is way too complicated to open the Google Doc and put it in there for potential later read, maybe with some note where I found it or why I think it is relevant for me. Then sometimes each month I go through all these tabs and put it into the Google Doc, which is pretty annoying.&lt;/p&gt;

&lt;p&gt;So now I considered to use &lt;a href="https://www.zotero.org/"&gt;Zotero&lt;/a&gt;. But this lacks a lot of what I do currently, e.g. running my scripts to unify entries. I saw that there is a plugin architecture, and the &lt;a href="https://github.com/retorquere/zotero-better-bibtex/"&gt;Zotero-better-bibtex plugin&lt;/a&gt;, and a &lt;a href="https://gist.github.com/danbe/6547077"&gt;Python script using that debug bridge&lt;/a&gt;. So probably I can use that as a base to make my existing scripts work. But not sure if I should work on that now. I also wonder a bit that I still need to put so much own work into it, and how other people are doing this.&lt;/p&gt;

&lt;p&gt;&lt;del&gt;Also, importing a paper in Zotero is still not so easy. E.g. when I have some Arxiv page open, ideally I want to do a single click to import it. But now I need to click the "export as bibtex" button, copy that into clipboard, then import that in Zotero, and then currently manually edit the entry to be consistent.&lt;/del&gt; &lt;strong&gt;Edit&lt;/strong&gt; I just needed a reload of the Arxiv page after I enabled the Chrome extension. After that, the import properly works now with a single click, which is nice. It still might need some post-editing, e.g. changing "Journal article" to "Report", and maybe other things.&lt;/p&gt;

&lt;p&gt;Maybe I have not found the right plugins yet. Or maybe there are also better solutions than Zotero. Or maybe I do things wrong. I would just like to know how others are doing this.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>help</category>
      <category>deeplearning</category>
    </item>
    <item>
      <title>Fastest implementation of `ast.literal_eval`</title>
      <dc:creator>Albert Zeyer</dc:creator>
      <pubDate>Thu, 02 Sep 2021 06:51:58 +0000</pubDate>
      <link>https://forem.com/albertzeyer/fastest-implementation-of-ast-literaleval-3plp</link>
      <guid>https://forem.com/albertzeyer/fastest-implementation-of-ast-literaleval-3plp</guid>
      <description>&lt;p&gt;I asked this as a &lt;a href="https://stackoverflow.com/questions/66480073/fastest-implementation-of-ast-literal-eval"&gt;question on StackOverflow&lt;/a&gt; and then answered it myself by some own implementation.&lt;/p&gt;




&lt;p&gt;I have some text (&lt;code&gt;str&lt;/code&gt;, &lt;code&gt;bytes&lt;/code&gt;; actually gzipped in a file on disk) which can be parsed via &lt;code&gt;ast.literal_eval&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;(It consists of a list of dicts, where the dict keys are strings, and values strings, int or float. But maybe this question could be generic for any string which can be parsed via &lt;code&gt;ast.literal_eval&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;It is large: ~22MB uncompressed.&lt;/p&gt;

&lt;p&gt;What is the fastest way to parse it?&lt;/p&gt;

&lt;p&gt;Surely I can use &lt;code&gt;ast.literal_eval&lt;/code&gt;, but this seems quite slow. Standard &lt;code&gt;eval&lt;/code&gt; is slightly faster (interestingly, but probably as expected, depending how well you know Python; see the implementation of &lt;code&gt;ast.literal_eval&lt;/code&gt;) but still slow.&lt;/p&gt;

&lt;p&gt;In comparison, when I serialize the same data as JSON, and then load the JSON (&lt;code&gt;json.loads&lt;/code&gt;), this is &lt;strong&gt;way&lt;/strong&gt; faster (&amp;gt;10x). So this shows that in principle it should be possible to parse it just as fast.&lt;/p&gt;

&lt;p&gt;Some statistics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gunzip + read time: 0.15111494064331055
Size: 22035943
compile: 3.1023156170000004
parse: 3.3381092380000004
eval: 3.0252232049999996
ast.literal_eval: 3.765798232
json.loads: 0.2657175249999994
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This benchmark script and also a script to generate such a dummy text file can be found: &lt;a href="https://gist.github.com/albertz/f403ed78024bcd1ac7e7866125fe6f89"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Maybe the answer is: "this needs a faster C implementation; no-one has implemented that yet")&lt;/p&gt;

&lt;p&gt;After posting this, I found some related questions. I did not found them via Google though (maybe my search term "faster literal_eval" was bad).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/21223392/why-is-json-loads-an-order-of-magnitude-faster-than-ast-literal-eval"&gt;Why is json.loads an order of magnitude faster than ast.literal_eval?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/12735106/python-ast-vs-json-for-str-to-dict-translation"&gt;python ast vs json for str to dict translation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This partly answers the question on why &lt;code&gt;ast.literal_eval&lt;/code&gt; is slow.&lt;/p&gt;

&lt;p&gt;Also, this basically tells you, when you are thinking whether Python code is a good human readable serialization format (e.g. via &lt;code&gt;repr&lt;/code&gt;), then this tells you, better use JSON instead.&lt;/p&gt;

&lt;p&gt;So, to the best of my knowledge, there currently did not exist a faster implementation than &lt;code&gt;ast.literal_eval&lt;/code&gt; (well, &lt;code&gt;eval&lt;/code&gt; itself is a bit faster, but unsafe).&lt;/p&gt;

&lt;p&gt;So I implemented my own simple implementation, which converts the literal Python code into equivalent binary Pickle data.&lt;br&gt;
So, for some bytes &lt;code&gt;data&lt;/code&gt;, instead of &lt;code&gt;ast.literal_eval(data.decode("utf8"))&lt;/code&gt;, you would use &lt;code&gt;pickle.loads(py_to_pickle(data))&lt;/code&gt;, and get a &lt;strong&gt;speedup by 5.5x&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The repo is &lt;a href="https://github.com/albertz/literal-python-to-pickle"&gt;here&lt;/a&gt;.&lt;br&gt;
This is a quite straight-forward implementation in C++, and you can easily directly use it with &lt;code&gt;ctypes&lt;/code&gt; (there is an example in the repo).&lt;/p&gt;

&lt;p&gt;New statistics:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gunzip + read time: 0.1663219928741455
Size: 22540270
py_to_pickle: 0.539439306
pickle.loads+py_to_pickle: 0.7234611099999999
compile: 3.3440755870000003
parse: 3.6302585899999995
eval: 3.306765757000001
ast.literal_eval: 4.056752016000003
json.loads: 0.3230752619999997
pickle.loads: 0.1351051709999993
marshal.loads: 0.10351717500000035
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
    </item>
    <item>
      <title>Difference of FICLONE vs FICLONERANGE vs copy_file_range (for copy-on-write support)</title>
      <dc:creator>Albert Zeyer</dc:creator>
      <pubDate>Thu, 02 Sep 2021 06:43:31 +0000</pubDate>
      <link>https://forem.com/albertzeyer/difference-of-ficlone-vs-ficlonerange-vs-copyfilerange-for-copy-on-write-support-41lm</link>
      <guid>https://forem.com/albertzeyer/difference-of-ficlone-vs-ficlonerange-vs-copyfilerange-for-copy-on-write-support-41lm</guid>
      <description>&lt;p&gt;This was original a &lt;a href="https://stackoverflow.com/questions/65505765/difference-of-ficlone-vs-ficlonerange-vs-copy-file-range-for-copy-on-write-supp"&gt;StackOverflow question by me&lt;/a&gt;, although it was maybe way too specific for StackOverflow, and too long. I then later also answered it myself. So the answer comes below.&lt;br&gt;
I feel this might be interesting for some developers, so this is why I post it here.&lt;/p&gt;




&lt;p&gt;I wonder about an efficient way to copy files (on Linux, on a FS which supports &lt;a href="https://en.wikipedia.org/wiki/Copy-on-write"&gt;&lt;strong&gt;copy-on-write (COW)&lt;/strong&gt;&lt;/a&gt;).&lt;br&gt;
Specifically, I want that my implementation uses copy-on-write if possible, but otherwise falls back to other efficient variants. Specifically, I also care about &lt;strong&gt;server-side copy&lt;/strong&gt; (supported by &lt;a href="https://wiki.samba.org/index.php/Server-Side_Copy"&gt;SMB&lt;/a&gt;, &lt;a href="https://linux-nfs.org/wiki/index.php/Server_Side_Copy"&gt;NFS&lt;/a&gt; and &lt;a href="https://serverfault.com/questions/566708/which-file-transfer-protocols-support-server-side-copying"&gt;others&lt;/a&gt;), and also &lt;a href="https://en.wikipedia.org/wiki/Zero-copy"&gt;&lt;strong&gt;zero-copy&lt;/strong&gt;&lt;/a&gt; (i.e. bypassing the CPU or memory if possible).&lt;/p&gt;

&lt;p&gt;(This question is not really specific to any programming language. It could be C or C++, but also any other like Python, Go or whatever has bindings to the OS syscalls, or has any way to do a syscall. If this is confusing to you, just answer in C.)&lt;/p&gt;

&lt;p&gt;It looks like &lt;a href="https://man7.org/linux/man-pages/man2/ioctl_ficlonerange.2.html"&gt;&lt;code&gt;ioctl_ficlonerange&lt;/code&gt;, &lt;code&gt;ioctl_ficlone&lt;/code&gt; (i.e. &lt;code&gt;ioctl&lt;/code&gt; with &lt;code&gt;FICLONE&lt;/code&gt; or &lt;code&gt;FICLONERANGE&lt;/code&gt;)&lt;/a&gt; support copy-on-write (COW). Specifically &lt;code&gt;FICLONE&lt;/code&gt; is used by GNU &lt;code&gt;cp&lt;/code&gt; (&lt;a href="https://github.com/coreutils/coreutils/blob/00ea4bacf6063ccc125209d5186f8f2382c6f0d4/src/copy.c#L408"&gt;here&lt;/a&gt;, via &lt;code&gt;--reflink&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Then there is also &lt;a href="https://man7.org/linux/man-pages/man2/copy_file_range.2.html"&gt;&lt;code&gt;copy_file_range&lt;/code&gt;&lt;/a&gt;, which also seems to support COW, and server-side-copy.&lt;br&gt;
(&lt;a href="https://lwn.net/Articles/659523/"&gt;LWN about copy_file_range&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;It sounds as if &lt;code&gt;copy_file_range&lt;/code&gt; is more generic (e.g. it supports server-side-copy; not sure if that is supported by &lt;code&gt;FICLONE&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;However, &lt;code&gt;copy_file_range&lt;/code&gt; seems to have some issues. &lt;br&gt;
E.g. &lt;a href="https://debbugs.gnu.org/cgi/bugreport.cgi?bug=24399"&gt;here&lt;/a&gt;, Paul Eggert comments:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[copy_file_range]'s man page &lt;br&gt;
says it uses a size_t (not off_t) to count the number of bytes to be &lt;br&gt;
copied, which is a strange choice for a file-copying API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Are there situations where &lt;code&gt;FICLONE&lt;/code&gt; would work better/different than &lt;code&gt;copy_file_range&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Are there situations where &lt;code&gt;FICLONE&lt;/code&gt; would work better/different than &lt;code&gt;FICLONERANGE&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Specifically, assuming the underlying FS supports this, and assume you want to copy a file. I ask about the support of these functions for the functionality of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Copy-on-write"&gt;Copy-on-write&lt;/a&gt; support&lt;/li&gt;
&lt;li&gt;Server-side copy support&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Zero-copy"&gt;Zero-copy&lt;/a&gt; support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are they (&lt;code&gt;FICLONE&lt;/code&gt;, &lt;code&gt;FICLONERANGE&lt;/code&gt;, &lt;code&gt;copy_file_range&lt;/code&gt;) always performing exactly the same operation? (Assuming the underlying FS supports copy-on-write, and/or server-side copy.)&lt;/p&gt;

&lt;p&gt;Or are there situations where it make sense to use &lt;code&gt;copy_file_range&lt;/code&gt; instead of &lt;code&gt;FICLONE&lt;/code&gt;? (E.g. COW only works with &lt;code&gt;copy_file_range&lt;/code&gt; but not with &lt;code&gt;FICLONE&lt;/code&gt;. Or the other way around. Or can this never happen?)&lt;/p&gt;

&lt;p&gt;Or formulating the same question differently: Would &lt;code&gt;copy_file_range&lt;/code&gt; always be fine, or are there situations where I would want to use &lt;code&gt;FICLONE&lt;/code&gt; instead?&lt;/p&gt;

&lt;p&gt;Why does GNU &lt;code&gt;cp&lt;/code&gt; use &lt;code&gt;FICLONE&lt;/code&gt; and not &lt;code&gt;copy_file_range&lt;/code&gt;? (Is there a technical reason, or is this just historic?)&lt;/p&gt;

&lt;p&gt;Related: GNU &lt;code&gt;cp&lt;/code&gt; originally did not use &lt;code&gt;reflink&lt;/code&gt; by default (see &lt;a href="https://unix.stackexchange.com/a/152639/2954"&gt;comment by the GNU coreutils maintainer Pádraig Brady&lt;/a&gt;).&lt;br&gt;
However, that was changed recently (&lt;a href="https://github.com/coreutils/coreutils/commit/25725f9d41735d176d73a757430739fb71c7d043"&gt;this commit&lt;/a&gt;, &lt;a href="https://debbugs.gnu.org/cgi/bugreport.cgi?bug=24400"&gt;bug report 24400&lt;/a&gt;), i.e. COW behavior is the default now (if possible) (&lt;code&gt;--reflink=auto&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Related &lt;a href="https://stackoverflow.com/questions/65492317/copy-file-in-python-for-zfs-or-other-fs-with-cow-copy-on-write-support/"&gt;question about Python for COW support&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Related &lt;a href="https://bugs.python.org/issue37157"&gt;discussion about FICLONE vs copy_file_range by Python developers&lt;/a&gt;. I.e. this seems to be a valid question, and it's not totally clear whether to use &lt;code&gt;FICLONE&lt;/code&gt; or &lt;code&gt;copy_file_range&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Related &lt;a href="https://docs.syncthing.net/advanced/folder-copyrangemethod.html"&gt;Syncthing documentation about the choice of methods for copying data between files&lt;/a&gt;, and&lt;br&gt;
&lt;a href="https://github.com/syncthing/syncthing/issues/4271"&gt;Syncthing issue about &lt;code&gt;copy_file_range&lt;/code&gt; and others for efficient file copying, e.g. with COW support&lt;/a&gt;.&lt;br&gt;
It also suggests that it is not so clear that &lt;code&gt;FICLONE&lt;/code&gt; would do the same as &lt;code&gt;copy_file_range&lt;/code&gt;, so their solution is to just try all of them, and fallback to the next, in this order:&lt;br&gt;
ioctl (with FICLONE), copy_file_range, sendfile, duplicate_extents, standard.&lt;/p&gt;

&lt;p&gt;Related &lt;a href="https://github.com/golang/go/issues/36817"&gt;issue by Go developers on the usage of &lt;code&gt;copy_file_range&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
It sounds as if they agree that &lt;code&gt;copy_file_range&lt;/code&gt; is always to be preferred over &lt;a href="https://man7.org/linux/man-pages/man2/sendfile.2.html"&gt;&lt;code&gt;sendfile&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;The answer:&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://github.com/torvalds/linux/blob/fcadab740480e0e0e9fa9bd272acd409884d431a/Documentation/filesystems/vfs.rst"&gt;Linux vfs doc&lt;/a&gt; about &lt;code&gt;copy_file_range&lt;/code&gt;, &lt;code&gt;remap_file_range&lt;/code&gt;, &lt;code&gt;FICLONERANGE&lt;/code&gt;, &lt;code&gt;FICLONE&lt;/code&gt; and &lt;code&gt;FIDEDUPERANGE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then see&lt;br&gt;
&lt;a href="https://github.com/torvalds/linux/blob/0adc313c4f20639f7e235b8d6719d96a2024cf91/fs/read_write.c#L1506"&gt;&lt;code&gt;vfs_copy_file_range&lt;/code&gt;&lt;/a&gt;. This first tries to call &lt;code&gt;remap_file_range&lt;/code&gt; if possible.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FICLONE&lt;/code&gt; calls &lt;code&gt;ioctl_file_clone&lt;/code&gt; (&lt;a href="https://github.com/torvalds/linux/blob/fcadab740480e0e0e9fa9bd272acd409884d431a/fs/ioctl.c#L714"&gt;here&lt;/a&gt;),&lt;br&gt;
and &lt;code&gt;FICLONERANGE&lt;/code&gt; calls &lt;code&gt;ioctl_file_clone_range&lt;/code&gt;.&lt;br&gt;
&lt;code&gt;ioctl_file_clone_range&lt;/code&gt; calls the more generic &lt;code&gt;ioctl_file_clone&lt;/code&gt; (&lt;a href="https://github.com/torvalds/linux/blob/fcadab740480e0e0e9fa9bd272acd409884d431a/fs/ioctl.c#L259"&gt;here&lt;/a&gt;).&lt;br&gt;
&lt;code&gt;ioctl_file_clone&lt;/code&gt; calls &lt;code&gt;vfs_clone_file_range&lt;/code&gt; (&lt;a href="https://github.com/torvalds/linux/blob/fcadab740480e0e0e9fa9bd272acd409884d431a/fs/ioctl.c#L239"&gt;here&lt;/a&gt;).&lt;br&gt;
&lt;code&gt;vfs_clone_file_range&lt;/code&gt; calls &lt;code&gt;do_clone_file_range&lt;/code&gt; and that calls &lt;code&gt;remap_file_range&lt;/code&gt; (&lt;a href="https://github.com/torvalds/linux/blob/74f602dc96dd854c7b2034947798c1e2a6b84066/fs/remap_range.c#L406"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;I.e. that answers the question. &lt;code&gt;copy_file_range&lt;/code&gt; is more generic, and anyway tries to call &lt;code&gt;remap_file_range&lt;/code&gt; (i.e. the same as &lt;code&gt;FICLONE&lt;/code&gt;/&lt;code&gt;FICLONERANGE&lt;/code&gt;) first internally.&lt;/p&gt;

&lt;p&gt;I think the &lt;code&gt;copy_file_range&lt;/code&gt; syscall is slightly newer than &lt;code&gt;FICLONE&lt;/code&gt; though, i.e. it might be possible that &lt;code&gt;copy_file_range&lt;/code&gt; is not available in your kernel but &lt;code&gt;FICLONE&lt;/code&gt; is.&lt;/p&gt;

&lt;p&gt;In any case, if &lt;code&gt;copy_file_range&lt;/code&gt; is available, it should be the best solution.&lt;/p&gt;

&lt;p&gt;The order done by Syncthing (ioctl (with FICLONE), copy_file_range, sendfile, duplicate_extents, standard) makes sense.&lt;/p&gt;

</description>
      <category>linux</category>
    </item>
    <item>
      <title>How to cleanup a branch (PR) with huge number of commits
</title>
      <dc:creator>Albert Zeyer</dc:creator>
      <pubDate>Thu, 02 Sep 2021 06:36:01 +0000</pubDate>
      <link>https://forem.com/albertzeyer/how-to-cleanup-a-branch-pr-with-huge-number-of-commits-2pcc</link>
      <guid>https://forem.com/albertzeyer/how-to-cleanup-a-branch-pr-with-huge-number-of-commits-2pcc</guid>
      <description>&lt;p&gt;I was trying to implement some new feature in some larger somewhat messy project (&lt;a href="https://github.com/rwth-i6/returnn/"&gt;RETURNN&lt;/a&gt; but not so relevant).&lt;/p&gt;

&lt;p&gt;So I created a new branch, also made a GitHub draft PR (&lt;a href="https://github.com/rwth-i6/returnn/pull/605"&gt;here&lt;/a&gt;), and started working on it.&lt;/p&gt;

&lt;p&gt;While working on it, it turned out that I needed several other things fixed or extended first. There was not really a clear boundary of these other things (i.e. whether they are to be considered as totally independent), nor was it really clear from the beginning on what actually is needed. This only became clear more and more along the way.&lt;/p&gt;

&lt;p&gt;In other cases, this was still not too much, and easy to manage. But for this particular thing, it became quite extreme.&lt;/p&gt;

&lt;p&gt;So now I have 90 commits (when you look at the PR at some later point, maybe less because I already cleaned up).&lt;/p&gt;

&lt;p&gt;What is a good strategy now to handle them? Some of them can be squashed together. The PR can also be split up because they touch upon several things, so each thing maybe could be moved over into an individual branch (and PR). But they partly also depend on each other in the way that they use a newly introduced feature/function, or tests would fail without the other thing, or so.&lt;/p&gt;

&lt;p&gt;Squashing can potentially already clean up a lot. Because there are some commits which introduce TODO comments, and then later implement this. Or sometimes I made some change, and then later I rewrote the code to do it differently.&lt;/p&gt;

&lt;p&gt;Is there some tool which can automatically tell which commits are good candidates to be squashed together? E.g. because they modify code in the same function or in nearby code.&lt;/p&gt;

&lt;p&gt;My usual strategy (on smaller PRs) is that I first reorder the commits logically as far as possible, and then in the next step I squash commits together.&lt;/p&gt;

&lt;p&gt;When there are other unrelated changes in the PR, I reorder them to be first. And then I create a new branch (and PR) consisting of the first set of changes. Then I wait for the test suite to run through for the new PR. Then I merge the PR into master. Then I rebase the main PR on master. And I repeat doing this process. It can require further work when the tests do not run through on some individual new PR.&lt;/p&gt;

&lt;p&gt;This way of working takes lots of time, and I need to wait often. The test cases take about 10 minutes to finish on GitHub CI. So for everything I do, I need to wait 10 minutes. So most of the time I would just wait. This often seems very unproductive to me.&lt;/p&gt;

&lt;p&gt;For the reordering and squashing and potential further changes, I use the Git GUI in PyCharm, by interactively rebasing again and again.&lt;/p&gt;

&lt;p&gt;Am I doing something suboptimally? How can I do it better?&lt;/p&gt;

&lt;p&gt;Are there other tools which can help me somehow?&lt;/p&gt;

&lt;p&gt;Are there good strategies in general how to deal with this situation?&lt;/p&gt;

&lt;p&gt;Maybe I could have avoided the situation somehow by working in a different way? Usually the branches (PRs) are much smaller, so this is much simpler to handle then. Should I actively try to keep changes minimal in some branch, so I don't end up in such situation?&lt;/p&gt;

&lt;p&gt;I guess one thing which could avoid such situation is to reduce the amount of technical debt in this project. This is one of the reasons that it was not clear from the beginning what is actually needed.&lt;/p&gt;




&lt;p&gt;Actually after formulating all this, I remembered that I did ask already a similar question on StackOverflow before on &lt;a href="https://stackoverflow.com/questions/66731069/how-to-find-pairs-groups-of-most-related-commits"&gt;"How to find pairs/groups of most related commits"&lt;/a&gt; (my memories are bad...).&lt;br&gt;
And actually I also did implement a similar script already &lt;a href="https://github.com/albertz/helpers/blob/master/git-find-related-commits.py"&gt;here&lt;/a&gt;, description of the algorithm &lt;a href="https://stackoverflow.com/a/66732834/133374"&gt;here&lt;/a&gt;. The algorithm is quadratic in the number of commits, and somewhat slow. So maybe already too slow here.&lt;/p&gt;

&lt;p&gt;(Note this is a cross post from &lt;a href="https://www.reddit.com/r/learnprogramming/comments/pftenx/how_to_cleanup_a_branch_pr_with_huge_number_of/"&gt;Reddit&lt;/a&gt;. But so far there is no real good solution.)&lt;/p&gt;

&lt;p&gt;(I &lt;a href="https://dev.to/albertzeyer/is-dev-to-good-for-asking-dev-questions-456c"&gt;asked before&lt;/a&gt; whether dev.to is a good fit for a question like this. I usually use StackOverflow but usually they do not want such opinion-based questions.)&lt;/p&gt;

</description>
      <category>help</category>
      <category>discuss</category>
      <category>github</category>
      <category>git</category>
    </item>
    <item>
      <title>Is dev.to good for asking dev questions?</title>
      <dc:creator>Albert Zeyer</dc:creator>
      <pubDate>Wed, 01 Sep 2021 12:14:04 +0000</pubDate>
      <link>https://forem.com/albertzeyer/is-dev-to-good-for-asking-dev-questions-456c</link>
      <guid>https://forem.com/albertzeyer/is-dev-to-good-for-asking-dev-questions-456c</guid>
      <description>&lt;p&gt;When I browse dev.to, most posts are just articles. I rarely see that questions are being asked here.&lt;/p&gt;

&lt;p&gt;If dev.to is not good for asking questions, what is a good place to ask questions?&lt;/p&gt;

&lt;p&gt;Of course there is StackOverflow. But that is only good for questions which have simple, clear, non-opinionated answers. I use StackOverflow quite extensively and it is great for questions which are "allowed". However, I often also have questions about recommendations and opinions, which are strictly not allowed there. But where can I ask such questions?&lt;/p&gt;

</description>
      <category>meta</category>
      <category>discuss</category>
    </item>
  </channel>
</rss>
