Skip to content

Commit 7ab5252

Browse files
committed
Add CIRCUITPY_MESSAGE_COMPRESSION_LEVEL
to trade compile speed & flash size Initially enable the faster mode on rp2040 and espressif, where there's usually plenty of flash available (these advanced techniques save hundreds to thousands of bytes, which is important on a lot of old samd21 boards but is a drop in the lake of a 4MB flash chip)
1 parent 770f22e commit 7ab5252

File tree

8 files changed

+32
-6
lines changed

8 files changed

+32
-6
lines changed

mpy-cross/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ endif
6363
OBJ = $(PY_CORE_O)
6464
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
6565

66+
# CIRCUITPY
6667
$(BUILD)/supervisor/shared/translate/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/compressed_translations.generated.h
68+
CIRCUITPY_MESSAGE_COMPRESSION_LEVEL = 1
6769

6870
include $(TOP)/py/mkrules.mk

ports/espressif/mpconfigport.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,6 @@ endif
148148
# only if something else is turned off, such as HID.
149149
USB_NUM_ENDPOINT_PAIRS = 7
150150
USB_NUM_IN_ENDPOINTS = 5
151+
152+
# Usually lots of flash space available
153+
CIRCUITPY_MESSAGE_COMPRESSION_LEVEL ?= 1

ports/raspberrypi/mpconfigport.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,6 @@ USB_NUM_ENDPOINT_PAIRS = 8
5252

5353
INTERNAL_FLASH_FILESYSTEM = 1
5454
CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY = 1
55+
56+
# Usually lots of flash space available
57+
CIRCUITPY_MESSAGE_COMPRESSION_LEVEL ?= 1

ports/unix/mpconfigport.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,6 @@ MICROPY_VFS_LFS2 = 0
5050

5151
# CIRCUITPY
5252
CIRCUITPY_ULAB = 1
53+
CIRCUITPY_MESSAGE_COMPRESSION_LEVEL = 1
5354
MICROPY_EMIT_NATIVE = 0
5455
CFLAGS += -DCIRCUITPY=1

ports/unix/variants/coverage/mpconfigvariant.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,4 @@ CFLAGS += \
9292

9393
SRC_C += coverage.c
9494
SRC_CXX += coveragecpp.cpp
95+
CIRCUITPY_MESSAGE_COMPRESSION_LEVEL = 1

py/circuitpy_mpconfig.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ CFLAGS += -DCIRCUITPY=$(CIRCUITPY)
5252
CIRCUITPY_FULL_BUILD ?= 1
5353
CFLAGS += -DCIRCUITPY_FULL_BUILD=$(CIRCUITPY_FULL_BUILD)
5454

55+
# By default, aggressively reduce the size of in-flash messages, at the cost of
56+
# increased build time
57+
CIRCUITPY_MESSAGE_COMPRESSION_LEVEL ?= 9
58+
5559
# Reduce the size of in-flash properties. Requires support in the .ld linker
5660
# file, so not enabled by default.
5761
CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE ?= 0

py/maketranslationdata.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ class EncodingTable:
174174
qstrs_inv: object
175175

176176

177-
def compute_huffman_coding(qstrs, translation_name, translations, f):
177+
def compute_huffman_coding(qstrs, translation_name, translations, f, compression_level):
178178
# possible future improvement: some languages are better when consider len(k) > 2. try both?
179179
qstrs = dict((k, v) for k, v in qstrs.items() if len(k) > 3)
180180
qstr_strs = list(qstrs.keys())
@@ -209,6 +209,8 @@ def remove_offset(c):
209209
if 0x80 <= ord_c < 0xFF:
210210
end_unused = min(ord_c, end_unused)
211211
max_words = end_unused - 0x80
212+
if compression_level < 5:
213+
max_words = 0
212214

213215
bits_per_codepoint = 16 if max_ord > 255 else 8
214216
values_type = "uint16_t" if max_ord > 255 else "uint8_t"
@@ -298,8 +300,12 @@ def est_net_savings(s, occ):
298300
word = scores[0][0]
299301
words.append(word)
300302

303+
splitters = words[:]
304+
if compression_level > 3:
305+
splitters.extend(qstr_strs)
306+
301307
words.sort(key=len)
302-
extractor = TextSplitter(words + qstr_strs)
308+
extractor = TextSplitter(splitters)
303309
counter = collections.Counter()
304310
used_qstr = 0
305311
for t in texts:
@@ -356,8 +362,8 @@ def est_net_savings(s, occ):
356362
len(translation.encode("utf-8")) for (original, translation) in translations
357363
)
358364

359-
maxlen = len(words[-1])
360-
minlen = len(words[0])
365+
maxlen = len(words[-1]) if words else 0
366+
minlen = len(words[0]) if words else 0
361367
wlencount = [len([None for w in words if len(w) == l]) for l in range(minlen, maxlen + 1)]
362368

363369
translation_qstr_bits = used_qstr.bit_length()
@@ -596,6 +602,12 @@ def output_translation_data(encoding_table, i18ns, out):
596602
parser.add_argument(
597603
"--translation", default=None, type=str, help="translations for i18n() items"
598604
)
605+
parser.add_argument(
606+
"--compression_level",
607+
type=int,
608+
default=9,
609+
help="degree of compression (>5: construct dictionary; >3: use qstrs)",
610+
)
599611
parser.add_argument(
600612
"--compression_filename",
601613
type=argparse.FileType("w", encoding="UTF-8"),
@@ -619,6 +631,6 @@ def output_translation_data(encoding_table, i18ns, out):
619631
i18ns = sorted(i18ns)
620632
translations = translate(args.translation, i18ns)
621633
encoding_table = compute_huffman_coding(
622-
qstrs, args.translation, translations, args.compression_filename
634+
qstrs, args.translation, translations, args.compression_filename, args.compression_level
623635
)
624636
output_translation_data(encoding_table, translations, args.translation_filename)

py/py.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ $(PY_BUILD)/translations-$(TRANSLATION).c: $(HEADER_BUILD)/compressed_translatio
269269
$(HEADER_BUILD)/compressed_translations.generated.h: $(PY_SRC)/maketranslationdata.py $(HEADER_BUILD)/$(TRANSLATION).mo $(HEADER_BUILD)/qstrdefs.generated.h
270270
$(STEPECHO) "GEN $@"
271271
$(Q)mkdir -p $(PY_BUILD)
272-
$(Q)$(PYTHON) $(PY_SRC)/maketranslationdata.py --compression_filename $(HEADER_BUILD)/compressed_translations.generated.h --translation $(HEADER_BUILD)/$(TRANSLATION).mo --translation_filename $(PY_BUILD)/translations-$(TRANSLATION).c --qstrdefs_filename $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/qstrdefs.preprocessed.h
272+
$(Q)$(PYTHON) $(PY_SRC)/maketranslationdata.py --compression_filename $(HEADER_BUILD)/compressed_translations.generated.h --translation $(HEADER_BUILD)/$(TRANSLATION).mo --translation_filename $(PY_BUILD)/translations-$(TRANSLATION).c --qstrdefs_filename $(HEADER_BUILD)/qstrdefs.generated.h --compression_level $(CIRCUITPY_MESSAGE_COMPRESSION_LEVEL) $(HEADER_BUILD)/qstrdefs.preprocessed.h
273273

274274
PY_CORE_O += $(PY_BUILD)/translations-$(TRANSLATION).o
275275

0 commit comments

Comments
 (0)