Beginning
I have always been a fan of (non premature) optimisations, especially the technical optimisations done to reduce the cost. When in .NET, the introduced Span<T> that brought a lot of efficiency to C# string operations, I could still remember I heard on a podcast somebody mentioned they were able to shutdown a VM on a cluster after adopting to Span<T> for some string operations that saved some money.
Fast-forward to last month, knowing libuv, a multi-platform C library that provides support for asynchronous I/O based on event loops is the backend of uvicorn, an ASGI-powered Python web server with enhanced performance was an eyeopener and I wasn’t really aware one could use C/C++ code in Python. I just learnt about extending Python with C.
Physical vs Logical Data Types
We often refer how the data is actually represented in a lower level at system level such as how it is represented in DMBS engine storage or programming language runtime / VMs as physical representation of data types, this includes numerical representation such as int, float, long, etc and characters char. On the other hand the higher level abstraction of human understandable representation of complex data such as json as logical data type.
The higher level abstraction is often coupled with the way it is implemented and such implementation does directly impact on its performance. This is why the conventional string processing using += operator is not optimal than StringBuilder class in C# and the same reason is applicable for the string slicing and manipulation operation done in traditional way is computationally high costing than Span<T>.
In the case of Python, especially in CPython, datatypes are implemented as C structures. Each Python object has a type object that defines its behaviour, such as how the object is created, how it behaves when manipulated, and how it interacts with other objects. This type object is a C structure that points to a set of function pointers that implement the object’s methods.
Modularity vs Convenience: Case Study on Date Only Representation
C was not implemented as a language to perform operations with high efficiency in a time when we didn’t have much hardware advancements, at the time of the first release of C, we’re just starting to moving away from punch cards. C was designed to be a small, simple language with a minimalistic feature set. The goal was to provide only the most essential features that a programmer needs to write efficient and portable programs, without adding unnecessary abstractions or functionality. The C Standard Library (ISO/IEC 9899) does not have a dedicated date type or a built-in date structure that directly supports handling calendar dates (i.e., year, month, day)
On the other hand Python was never implemented in performance considered. It was implemented as a convenient language. In its standard library the language provides datatime module. but the C Standard Library provides several functions for working with date and time, primarily through the <time.h> header. The functionality is more low-level and doesn’t provide the same high-level abstractions that Python’s datetime module does, but you can still represent, manipulate, and format date and time using the C standard library.
I wanted to manipulate only date (ie: dateonly) but in Python I get a convoluted datetime library while on C, I may need to use something like below which would take 12 bytes to store a date in memory:
typedef struct {
int year;
int month;
int day;
} Date;
This is how I could only be able to achieve modularity for dateonly data representation in C.
Reduced Memory ∝ Reduced Cloud Cost: Bit Packing
As I said in the beginning, if we manage to reduce the memory footprint, we should be able to reduce the cloud bill. If my requirement is only to process dateonly values, using datetime module in Python in unnecessary. I could use 12 bytes if I use the above C typedef or even I could use just 4 bytes, if I use something like below:
typedef struct {
unsigned int day : 5; // 5 bits day
unsigned int month : 4; // 4 bits month
unsigned int year : 7; // 7 bits year
} Date;
Even though this representation would use only 16 bit fields (which may appear like 2 bytes) due to this is unsigned, it would cost us 4 bytes.
This is where bitpacking comes handy. So I can pack 16 bits, allocate first 7 bits to store year (where I can store 127 years conveniently), the next 4 bits to store month and the last 5 to store date. So the packed date would look like this:

((year << 9) | (month << 5) | (day))
High Performance ∝ Reduced Cloud Cost: The Birth of the Package
This is the mechanism I used in my dateonly-20 package (dateonly_20 module). It is open source and it does certainly perform better.
$ python
Python 3.9.13 (v3.9.13:6de2ca5339, May 17 2022, 11:37:23)
[Clang 13.0.0 (clang-1300.0.29.30)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> from dateonly_20 import parse_date, add_date
>>> from datetime import timedelta, datetime
>>>
>>> d = parse_date('2000-05-09')
>>> timeit.timeit('add_date(d,0,0,10)', globals=globals(), number=10000000)
1.9289473790000216
>>>
>>> dt = datetime(2000,5,9)
>>> timeit.timeit('dt + timedelta(days=10)', globals=globals(), number=10000000)
5.240445284999964
>>>
>>>
On my Intel Mac, the dateonly_20 module performs nearly 3 times better than the conventional way to add dates.
Floating Point Bug: Time Cost of Blind LLM Dependancy
While I am publishing the package I decided to use LLM to save sometime by using ChatGPT to help me implement the github actions yml file. I mainly decided as this is the first time I will be publishing PyPI package using CI/CD where it has C code that needs to be built in various platforms for each desired python version and all of the platform and python version specific files needs to be uploaded to the package manager.
Thats when the ChatGPT gave me buggy code. It didn’t clearly hallucinate, but it didn’t actually know of a workaround hidden in a Github issue comment.
build-macos:
runs-on: macos-latest
strategy:
matrix:
python-version: [3.9, 3.10, 3.11, 3.12, 3.13]
fail-fast: false
The above is what ChatGPT suggested, but due to the bug 3.10 is parsed as 3.1 and the cibuildwheel couldn’t locate the right artifacts to build for python 3.1. However finally I was managed to resolve this problem too with my intervention.
Rust: Missing Standard Library Date Time Module
In the case of Rust too, as a modern language, it doesn’t contain date time module in its standard library. The reason is very simple, this topic is complicated. In my opinion too, covering a while combination – permutation of datetime values would surely convolute the module. It doesn’t make the module truly modular. As programmers, we should be able to implement something that is effective for the requirement, just like no one will create a module to logically store all address in the world as a date type and deal with UK’s postcode and US’s zip code problem.
Happy Coding.

Leave a comment