Finding dependencies in the standard runtimes of the different programming languages
For some reasons I get’s easiely irritated when Go developers claim that their language produce small executables. I think it’s unreasonable last 5 years at least. At the same time, it’s hard topic to compare. I have experiment which maybe help to see at least partially what parts of language and runtime actually small in different programming languages. For now, I have only 4 languages: C, Rust, C# and Go. Obviously experiment can be expanded.
So the idea is following, create lots of trivial applications, define some components from which this application constist, for example language runtime, print line function, string replace function, etc. Then we can measure what compiler produces under more or less normal conditions, and solve linear equations which we curate. All programs should use functions from standard library if possible, and use dependencies only if its’ really necessary. I understand that different dependencies may give different results, but for now, when set of applications is small, I think it’s manageable.
Results
After that, would be lot of boring stuff which explain how I setup experiement, so you can better understand how to intepret results.
| Component | C - Size (B) | Rust - Size (B) | C# - Size (B) | Go - Size (B) |
|---|---|---|---|---|
| Runtime | 10,240 | 123,904 | 868,352 | 1,228,800 |
| PrintLine | 0 | 7,168 | 65,024 | 442,368 |
| ParseFloat | 512 | 17,920 | 26,112 | 17,920 |
| ParseInt | 0 | 0 | 1,024 | 23,040 |
| RandInt | 512 | 12,800 | 512 | 13,312 |
| SumStrings | 1,024 | 512 | 0 | 0 |
| StrReverse | 512 | 1,536 | 16,896 | 1,536 |
| StrReplace | 512 | 2,560 | 7,168 | 11,776 |
| ToLower | 1,024 | 8,704 | 2,048 | 14,336 |
| StrEmpty | 1,024 | 0 | 0 | 0 |
| ArrayInit | 0 | 512 | 3,584 | 1,024 |
| CmdLineArgs | 0 | 6,656 | 0 | 0 |
| CmdLineArgs2 | 4,608 | 510,976 | 1,896,448 | 89,088 |
| ReadFile | 1,024 | 12,800 | 200,704 | 115,200 |
| WriteFile | 512 | 11,264 | 182,272 | 14,848 |
| CreateFile | 512 | 8,704 | 181,248 | 15,360 |
| CreateDir | 512 | 16,896 | 14,336 | 9,728 |
| CreateDir2 | 1,536 | 16,896 | 14,336 | 113,664 |
| DeleteFile | 512 | 10,240 | 6,144 | 11,264 |
| ExistsFile | 512 | 7,168 | 10,240 | 108,544 |
| CopyFile | 1,536 | 1,536 | 13,312 | 34,816 |
| ZipFile | 189,440 | 916,992 | 971,776 | 329,216 |
| Win32Window | 1,536 | 7,168 | 120,320 | 483,840 |
| Win32Button | 0 | 1,536 | 1,024 | 0 |
| ProxyCallBaseline | 512 | 512 | 1,536 | 4,608 |
| ProxyCall | 0 | 0 | -66,560 | 512 |
| RegexMatch | 317,952 | 1,547,264 | 550,400 | 303,104 |
| TcpSimple | 1,536 | 40,960 | 194,048 | 679,936 |
| CsvWrite | 2,560 | 47,104 | 192,000 | 31,232 |
| ParametersObjectBaseline | 1,536 | 25,088 | 22,016 | 22,016 |
| ParametersObject | -512 | 0 | -512 | 512 |
| JsonWrite | 7,168 | 10,752 | 1,041,408 | 1,071,616 |
Description of each experiments
Random helpers
- PrintLine Print line to the console.
- ParseFloat Parse string with float value into float32 datatype.
- ParseInt Parse string with integer value into int32 datatype.
- RandInt Generate pseudo random number
String operations
- SumStrings The perform concatenation of two string types in the language.
- StrReverse Reverse constant string
- StrReplace Replace constant search string with target string one time
- ToLower Convert string to lowercase using default locale parameters in the langugage.
- StrEmpty Check that string is empty.
Language featuers
- ArrayInit Initialize array of 100 bytes and print all 100 of them.
- ProxyCall How much cost have proxy methods which do nothing and just bypass calls to underlying worker methods.
- ParametersObject Use parameter objects instead of long list of parameters.
Command line handling
- CmdLineArgs Printing all passed command line args
- CmdLineArgs2 Parse 4 command line arguments and print them.
Work with files and directories
- ReadFile Read file and prints it content to the console
- WriteFile Write string content to file
- CreateFile Create empty file with the given name.
- CreateDir Create empty directory with the given name.
- CreateDir2 Create empty directory with the given name and all subdirectories in path.
- DeleteFile Delete existing file.
- ExistsFile Check if file exists and print message.
- CopyFile Copy file into other file.
Archives
- ZipFile Archive string into single file packaged into ZIP file.
UI work
- Win32Window Create empty Win32 window.
- Win32Button Create Win32 window with one button.
Regex
- RegexMatch Check if string match with pattern defined as regular expression
Networking
- TcpSimple The TCP server which wrote Helo World to connected client and close the connection.
File format serialization
- CsvWrite Write simple CSV file with 3 column and proper escaping. All data is hardcoded.
- JsonWrite Write simple JSON with 3 properties. All data is hardcoded.
Experiment structure
The experiment sitting on the GitHub repo, maybe I will move it to Codeberg.
Each experiment is set of 4 applcations which reside in one file. All build infrastructure is built using conventions, so automating measurement is possible. Example of empty experiment can be found in the .template folder. List of all experiments registered in the measure.ps1. Linear equations defined in the calc.fsx file, for now things a bit fragile, since I have to manually maintain order, but it’s easier while I’m alone. When building I do not enable agressive optimization at all, since my goal not to find minimum possible with language, but to map dependencies inside language’s standard libary and common libraries, and how it affects side of code.
Findings
I cannot conclusively say lot, you can see that from numbers. C is still language with smaller footprint. Rust is second closer. C# and Go give me wierd feeling, that they try to fight for third place, but each slip and fail spectacularly in different areas. C# seems to be have better codegen, but Go have smaller standard library. Rust have sometimes really havy dependencies for unknown for me reasons.
I really would like to continue measuring languages, and their parts, but probably need help with community to have simple ideas, and implementing all of them. Would be glad if you go to repository and share what additional measurements you think would be interested to see, and easy to implement.