diff --git a/README.md b/README.md index 1dfcf76cfcd2d19068a090b00640a642608d9eed..e8a91574fde51796a933aa341779e06fa1301d1f 100644 --- a/README.md +++ b/README.md @@ -242,6 +242,76 @@ $ ab abconfig-mpy * 字符数据使用`Dict`存储,字符`Unicode`值作为关键字,取值耗时可以忽略 * 显示字符耗时未统计 +### 关于提速 + +决定显示速度的因素有两方面: + +* 从字库中读取指定字符的字模数据 +* 在 oled 中显示 + +显示部分,`MicroPython`已经提供了`SSD1306`驱动,使用`FrameBuffer`进行数据管理,我相信官方的实力,所以显示部分的速度假设已经没有提升空间了 + +数据部分,最开始的思路就是“完成功能”,所以在读取的时候是这个流程: + +1. 打开字库文件 +2. 取一个字符 +3. `分段`查找字符在`索引表`中的偏移量 +4. `定位`到偏移量读取字模数据 +5. 从第`2`步开始循环,直到读取所有字符数据 + +> `分段`的意思是:在`Python`中打开文件,它不提供查找功能,需要先读取文件内容再进行查找,对于开发板来说,一次性读取全部文件肯定会导致`内存溢出`,所以需要分段读取一段合理长度的数据再进行查找,在查找到之前就需要不停的分段读取 + + +这个方法的问题在于,每个字符都要从`索引表`的开始位置进行查找,比较浪费 + +提速的思路就是,在每次`分段`读取数据的时候查找所有字符,减少`分段`次数 + +继续查找资料,有人说使用`read`代替`seek`可以提高`定位`的效率,在电脑上进行了简单测试,300M 的文件使用`read`比`seek`快大约`0.2 ms`,但是这个方法有个致命问题,虽然`read`读取到的数据并不使用,但也会分配内存空间,在开发板上运行的结果就是,更慢了 + +对比一下三种方式的读取速度(毫秒) + +字库文件信息: +* 文件大小:500024 字节 +* 字符总数:8932 个 +* 数据大小:54 字节 + +| | 原方法 | 新方法(seek) | 新方法(read) | +| :-: | :-: | :-: | :-: | +| 打开字库 | 27.51 | 26.22 | 61.21 | + +| 字符数 | 原方法 | 新方法(seek) | 新方法(read) | +| :-: | :-: | :-: | :-: | +| 240 | 13.09 | 6.50 | 159.28 | +| 227 | 16.05 | 8.22 | / | +| 767 | 内存溢出 | 内存溢出 | / | + +> 注:统计结果为**平均时间** + + +这里的字符数是包含了重复字符的总数,实际获取数据时是要去重的 + +读取速度还与字符在`索引表`中的相对位置有关,相对位置靠前的字符当然能更快被找到,反之则更慢 + +一次性读取太多的数据也会导致`内存溢出`,所以在实际使用时不建议一次性读取太多 + +手动调用垃圾回收(gc.collect())的时机一定要掌握好,并不是任何时候手动调用都能起到预期的作用,有时还会起到反作用 + +对于能够自动回收的,如函数内部的变量,可以省去手动调用的操作 + +> 统计运行时间使用的装饰器 + +```python +from utime import ticks_us, ticks_diff + +def cal_time(fn): + def wrapper(*args,**kwargs): + starTime = ticks_us() + f = fn(*args,**kwargs) + print('%s() runtime: %s ms' % (fn.__name__, ticks_diff(ticks_us(), starTime) / 1000)) + return f + return wrapper +``` + ### 合作交流 * 联系邮箱: diff --git a/client b/client index 6268505fcc031727afb3acf44ab76b7749c6c7f8..6fc042a8a592160263d12fb14e526706b46284c5 160000 --- a/client +++ b/client @@ -1 +1 @@ -Subproject commit 6268505fcc031727afb3acf44ab76b7749c6c7f8 +Subproject commit 6fc042a8a592160263d12fb14e526706b46284c5 diff --git a/fontlib.py b/fontlib.py index 3dab3580b175b08c240f35e4ee7538e6c0a73160..0cc04e63f0f91afb1f28f9ea269d2f4ee2f43537 100644 --- a/fontlib.py +++ b/fontlib.py @@ -82,7 +82,7 @@ class FontLib(object): with open(self.__font_filename, 'rb') as font_file: self.__header = FontLibHeader(memoryview(font_file.read(FontLibHeader.LENGTH))) - self.__placeholder_buffer = self.__get_character_unicode_buffer(font_file, {ord('?')})[ord('?')] + self.__placeholder_buffer = self.__get_character_unicode_buffer(font_file, {ord('?')}, True)[0][1] gc.collect() @@ -92,58 +92,91 @@ class FontLib(object): def __is_gb2312(self, char_code): return 0x80 <= char_code <= 0xffef - def __get_character_unicode_buffer(self, font_file, unicode_set): - buffer_list = {} + def __get_character_unicode_buffer(self, font_file, unicode_set, is_placeholder=False): + buffer_list = [] + ascii_list = [] + gb2312_list = [] + chunk_size = 1000 + + def __seek(offset, data, targets): + # target: + # 0: unicode + # 1: little endian bytes + # 2: charest index offset + seeked_count = 0 + for target in targets: + if target[2] is not None: + seeked_count += 1 + continue + + seek_offset = -1 + while True: + seek_offset = data.find(target[1], seek_offset + 1) + + if seek_offset >= 0: + if seek_offset % 2 == 0: + target[2] = seek_offset + offset + break + else: + continue + else: + break + + return seeked_count == len(targets) for unicode in unicode_set: if self.__is_ascii(unicode): char_offset = self.__header.ascii_start + (unicode - 0x20) * self.__header.data_size + ascii_list.append([unicode, char_offset]) elif self.__is_gb2312(unicode): - gb2312_index = struct.pack('= 0: - if seek_offset % 2 == 0: - return seek_offset - else: - continue - else: - return -1 + gb2312_list.append([unicode, struct.pack('= 0: - char_index_offset += offset - break - else: - buffer_list[unicode] = memoryview(self.__placeholder_buffer) - continue + if is_placeholder: + return buffer_list - char_offset = self.__header.gb2312_start + (char_index_offset - self.__header.index_table_address) / 2 * self.__header.data_size + if len(gb2312_list): + font_file.seek(self.__header.index_table_address) + for offset in range(self.__header.index_table_address, self.__header.ascii_start, chunk_size): + if __seek(offset, font_file.read(chunk_size), gb2312_list): + break else: - buffer_list[unicode] = memoryview(self.__placeholder_buffer) - continue + __seek(self.__header.ascii_start - offset, font_file.read(chunk_size), gb2312_list) - font_file.seek(int(char_offset)) - buffer_list[unicode] = memoryview(font_file.read(self.__header.data_size)) + for gb2312 in gb2312_list: + if gb2312[2] is None: + buffer_list.append([gb2312[0], memoryview(self.__placeholder_buffer)]) + else: + char_offset = int(self.__header.gb2312_start + (gb2312[2] - self.__header.index_table_address) / 2 * self.__header.data_size) - gc.collect() + font_file.seek(char_offset) + buffer_list.append([gb2312[0], memoryview(font_file.read(self.__header.data_size))]) + + gc.collect() + + del gb2312_list return buffer_list def get_characters(self, characters: str): + result = {} with open(self.__font_filename, 'rb') as font_file: unicode_set = set() for char in characters: unicode_set.add(ord(char)) - gc.collect() - return self.__get_character_unicode_buffer(font_file, unicode_set) + chunk = 30 + for count in range(0, len(unicode_set) // chunk + 1): + # result.append(self.__get_character_unicode_buffer(font_file, list(unicode_set)[count * chunk:count * chunk + chunk])) + for char in self.__get_character_unicode_buffer(font_file, list(unicode_set)[count * chunk:count * chunk + chunk]): + result[char[0]] = char[1] + + gc.collect() + return result @property def scan_mode(self): @@ -294,7 +327,7 @@ def run_test(): diff_time = ticks_diff(ticks_us(), start_time) / 1000 print('### show {} chars: {} ms, avg: {} ms'.format(len(chars), diff_time, diff_time / len(chars))) else: - buffer_dict = fontlib.get_characters('爱我,中华!Hello⒉あβǚㄘB⑴■☆') + buffer_dict = fontlib.get_characters('\ue900鼽爱我,中华!Hello⒉あβǚㄘB⑴■☆') buffer_list = [] for unicode, buffer in buffer_dict.items(): diff --git a/libs/fontlib.mpy b/libs/fontlib.mpy index 12188752e0aaa35c12a474f9fc241673174f8825..9c9c26c971b89d6206301dc2a3ba675904566efa 100644 Binary files a/libs/fontlib.mpy and b/libs/fontlib.mpy differ diff --git a/libs/fontlib.py b/libs/fontlib.py index 1e5e972195da7bd3e7b6bdf3557503f669f42e60..ed54eeec4f10f2aec88ec0ace751923636647985 100644 --- a/libs/fontlib.py +++ b/libs/fontlib.py @@ -61,9 +61,9 @@ class FontLib(object): with open(self.__font_filename, 'rb') as font_file: self.__header = FontLibHeader(memoryview(font_file.read(FontLibHeader.LENGTH))) - self.__placeholder_buffer = self.__get_character_unicode_buffer(font_file, {ord('?')})[ord('?')] + self.__placeholder_buffer = self.__get_character_unicode_buffer(font_file, {ord('?')}, True)[0][1] # [ord('?')] - gc.collect() + # gc.collect() def __is_ascii(self, char_code): return FontLib.ASCII_START <= char_code <= FontLib.ASCII_END @@ -72,58 +72,97 @@ class FontLib(object): return FontLib.GB2312_START <= char_code <= FontLib.GB2312_END # @micropython.native - def __get_character_unicode_buffer(self, font_file, unicode_set): - buffer_list = {} + def __get_character_unicode_buffer(self, font_file, unicode_set, is_placeholder=False): + buffer_list = [] + ascii_list = [] + gb2312_list = [] + chunk_size = const(1000) + + def __seek(offset, data, targets): + # target: + # 0: unicode + # 1: little endian bytes + # 2: charest index offset + seeked_count = 0 + for target in targets: + if target[2] is not None: + seeked_count += 1 + continue + + seek_offset = -1 + while True: + seek_offset = data.find(target[1], seek_offset + 1) + + if seek_offset >= 0: + if seek_offset % 2 == 0: + target[2] = seek_offset + offset + break + else: + continue + else: + break + + return seeked_count == len(targets) for unicode in unicode_set: + if unicode in (9, 10, 13): continue if self.__is_ascii(unicode): char_offset = self.__header.ascii_start + (unicode - FontLib.ASCII_START) * self.__header.data_size + ascii_list.append([unicode, char_offset]) elif self.__is_gb2312(unicode): - gb2312_index = struct.pack('= 0: - if seek_offset % 2 == 0: - return seek_offset - else: - continue - else: - return -1 + gb2312_list.append([unicode, struct.pack('= 0: - char_index_offset += offset - break - else: - buffer_list[unicode] = memoryview(self.__placeholder_buffer) - continue + for ascii in ascii_list: + font_file.seek(ascii[1]) + buffer_list.append([ascii[0], memoryview(font_file.read(self.__header.data_size))]) - char_offset = self.__header.gb2312_start + (char_index_offset - self.__header.index_table_address) / 2 * self.__header.data_size + if is_placeholder: + return buffer_list + + del ascii_list + + if len(gb2312_list): + font_file.seek(self.__header.index_table_address) + + for offset in range(self.__header.index_table_address, self.__header.ascii_start, chunk_size): + if __seek(offset, font_file.read(chunk_size), gb2312_list): + break else: - buffer_list[unicode] = memoryview(self.__placeholder_buffer) - continue + __seek(self.__header.ascii_start - offset, font_file.read(chunk_size), gb2312_list) - font_file.seek(int(char_offset)) - buffer_list[unicode] = memoryview(font_file.read(self.__header.data_size)) + for gb2312 in gb2312_list: + if gb2312[2] is None: + buffer_list.append([gb2312[0], memoryview(self.__placeholder_buffer)]) + else: + char_offset = int(self.__header.gb2312_start + (gb2312[2] - self.__header.index_table_address) / 2 * self.__header.data_size) - gc.collect() + font_file.seek(char_offset) + buffer_list.append([gb2312[0], memoryview(font_file.read(self.__header.data_size))]) + + gc.collect() + + del gb2312_list return buffer_list def get_characters(self, characters: str): + result = {} with open(self.__font_filename, 'rb') as font_file: unicode_set = set() for char in characters: unicode_set.add(ord(char)) - gc.collect() - return self.__get_character_unicode_buffer(font_file, unicode_set) + chunk = 30 + for count in range(0, len(unicode_set) // chunk + 1): + # result.append(self.__get_character_unicode_buffer(font_file, list(unicode_set)[count * chunk:count * chunk + chunk])) + for char in self.__get_character_unicode_buffer(font_file, list(unicode_set)[count * chunk:count * chunk + chunk]): + result[char[0]] = char[1] + + gc.collect() + return result @property def scan_mode(self): diff --git a/main.py b/main.py index 8e01c208275b65a23fdc941848011dd1cef113b7..04ce2806ec2ec87316d8704fd8054bc022cbe5f2 100644 --- a/main.py +++ b/main.py @@ -4,10 +4,12 @@ Copyright © 2021 Walkline Wang (https://walkline.wang) Gitee: https://gitee.com/walkline/micropython-new-fontlib """ from utime import ticks_us, ticks_diff, sleep -from machine import I2C, Pin +from machine import I2C, Pin, Timer from drivers.ssd1306 import SSD1306_I2C import framebuf from libs.fontlib import FontLib +import gc +import _thread class FontLibTest(object): @@ -25,7 +27,8 @@ class FontLibTest(object): def load_font(self, font_file): start_time = ticks_us() self.__fontlib = FontLib(font_file) - print('### load font file: {} ms'.format(ticks_diff(ticks_us(), start_time) / 1000)) + diff_time = ticks_diff(ticks_us(), start_time) / 1000 + print('### load font file: {} ms'.format(diff_time)) self.__fontlib.info() self.__font_width = self.__fontlib.font_height @@ -153,7 +156,7 @@ class FontLibTest(object): def __fill_buffer(self, buffer, x, y, format): if isinstance(buffer, (bytes, memoryview)): buffer = framebuf.FrameBuffer(bytearray(buffer), self.__font_width, self.__font_height, format) - oled.blit(buffer, x, y) + self.__oled.blit(buffer, x, y) class FontLibTest2(object): @@ -201,6 +204,204 @@ class FontLibTest2(object): oled.blit(buffer, x, y) +class FontLibTest3(object): + def __init__(self, oled=None): + self.__oled = oled + self.__oled_width = None + self.__oled_height = None + + if self.__oled: + self.__oled_width = self.__oled.width + self.__oled_height = self.__oled.height + + def load_font(self, font_file): + self.__fontlib = FontLib(font_file) + self.__fontlib.info() + + self.__font_width = self.__fontlib.font_height + self.__font_height = self.__fontlib.font_height + + def run_test(self, scroll_height=1, interval=20, chars=None, load_all=False, thread=False): + if self.__oled is None or chars is None: + return + + self.__scroll_speed = scroll_height + self.__scroll_interval = interval + self.__chars = chars.replace('\t', '').replace('\r\n', '\n') + self.__load_all = load_all + self.__thread = thread + + self.__setup() + self.__fill_page(2, True) + + self.__oled.blit(self.__fb_foreground, 0, 0) + self.__oled.show() + + self.__page_prepared = True + if self.__thread: + self.__need_next_page = True + _thread.start_new_thread(self.__fill_page_thread, ()) + else: + self.__fill_page() + + sleep(1) + + if self.__thread: + _thread.start_new_thread(self.__scroll_thread, ()) + else: + self.__scroll_timer.init( + mode=Timer.PERIODIC, + period=self.__scroll_interval, + callback=self.__scroll_cb + ) + + def __setup(self): + self.__chars_per_row = int(self.__oled_width / self.__fontlib.font_height) + self.__chars_per_col = int(self.__oled_height / self.__fontlib.font_height) + self.__chars_per_page = self.__chars_per_row * self.__chars_per_col + + self.__total_rows = int(len(self.__chars) / self.__chars_per_row) + self.__chars.count('\n') + self.__total_pages = int(self.__total_rows / self.__chars_per_col) + + self.__buffer_size = self.__oled_width // 8 * self.__oled_height + self.__fb_foreground = framebuf.FrameBuffer(bytearray(self.__buffer_size * 2), self.__oled_width, self.__oled_height * 2, framebuf.MONO_VLSB) + self.__fb_background = framebuf.FrameBuffer(bytearray(self.__buffer_size), self.__oled_width, self.__oled_height, framebuf.MONO_VLSB) + # self.__fb_temp = framebuf.FrameBuffer(bytearray(self.__buffer_size), self.__oled_width, self.__oled_height, framebuf.MONO_VLSB) + + self.__scroll_timer = Timer(1) + self.__buffer_dict = self.__fontlib.get_characters(self.__chars) if self.__load_all else {} + + self.__need_next_page = False + self.__page_prepared = False + self.__current_page = 0 + self.__x = self.__y = 0 + self.__current_char_index = 0 + + def __fill_buffer(self, buffer): + return framebuf.FrameBuffer(bytearray(buffer), self.__font_width, self.__font_height, framebuf.MONO_VLSB) + + def __fill_page(self, num=1, first=False): + x = y = 0 + while num: + col = 0 + current_page_chars = self.__chars[self.__current_char_index:self.__current_char_index + self.__chars_per_page] + + if not self.__load_all: + self.__buffer_dict = self.__fontlib.get_characters(current_page_chars) + + self.__fb_background.fill(0) + + for char in current_page_chars: + if ord(char) == 10: + x = 0 + y += self.__font_height + col += 1 + self.__current_char_index += 1 + continue + + if x > ((self.__oled_width // self.__font_width - 1) * self.__font_width): + x = 0 + y += self.__font_height + col += 1 + + if col >= self.__chars_per_col: + break + + # print(char, end='') + + buffer = self.__fill_buffer(memoryview(self.__buffer_dict[ord(char)])) + self.__fb_foreground.blit(buffer, x, y) if first else self.__fb_background.blit(buffer, x, y) + x += self.__font_width + self.__current_char_index += 1 + + num -= 1 + self.__current_page += 1 + self.__page_prepared = True + + def __scroll_cb(self, timer): + if self.__current_page > self.__total_pages: + self.__scroll_timer.deinit() + return + + if self.__y >= self.__oled_height: + if not self.__page_prepared: + return + + self.__fb_foreground.blit(self.__fb_background, 0, self.__oled_height) + # print('page ', self.__current_page, ' used') + + self.__page_prepared = False + self.__fill_page() + self.__x = self.__y = 0 + + self.__fb_foreground.scroll(0, self.__scroll_speed * -1) + self.__oled.blit(self.__fb_foreground, 0, 0) + self.__oled.show() + self.__y += self.__scroll_speed + + def __scroll_thread(self): + while self.__current_page <= self.__total_pages: + if self.__y >= self.__oled_height: + if not self.__page_prepared: + return + + self.__fb_foreground.blit(self.__fb_background, 0, self.__oled_height) + # print('page ', self.__current_page, ' used') + + self.__page_prepared = False + self.__need_next_page = True + self.__x = self.__y = 0 + self.__current_page += 1 + + self.__fb_foreground.scroll(0, self.__scroll_speed * -1) + self.__oled.blit(self.__fb_foreground, 0, 0) + self.__oled.show() + self.__y += self.__scroll_speed + + sleep(self.__scroll_interval / 1000) + + def __fill_page_thread(self): + while self.__current_page < self.__total_pages: + if self.__need_next_page: + # print('filling page ', self.__current_page) + col = x = y = 0 + current_page_chars = self.__chars[self.__current_char_index:self.__current_char_index + self.__chars_per_page] + + if not self.__load_all: + self.__buffer_dict = self.__fontlib.get_characters(current_page_chars) + + self.__fb_background.fill(0) + + for char in current_page_chars: + if ord(char) == 10: + x = 0 + y += self.__font_height + col += 1 + self.__current_char_index += 1 + continue + + if x > ((self.__oled_width // self.__font_width - 1) * self.__font_width): + x = 0 + y += self.__font_height + col += 1 + + if col >= self.__chars_per_col: + break + + # print(char, end='') + + buffer = self.__fill_buffer(memoryview(self.__buffer_dict[ord(char)])) + self.__fb_background.blit(buffer, x, y) + x += self.__font_width + self.__current_char_index += 1 + + # print('\npage: ', self.__current_page, ' filled') + self.__page_prepared = True + self.__need_next_page = False + + print('thread exit') + + chars =\ '''  清晨4:50,老刀穿过熙熙攘攘的步行街,去找彭蠡。   从垃圾站下班之后,老刀回家洗了个澡,换了衣服。白色衬衫和褐色裤子,这是他唯一一套体面衣服,衬衫袖口磨了边,他把袖子卷到胳膊肘。老刀四十八岁,没结婚,已经过了注意外表的年龄,又没人照顾起居,这一套衣服留着穿了很多年,每次穿一天,回家就脱了叠上。他在垃圾站上班,没必要穿得体面,偶尔参加谁家小孩的婚礼,才拿出来穿在身上。这一次他不想脏兮兮地见陌生人。他在垃圾站连续工作了五小时,很担心身上会有味道。''' @@ -216,6 +417,16 @@ chars2 =\   这似乎解答了我的疑惑。   这种事实对本人来说意义重大,相信对这个世界也是有一定意义的。''' +chars3 =\ +'''出师表 +  先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。 +  宫中府中,俱为一体;陟罚臧否,不宜异同:若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理;不宜偏私,使内外异法也。 +  侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下:愚以为宫中之事,事无大小,悉以咨之,然后施行,必能裨补阙漏,有所广益。 +  将军向宠,性行淑均,晓畅军事,试用于昔日,先帝称之曰“能”,是以众议举宠为督:愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。 +  亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。 +  臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间:尔来二十有一年矣。先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐托付不效,以伤先帝之明;故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。 +  愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏。臣不胜受恩感激。今当远离,临表涕零,不知所言。''' + if __name__ == '__main__': i2c = I2C(0, scl=Pin(18), sda=Pin(19)) @@ -243,5 +454,17 @@ if __name__ == '__main__': # $ FontMaker_Cli.exe -f 幼圆 --input input.txt -o welcome.bin # # 将生成的字库和 fonts/open-iconic.bin 一起上传到开发板 - runner = FontLibTest2(oled) - runner.run_test() + # runner = FontLibTest2(oled) + # runner.run_test() + + + runner = FontLibTest3(oled) + runner.load_font('client/wenqy_chushibiao.bin') + runner.run_test(scroll_height=1, interval=40, chars=chars3, thread=True) # 每次滚动 1 像素 + + # 读取所有字符数据,每次滚动 1 像素 + # runner = FontLibTest3(oled) + # runner.load_font('client/combined_vlsb.bin') + # runner.run_test(1, 20, chars2, True) + + gc.collect() diff --git a/test.txt b/test.txt index 0811fd808d3099789d97d9e87a77b22716f1cc9f..e5bb8dc4ddfa4a6dac1c6f8f1fb5a1958412889a 100644 --- a/test.txt +++ b/test.txt @@ -40,3 +40,118 @@ HZK Info: client/customize_hmsb.bin byte order : MSB characters : 1868 ### get 227 chars: 1239.848 ms, avg: 5.461885 ms + + + + + + +新方法,一次打开字库文件读取全部字模数据,使用read代替seek +__get_character_unicode_buffer() runtime: 32.91 ms +### load font file: 61.217 ms +HZK Info: //client//combined.bin + file size : 500024 + font height : 18 + data size : 54 + scan mode : Vertical + byte order : LSB + characters : 8932 + +__get_character_unicode_buffer() runtime: 37584.83 ms +### get 240 chars: 38228.77 ms, avg: 159.2866 ms + + +新方法,一次打开字库文件读取全部字模数据,使用seek +__get_character_unicode_buffer() runtime: 2.773 ms +### load font file: 30.97 ms +HZK Info: //client//combined.bin + file size : 500024 + font height : 18 + data size : 54 + scan mode : Vertical + byte order : LSB + characters : 8932 + +__get_character_unicode_buffer() runtime: 917.797 ms +### get 240 chars: 1561.768 ms, avg: 6.507367 ms +和 +__get_character_unicode_buffer() runtime: 2.726 ms +### load font file: 26.22 ms +HZK Info: //client//combined.bin + file size : 500024 + font height : 18 + data size : 54 + scan mode : Vertical + byte order : LSB + characters : 8932 + +Traceback (most recent call last): + File "", line 387, in + File "", line 304, in run_test + File "", line 178, in get_characters + File "", line 15, in wrapper +MemoryError: memory allocation failed, allocating 55 bytes +767 chars +和 +__get_character_unicode_buffer() runtime: 2.726 ms +### load font file: 26.17 ms +HZK Info: //client//combined.bin + file size : 500024 + font height : 18 + data size : 54 + scan mode : Vertical + byte order : LSB + characters : 8932 + +__get_character_unicode_buffer() runtime: 1134.455 ms +### get 227 chars: 1867.552 ms, avg: 8.227101 ms + + + + +原方法,逐字读取字模数据 +__get_character_unicode_buffer() runtime: 4.13 ms +### load font file: 27.516 ms +HZK Info: //client//combined.bin + file size : 500024 + font height : 18 + data size : 54 + scan mode : Vertical + byte order : LSB + characters : 8932 + +__get_character_unicode_buffer() runtime: 2912.698 ms +### get 227 chars: 3643.97 ms, avg: 16.05273 ms +和 +__get_character_unicode_buffer() runtime: 4.132 ms +### load font file: 27.536 ms +HZK Info: //client//combined.bin + file size : 500024 + font height : 18 + data size : 54 + scan mode : Vertical + byte order : LSB + characters : 8932 + +__get_character_unicode_buffer() runtime: 2504.442 ms +### get 240 chars: 3143.604 ms, avg: 13.09835 ms +和 +__get_character_unicode_buffer() runtime: 4.181 ms +### load font file: 27.623 ms +HZK Info: //client//combined.bin + file size : 500024 + font height : 18 + data size : 54 + scan mode : Vertical + byte order : LSB + characters : 8932 + +Traceback (most recent call last): + File "", line 365, in + File "", line 282, in run_test + File "", line 155, in get_characters + File "", line 15, in wrapper + File "", line 143, in __get_character_unicode_buffer +MemoryError: memory allocation failed, allocating 3112 bytes + +