Made some effort at reducing memory use. Implemented #54
This commit is contained in:
parent
41dbdaed4a
commit
cc49cef4c7
73
actypes.d
73
actypes.d
|
@ -98,6 +98,23 @@ public:
|
||||||
return this.opCmp(other.name);
|
return this.opCmp(other.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all parts whose name matches the given string.
|
||||||
|
*/
|
||||||
|
const(ACSymbol)*[] getPartsByName(string name) const
|
||||||
|
{
|
||||||
|
return cast(typeof(return)) parts.filter!(a => a.name == name).array;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t estimateMemory(size_t runningTotal) const
|
||||||
|
{
|
||||||
|
runningTotal = runningTotal + name.length + callTip.length
|
||||||
|
+ ACSymbol.sizeof;
|
||||||
|
foreach (part; parts)
|
||||||
|
runningTotal = part.estimateMemory(runningTotal);
|
||||||
|
return runningTotal;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Symbols that compose this symbol, such as enum members, class variables,
|
* Symbols that compose this symbol, such as enum members, class variables,
|
||||||
* methods, etc.
|
* methods, etc.
|
||||||
|
@ -109,15 +126,25 @@ public:
|
||||||
*/
|
*/
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calltip to display if this is a function
|
||||||
|
*/
|
||||||
|
string callTip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module containing the symbol.
|
||||||
|
*/
|
||||||
|
string symbolFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The symbol that represents the type.
|
* The symbol that represents the type.
|
||||||
*/
|
*/
|
||||||
const(ACSymbol)* type;
|
const(ACSymbol)* type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calltip to display if this is a function
|
* Symbol location
|
||||||
*/
|
*/
|
||||||
string callTip;
|
size_t location;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The kind of symbol
|
* The kind of symbol
|
||||||
|
@ -128,24 +155,6 @@ public:
|
||||||
* Symbol qualifier
|
* Symbol qualifier
|
||||||
*/
|
*/
|
||||||
SymbolQualifier qualifier;
|
SymbolQualifier qualifier;
|
||||||
|
|
||||||
/**
|
|
||||||
* Symbol location
|
|
||||||
*/
|
|
||||||
size_t location;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Module containing the symbol.
|
|
||||||
*/
|
|
||||||
string symbolFile;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all parts whose name matches the given string.
|
|
||||||
*/
|
|
||||||
const(ACSymbol)*[] getPartsByName(string name) const
|
|
||||||
{
|
|
||||||
return cast(typeof(return)) parts.filter!(a => a.name == name).array;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Scope
|
struct Scope
|
||||||
|
@ -318,6 +327,28 @@ static this()
|
||||||
builtinSymbols = [bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_,
|
builtinSymbols = [bool_, int_, long_, byte_, char_, dchar_, short_, ubyte_, uint_,
|
||||||
ulong_, ushort_, wchar_, cdouble_, cent_, cfloat_, creal_, double_,
|
ulong_, ushort_, wchar_, cdouble_, cent_, cfloat_, creal_, double_,
|
||||||
float_, idouble_, ifloat_, ireal_, real_, ucent_, void_];
|
float_, idouble_, ifloat_, ireal_, real_, ucent_, void_];
|
||||||
|
|
||||||
|
// _argptr has type void*
|
||||||
|
argptrType = new Type;
|
||||||
|
argptrType.type2 = new Type2;
|
||||||
|
argptrType.type2.builtinType = TokenType.void_;
|
||||||
|
TypeSuffix argptrTypeSuffix = new TypeSuffix;
|
||||||
|
argptrTypeSuffix.star = true;
|
||||||
|
argptrType.typeSuffixes ~= argptrTypeSuffix;
|
||||||
|
|
||||||
|
// _arguments has type TypeInfo[]
|
||||||
|
argumentsType = new Type;
|
||||||
|
argumentsType = new Type;
|
||||||
|
argumentsType.type2 = new Type2;
|
||||||
|
argumentsType.type2.symbol = new Symbol;
|
||||||
|
argumentsType.type2.symbol.identifierOrTemplateChain = new IdentifierOrTemplateChain;
|
||||||
|
IdentifierOrTemplateInstance i = new IdentifierOrTemplateInstance;
|
||||||
|
i.identifier.value = "TypeInfo";
|
||||||
|
i.identifier.type = TokenType.identifier;
|
||||||
|
argumentsType.type2.symbol.identifierOrTemplateChain.identifiersOrTemplateInstances ~= i;
|
||||||
|
TypeSuffix argumentsTypeSuffix = new TypeSuffix;
|
||||||
|
argumentsTypeSuffix.array = true;
|
||||||
|
argumentsType.typeSuffixes ~= argptrTypeSuffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
const(ACSymbol)*[] builtinSymbols;
|
const(ACSymbol)*[] builtinSymbols;
|
||||||
|
@ -325,3 +356,5 @@ const(ACSymbol)*[] arraySymbols;
|
||||||
const(ACSymbol)*[] assocArraySymbols;
|
const(ACSymbol)*[] assocArraySymbols;
|
||||||
const(ACSymbol)*[] classSymbols;
|
const(ACSymbol)*[] classSymbols;
|
||||||
const(ACSymbol)*[] structSymbols;
|
const(ACSymbol)*[] structSymbols;
|
||||||
|
Type argptrType;
|
||||||
|
Type argumentsType;
|
||||||
|
|
|
@ -62,6 +62,19 @@ final class FirstPass : ASTVisitor
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
visit(mod);
|
visit(mod);
|
||||||
|
mod = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
override void visit(Unittest u)
|
||||||
|
{
|
||||||
|
// Create a dummy symbol because we don't want unit test symbols leaking
|
||||||
|
// into the symbol they're declared in.
|
||||||
|
SemanticSymbol* s = new SemanticSymbol("*unittest*",
|
||||||
|
CompletionKind.dummy, null, 0);
|
||||||
|
s.parent = currentSymbol;
|
||||||
|
currentSymbol = s;
|
||||||
|
u.accept(this);
|
||||||
|
currentSymbol = s.parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
override void visit(Constructor con)
|
override void visit(Constructor con)
|
||||||
|
@ -388,6 +401,20 @@ private:
|
||||||
symbol.addChild(parameter);
|
symbol.addChild(parameter);
|
||||||
parameter.parent = symbol;
|
parameter.parent = symbol;
|
||||||
}
|
}
|
||||||
|
if (parameters.hasVarargs)
|
||||||
|
{
|
||||||
|
SemanticSymbol* argptr = new SemanticSymbol("_argptr",
|
||||||
|
CompletionKind.variableName, null, 0);
|
||||||
|
argptr.type = argptrType;
|
||||||
|
argptr.parent = symbol;
|
||||||
|
symbol.addChild(argptr);
|
||||||
|
|
||||||
|
SemanticSymbol* arguments = new SemanticSymbol("_arguments",
|
||||||
|
CompletionKind.variableName, null, 0);
|
||||||
|
arguments.type = argumentsType;
|
||||||
|
arguments.parent = symbol;
|
||||||
|
symbol.addChild(arguments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
symbol.acSymbol.callTip = formatCallTip(returnType, functionName,
|
symbol.acSymbol.callTip = formatCallTip(returnType, functionName,
|
||||||
parameters);
|
parameters);
|
||||||
|
@ -695,22 +722,29 @@ const(ACSymbol)*[] convertAstToSymbols(Module m, string symbolFile)
|
||||||
{
|
{
|
||||||
FirstPass first = new FirstPass(m, symbolFile);
|
FirstPass first = new FirstPass(m, symbolFile);
|
||||||
first.run();
|
first.run();
|
||||||
|
|
||||||
SecondPass second = SecondPass(first.rootSymbol, first.moduleScope);
|
SecondPass second = SecondPass(first.rootSymbol, first.moduleScope);
|
||||||
second.run();
|
second.run();
|
||||||
|
|
||||||
ThirdPass third = ThirdPass(second.rootSymbol, second.moduleScope);
|
ThirdPass third = ThirdPass(second.rootSymbol, second.moduleScope);
|
||||||
third.run();
|
third.run();
|
||||||
|
|
||||||
return cast(typeof(return)) third.rootSymbol.acSymbol.parts;
|
return cast(typeof(return)) third.rootSymbol.acSymbol.parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
const(Scope)* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile)
|
const(Scope)* generateAutocompleteTrees(const(Token)[] tokens, string symbolFile)
|
||||||
{
|
{
|
||||||
Module m = parseModule(tokens, null);
|
Module m = parseModule(tokens, null);
|
||||||
|
|
||||||
FirstPass first = new FirstPass(m, symbolFile);
|
FirstPass first = new FirstPass(m, symbolFile);
|
||||||
first.run();
|
first.run();
|
||||||
|
|
||||||
SecondPass second = SecondPass(first.rootSymbol, first.currentScope);
|
SecondPass second = SecondPass(first.rootSymbol, first.currentScope);
|
||||||
second.run();
|
second.run();
|
||||||
|
|
||||||
ThirdPass third = ThirdPass(second.rootSymbol, second.moduleScope);
|
ThirdPass third = ThirdPass(second.rootSymbol, second.moduleScope);
|
||||||
third.run();
|
third.run();
|
||||||
|
|
||||||
return cast(typeof(return)) third.moduleScope;
|
return cast(typeof(return)) third.moduleScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,7 +765,7 @@ string[] iotcToStringArray(const IdentifierOrTemplateChain iotc)
|
||||||
|
|
||||||
private static string convertChainToImportPath(IdentifierChain chain)
|
private static string convertChainToImportPath(IdentifierChain chain)
|
||||||
{
|
{
|
||||||
return to!string(chain.identifiers.map!(a => a.value.dup).join(dirSeparator).array) ~ ".d";
|
return to!string(chain.identifiers.map!(a => a.value).join(dirSeparator).array) ~ ".d";
|
||||||
}
|
}
|
||||||
|
|
||||||
version(unittest) Module parseTestCode(string code)
|
version(unittest) Module parseTestCode(string code)
|
||||||
|
|
4
build.sh
4
build.sh
|
@ -2,6 +2,10 @@ dmd -wi client.d\
|
||||||
messages.d\
|
messages.d\
|
||||||
msgpack-d/src/msgpack.d\
|
msgpack-d/src/msgpack.d\
|
||||||
-Imsgpack-d/src\
|
-Imsgpack-d/src\
|
||||||
|
-release\
|
||||||
|
-inline\
|
||||||
|
-noboundscheck\
|
||||||
|
-O\
|
||||||
-ofdcd-client
|
-ofdcd-client
|
||||||
|
|
||||||
dmd \
|
dmd \
|
||||||
|
|
|
@ -60,6 +60,18 @@ struct ModuleCache
|
||||||
cache = cache.init;
|
cache = cache.init;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void estimateMemory()
|
||||||
|
{
|
||||||
|
size_t estimate = 0;
|
||||||
|
foreach (c; cache)
|
||||||
|
{
|
||||||
|
foreach (symbol; c.symbols)
|
||||||
|
estimate = symbol.estimateMemory(estimate);
|
||||||
|
}
|
||||||
|
double megabytes = estimate / (1024.0F * 1024.0F);
|
||||||
|
Log.info("Memory use estimated at ", megabytes, " megabytes");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the given path to the list of directories checked for imports
|
* Adds the given path to the list of directories checked for imports
|
||||||
*/
|
*/
|
||||||
|
@ -78,7 +90,6 @@ struct ModuleCache
|
||||||
{
|
{
|
||||||
foreach (fileName; dirEntries(path, "*.{d,di}", SpanMode.depth))
|
foreach (fileName; dirEntries(path, "*.{d,di}", SpanMode.depth))
|
||||||
{
|
{
|
||||||
Log.info("Loading and caching completions for ", fileName);
|
|
||||||
getSymbolsInModule(fileName);
|
getSymbolsInModule(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +103,7 @@ struct ModuleCache
|
||||||
*/
|
*/
|
||||||
static const(ACSymbol)*[] getSymbolsInModule(string moduleName)
|
static const(ACSymbol)*[] getSymbolsInModule(string moduleName)
|
||||||
{
|
{
|
||||||
// Log.info("Getting symbols for module ", moduleName);
|
|
||||||
string location = resolveImportLoctation(moduleName);
|
string location = resolveImportLoctation(moduleName);
|
||||||
if (location is null)
|
if (location is null)
|
||||||
return [];
|
return [];
|
||||||
|
@ -104,6 +115,8 @@ struct ModuleCache
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.info("Getting symbols for module ", moduleName);
|
||||||
|
|
||||||
recursionGuard[location] = true;
|
recursionGuard[location] = true;
|
||||||
|
|
||||||
const(ACSymbol)*[] symbols;
|
const(ACSymbol)*[] symbols;
|
||||||
|
@ -131,9 +144,6 @@ struct ModuleCache
|
||||||
CacheEntry c = CacheEntry(symbols, modification);
|
CacheEntry c = CacheEntry(symbols, modification);
|
||||||
cache[location] = c;
|
cache[location] = c;
|
||||||
recursionGuard[location] = false;
|
recursionGuard[location] = false;
|
||||||
import core.memory;
|
|
||||||
GC.collect();
|
|
||||||
GC.minimize();
|
|
||||||
return symbols;
|
return symbols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,11 +42,6 @@ public:
|
||||||
acSymbol.symbolFile = symbolFile;
|
acSymbol.symbolFile = symbolFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
Log.trace(acSymbol.name, " destructor");
|
|
||||||
}
|
|
||||||
|
|
||||||
void addChild(SemanticSymbol* child)
|
void addChild(SemanticSymbol* child)
|
||||||
{
|
{
|
||||||
children ~= child;
|
children ~= child;
|
||||||
|
|
3
server.d
3
server.d
|
@ -98,6 +98,7 @@ int main(string[] args)
|
||||||
|
|
||||||
sw.stop();
|
sw.stop();
|
||||||
Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds");
|
Log.info("Startup completed in ", sw.peek().to!("msecs", float), " milliseconds");
|
||||||
|
ModuleCache.estimateMemory();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -114,8 +115,6 @@ int main(string[] args)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Only process connections from localhost
|
|
||||||
|
|
||||||
scope (exit)
|
scope (exit)
|
||||||
{
|
{
|
||||||
s.shutdown(SocketShutdown.BOTH);
|
s.shutdown(SocketShutdown.BOTH);
|
||||||
|
|
Loading…
Reference in New Issue