Skip to content

Commit

Permalink
Оптимизация: переписаны функции, имеющие полиномиальную сложность (#194)
Browse files Browse the repository at this point in the history
Глобальная оптимизация (#255) выявила участки кода, имеющие сверхлинейную
зависимость по времени от входных данных. Если при компиляции отдельных
небольших файлов проблемы заметны не были, то теперь, на конкатенации
всех деревьев они встали в полный рост.

Часть кода удалось оптимизировать, заменив Map на MapAccum,
и соответственно, передавать константное значение не как параметр,
а через аккумулятор:

• FilterDeclaration в Desugaring.ref,
• GenCommand-Globals в Generator-RASL.ref

А некоторые функции пришлось переписать явно в линейные. Или, вернее,
«прямоугольные» O(m×n) вместо «квадратных» O(max(m,n)²):

• Переписана борьба с дублированием новых функций в прогонщике. Вместо
  DistinctFuncs, которая содержала две открытые переменные, делается
  два прохода по синтаксическому дереву: на первом все новые функции
  извлекаются (тут же исключается их дублирование), на втором удаляются
  те, которые в дереве уже присутствуют.
• Переписан проход Pass-RemoveRedundantDriveInline в рассахаривателе.
  В нём ранее при помощи двойной открытой переменной обнаруживались
  парные (избыточные) метки Drive/Inline, функция вызывалась до тех пор,
  пока все избыточные пары не будут разрешены. Теперь делается два
  прохода по дереву: сначала все метки извлекаются, а потом они
  фильтруются. Преобразование является точным рефакторингом — позиции
  оставленных меток сохраняются.

Формальных замеров я не делал, но цикл самоприменения с ключами -X-ODGS
ускорился примерно в два раза (если не больше).
  • Loading branch information
Mazdaywik committed May 16, 2020
1 parent 85f2f81 commit e6a0d05
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 62 deletions.
57 changes: 45 additions & 12 deletions src/compiler/Desugaring.ref
Original file line number Diff line number Diff line change
Expand Up @@ -192,17 +192,47 @@ Pass-AttachEntries {
}

Pass-RemoveRedundantDriveInline {
e.B (s.Label e.FuncName) e.M (s.Label e.FuncName) e.E
, <OneOf s.Label Drive Inline> : True
= <Pass-RemoveRedundantDriveInline e.B (s.Label e.FuncName) e.M e.E>;
e.AST
= <MapAccum
{
(e.Labels-B (e.Name s.KnownLabel) e.Labels-E) (Drive e.Name)
= (e.Labels-B (e.Name Drive) e.Labels-E)
(Drive e.Name);

(e.Labels-B (e.Name s.KnownLabel) e.Labels-E) (Inline e.Name)
= (e.Labels-B (e.Name s.KnownLabel) e.Labels-E)
(Inline e.Name);

e.B (Drive e.FuncName) e.M (Inline e.FuncName) e.E
= <Pass-RemoveRedundantDriveInline e.B (Drive e.FuncName) e.M e.E>;
(e.Labels) (Drive e.Name)
= (e.Labels (e.Name Drive)) (Drive e.Name);

(e.Labels) (Inline e.Name)
= (e.Labels (e.Name Inline)) (Inline e.Name);

(e.Labels) t.Other = (e.Labels) t.Other;
}
(/* labels */) e.AST
>
: (e.Labels) e.AST^

e.B (Inline e.FuncName) e.M (Drive e.FuncName) e.E
= <Pass-RemoveRedundantDriveInline e.B e.M (Drive e.FuncName) e.E>;
= <MapAccum
{
(e.Labels-B (e.Name s.Label) e.Labels-E) (s.Label e.Name)
= (e.Labels-B e.Labels-E) (s.Label e.Name);

(e.Labels-B (e.Name Drive) e.Labels-E) (Inline e.Name)
= (e.Labels-B (e.Name Drive) e.Labels-E) /* пропускаем */;

(e.Labels^) (Drive e.Name) = (e.Labels) /* пропускаем */;
(e.Labels^) (Inline e.Name) = (e.Labels) /* пропускаем */;

(e.Labels^) t.Other = (e.Labels) t.Other;
}
(e.Labels) e.AST
>
: () e.AST^

e.AST = e.AST;
= e.AST;
}

Pass-EnumerateVariables {
Expand Down Expand Up @@ -888,15 +918,18 @@ Pass-CleanupRedudandExterns {
e.AST
>
: (e.DefinedFunctions) e.AST^
= <Map (&FilterDeclarations e.DefinedFunctions) e.AST>;
= <MapAccum &FilterDeclarations (e.DefinedFunctions) e.AST>
: (e.DefinedFunctions^) e.AST^
= e.AST;
}

FilterDeclarations {
e.DefinedFunctions-B (e.Name) e.DefinedFunctions-E
(e.DefinedFunctions-B (e.Name) e.DefinedFunctions-E)
(Declaration s.ScopeClass e.Name)
= /* пусто */;
= (e.DefinedFunctions-B (e.Name) e.DefinedFunctions-E)
/* пусто */;

e.DefinedFunctions t.OtherItem = t.OtherItem;
(e.DefinedFunctions) t.OtherItem = (e.DefinedFunctions) t.OtherItem;
}

Pass-UnfoldEnums {
Expand Down
58 changes: 33 additions & 25 deletions src/compiler/Generator-RASL.ref
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ $ENTRY GenProgram-RASL {
e.StringsAsBytes
<Map &UnBracket e.RASLAsWords>
>
<Map (&GenCommand-Globals e.LabelOffsets) e.Items>;
<DelAccumulator
<MapAccum &GenCommand-Globals (e.LabelOffsets) e.Items>
>
}

BytesFromFunctionList {
Expand Down Expand Up @@ -132,45 +134,51 @@ NameWithSign-Bytes {
}

GenCommand-Globals {
e.Labels (UnitName e.SrcName) =
<PutBlock UnitName <Asciiz e.SrcName>>;

e.Labels (CmdEnumDescr s.ScopeClass e.Name) =
<PutBlock EmptyFunction <NameWithSign-Bytes s.ScopeClass e.Name>>;

e.Labels-B (s.Label s.Offset) e.Labels-E
(CmdInterpretFuncDescr s.ScopeClass e.Name s.Label) =
<PutBlock
RefalFunction
<NameWithSign-Bytes s.ScopeClass e.Name>
<PutWordLE s.Offset>
>;
(e.Labels) (UnitName e.SrcName)
= (e.Labels) <PutBlock UnitName <Asciiz e.SrcName>>;

(e.Labels) (CmdEnumDescr s.ScopeClass e.Name)
= (e.Labels) <PutBlock EmptyFunction <NameWithSign-Bytes s.ScopeClass e.Name>>;

(e.Labels-B (s.Label s.Offset) e.Labels-E)
(CmdInterpretFuncDescr s.ScopeClass e.Name s.Label)
= (e.Labels-B (s.Label s.Offset) e.Labels-E)
<PutBlock
RefalFunction
<NameWithSign-Bytes s.ScopeClass e.Name>
<PutWordLE s.Offset>
>;

e.Labels (CmdMetatable s.ScopeClass (e.Name) e.Table)
(e.Labels) (CmdMetatable s.ScopeClass (e.Name) e.Table)
= <Lenw e.Table> : s.Count e.Table^
= <PutBlock
= (e.Labels)
<PutBlock
Metatable
<NameWithSign-Bytes s.ScopeClass e.Name>
<PutWordLE s.Count>
<Map
{
(s.Ident s.Function) = <PutWordLE s.Ident> <PutWordLE s.Function>;
(s.Ident s.Function)
= <PutWordLE s.Ident> <PutWordLE s.Function>;
}
e.Table
>
>;

e.Labels (CmdSwapDescr s.ScopeClass e.Name) =
<PutBlock Swap <NameWithSign-Bytes s.ScopeClass e.Name>>;
(e.Labels) (CmdSwapDescr s.ScopeClass e.Name)
= (e.Labels) <PutBlock Swap <NameWithSign-Bytes s.ScopeClass e.Name>>;

e.Labels (CmdConditionFuncDecsrRasl s.ScopeClass e.Name) =
<PutBlock ConditionRasl <NameWithSign-Bytes s.ScopeClass e.Name>>;
(e.Labels) (CmdConditionFuncDecsrRasl s.ScopeClass e.Name)
= (e.Labels)
<PutBlock ConditionRasl <NameWithSign-Bytes s.ScopeClass e.Name>>;

e.Labels (CmdConditionFuncDecsrNative s.ScopeClass e.Name) =
<PutBlock ConditionNative <NameWithSign-Bytes s.ScopeClass e.Name>>;
(e.Labels) (CmdConditionFuncDecsrNative s.ScopeClass e.Name)
= (e.Labels)
<PutBlock ConditionNative <NameWithSign-Bytes s.ScopeClass e.Name>>;

e.Labels (CmdNativeFuncDescr s.ScopeClass e.Name) =
<PutBlock NativeFunction <NameWithSign-Bytes s.ScopeClass e.Name>>;
(e.Labels) (CmdNativeFuncDescr s.ScopeClass e.Name)
= (e.Labels)
<PutBlock NativeFunction <NameWithSign-Bytes s.ScopeClass e.Name>>;
}

Assemble {
Expand Down
56 changes: 31 additions & 25 deletions src/compiler/OptTree-Drive.ref
Original file line number Diff line number Diff line change
Expand Up @@ -168,32 +168,38 @@ DriveInlineOptimizerTick {
e.AST
>
: (e.OptInfo) e.AST^
= (DriveInfo e.OptInfo) <DistinctFuncs e.AST>
}

DistinctFuncs {
e.AST
= <DistinctFuncs-Aux ColdFunction e.AST> : e.AST^
= <DistinctFuncs-Aux Function e.AST>;
}

$SPEC DistinctFuncs-Aux s.TAG e.ast;

DistinctFuncs-Aux {
s.FunctionTag
e.AST-B
(s.FunctionTag s.ScopeClass (e.Name) e.Body1)
e.AST-M
(Function s.ScopeClass (e.Name) e.Body2)
e.AST-E
= e.AST-B
<DistinctFuncs-Aux
s.FunctionTag
(s.FunctionTag s.ScopeClass (e.Name) e.Body1)
e.AST-M e.AST-E
>;
= <MapAccum
{
(e.News-B (Function s.ScopeClass (e.Name) e.Body) e.News-E)
(NewFunction s.ScopeClass (e.Name) e._)
= (e.News-B (Function s.ScopeClass (e.Name) e.Body) e.News-E)
/* пропускаем */;

(e.NewFunctions) (NewFunction s.ScopeClass (e.Name) e.Body)
= (e.NewFunctions (Function s.ScopeClass (e.Name) e.Body));

(e.NewFunctions) t.Other = (e.NewFunctions) t.Other;
}
(/* new functions */) e.AST
>
: (e.NewFunctions) e.AST^

= <MapAccum
{
(e.News-B (Function s.ScopeClass (e.Name) e._) e.News-E)
(s.Function s.ScopeClass (e.Name) e.Body)
, <OneOf s.Function Function ColdFunction> : True
= (e.News-B e.News-E)
(s.Function s.ScopeClass (e.Name) e.Body);

(e.NewFunctions^) t.Other = (e.NewFunctions) t.Other;
}
(e.NewFunctions) e.AST
>
: (e.NewFunctions^) e.AST^

s.FunctionTag e.AST = e.AST
= (DriveInfo e.OptInfo) e.AST e.NewFunctions;
}

IsPassiveCall {
Expand Down Expand Up @@ -366,7 +372,7 @@ MakeColdSolution {
= (
((ColdCallBrackets (Symbol Name e.Name) e.Args))
((/* нет присваиваний */) (/* нет сужений */))
((Function s.ScopeClass (e.Name) Sentences e.Body))
((NewFunction s.ScopeClass (e.Name) Sentences e.Body))
);

(s.FuncMode s.ScopeClass (e.Name) Sentences e.Body) e.Args
Expand Down

0 comments on commit e6a0d05

Please sign in to comment.