Made some effort at reducing memory use. Implemented #54

This commit is contained in:
Hackerpilot 2013-10-13 23:23:31 +00:00
parent 41dbdaed4a
commit cc49cef4c7
6 changed files with 108 additions and 33 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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 \

View File

@ -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;
} }

View File

@ -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;

View File

@ -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);