You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I spent some time reading over #32 and was wondering if speeding up Python startup in certain constrained scenarios may be possible. In particular, I happen to use Python to execute scripts that operate on single files so I can incorporate them into a build system.
I have a script that converts a text representation of data into a binary format. On WSL1 on my machine, this script takes 20 milliseconds to actually execute 'useful work', but takes 105 milliseconds to actually import everything. On my M1 MacBook Pro, this is 10 milliseconds + 17 milliseconds to import everything (significantly faster, but still quite a large chunk of the total time). My measurements below. The script isn't very complex either but I've included it as well (there are definitely updates I could make to further reduce the import time, but that's a bit out of scope for this issue IMO).
I believe the approach of one file processed per call is quite common, especially in a build system where you'd like to have fast iterative builds, but some alternatives I had considered:
Have one script that processes all the files at once -> we give up parallelism and the benefit of incremental builds
Have the script just process multiple files and pass 'all changed files at once' -> this would also cause us to not benefit from proper parallelism on clean builds and it would not be trivial to take advantage of resources on a system (i.e., how would you know how to take advantage of multiple cores with some N number of files? Would you need to do import time profiling? etc...)
Maybe there are some other alternatives, but some possibilities I considered were:
A ccache-like mechanism that would allow for keeping the loaded module state in memory within the scope of a build system process (e.g., the build system could spawn a 'cached-python' entity that would build up the imported/initialized modules as necessary, allowing them to be reused among many python processes)
A precompiled DSO-like mechanism that could just be loaded alongside the Python process (i.e. with LD_LIBRARY_PATH or some equivalent) with the necessary modules pre-initialized (this would probably be a huge pain for things that must dynamically initialize based on the execution environment)
python3 -m cProfile ./scripts/txt2map.py build/attribmaps/0115.map gfx/attribmaps/0115.txt ./gfx/prebuilt/attribmaps
4350 function calls (4283 primitive calls) in 0.020 seconds
#!/bin/python
import os, sys
from shutil import copyfile
sys.path.append(os.path.join(os.path.dirname(__file__), 'common'))
from common import utils, tilemaps, tilesets
output_file = sys.argv[1]
input_file = sys.argv[2]
prebuilt_root = sys.argv[3]
fname = os.path.splitext(os.path.basename(input_file))[0]
char_table = {}
# 0xFE is a special character indicating a new line for tilemaps, it doesn't really belong in the tileset table but for this specifically it makes sense
char_table['\n'] = 0xFE
prebuilt = os.path.join(prebuilt_root, f"{fname}.map")
if os.path.isfile(prebuilt):
print("\tUsing prebuilt {}".format(prebuilt))
copyfile(prebuilt, output_file)
os.utime(output_file, None)
quit()
with open(input_file, 'r', encoding='utf-8-sig') as f:
mode = f.readline().strip().strip('[]').split('|')
mode[0] = int(mode[0], 16)
is_compressed = mode[0] & 3
if len(mode) == 2:
mode[0] |= int(mode[1], 16) << 1
tmap = [mode[0]]
if is_compressed:
text = []
for line in f:
b = utils.txt2bin(line, char_table)
text += b
text.append(0xFF) # tmap compression expects 0xFF at the end
tmap += tilemaps.compress_tmap(text)
else:
text = f.read().replace('\r\n','\n')
tmap += utils.txt2bin(text, char_table)
tmap.append(0xFF)
with open(output_file, 'wb') as of:
of.write(bytearray(tmap))
From the common modules:
import struct
from ast import literal_eval
from collections import OrderedDict
import os
import struct
import sys
The text was updated successfully, but these errors were encountered:
I spent some time reading over #32 and was wondering if speeding up Python startup in certain constrained scenarios may be possible. In particular, I happen to use Python to execute scripts that operate on single files so I can incorporate them into a build system.
I have a script that converts a text representation of data into a binary format. On WSL1 on my machine, this script takes 20 milliseconds to actually execute 'useful work', but takes 105 milliseconds to actually import everything. On my M1 MacBook Pro, this is 10 milliseconds + 17 milliseconds to import everything (significantly faster, but still quite a large chunk of the total time). My measurements below. The script isn't very complex either but I've included it as well (there are definitely updates I could make to further reduce the import time, but that's a bit out of scope for this issue IMO).
I believe the approach of one file processed per call is quite common, especially in a build system where you'd like to have fast iterative builds, but some alternatives I had considered:
Maybe there are some other alternatives, but some possibilities I considered were:
(The common module imports are listed below)
From the common modules:
The text was updated successfully, but these errors were encountered: