我正在解析一个相当简单的文件格式,它由一系列行组成,每一行都有一些用空格分隔的字段,看起来像这样:
l 0x9823 1
s 0x1111 3
l 0x1111 12
⋮
我正在使用SWI-Prolog。这是我目前的DCG:
:- consult(library(pure_input)).
load_trace(Filename, Traces) :-
phrase_from_file(trace_file_phrase(Traces), Filename).
trace_file_phrase([]) --> [].
trace_file_phrase([T|Ts]) --> trace_phrase(T), trace_file_phrase(Ts).
trace_phrase(access(Type, Address, SinceLast)) -->
access_type(Type), space,
address(Address), space,
nat(SinceLast), newline.
access_type(load) --> "l".
access_type(store) --> "s".
address(Number) --> "0x", hexnum(Number).
hexdigit(N) --> digit(N).
hexdigit(10) --> "a". hexdigit(11) --> "b". hexdigit(12) --> "c".
hexdigit(13) --> "d". hexdigit(14) --> "e". hexdigit(15) --> "f".
hexnum(N) --> hexdigit(D), hexnum(D, N).
hexnum(N, N) --> [].
hexnum(A, N) --> hexdigit(D), { A1 is A*16 + D }, hexnum(A1, N).
newline --> "\n".
space --> " ".
%% the following two productions are courtesy of Lars Mans at
%% https://dev59.com/13A75IYBdhLWcg3weY1f
digit(0) --> "0". digit(1) --> "1". digit(2) --> "2".
digit(3) --> "3". digit(4) --> "4". digit(5) --> "5".
digit(6) --> "6". digit(7) --> "7". digit(8) --> "8".
digit(9) --> "9".
nat(N) --> digit(D), nat(D,N).
nat(N,N) --> [].
nat(A,N) --> digit(D), { A1 is A*10 + D }, nat(A1, N).
正如评论中提到的,我从在Prolog中解析具有多个数字的数字中借鉴了数字处理。
我遇到的问题是其中一些文件很大,比如5-10 MB。 SWI-Prolog中的默认堆栈不足以处理这个问题,并且解析这些文件需要相当长的时间,大约为5-15秒。 我有几个关于这种情况的问题:
- 这段代码的效率问题在哪里? 我认为可能在
trace_file_phrase//1
或nat//1
中,但这只是猜测。 - 如果问题在于列表,那么是否有比这更好的处理DCG的列表的方法?
- 一般来说,如何诊断和处理此类DCG的性能问题?
nat/2
看起来有点晦涩。你能详细说明一下我需要做什么来解决这个问题吗?我不太担心那个规则变得晦涩,因为它可以被隔离在其他模块中,不会干扰我的“纯净小规范”——如果感染不会蔓延的话。 - Daniel Lyons