Skip to content

Commit 5ea2056

Browse files
committed
Merge pull request #376 from Azure/master
Fix #367 & Support IdlePageOut
2 parents ca16eff + b6c5e20 commit 5ea2056

19 files changed

+367
-6
lines changed

src/config/iisnode_dev_x64.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
5959
<attribute name="promoteServerVars" type="string" defaultValue=""/>
6060
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
6161
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
62+
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
6263
</sectionSchema>
6364
</configSchema>

src/config/iisnode_dev_x86_on_x64.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
5959
<attribute name="promoteServerVars" type="string" defaultValue=""/>
6060
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
6161
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
62+
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
6263
</sectionSchema>
6364
</configSchema>

src/config/iisnode_dev_x86_on_x86.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
5959
<attribute name="promoteServerVars" type="string" defaultValue=""/>
6060
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
6161
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
62+
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
6263
</sectionSchema>
6364
</configSchema>

src/config/iisnode_express_schema.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
5959
<attribute name="promoteServerVars" type="string" defaultValue=""/>
6060
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
6161
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
62+
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
6263
</sectionSchema>
6364
</configSchema>

src/config/iisnode_express_schema_x64.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
5959
<attribute name="promoteServerVars" type="string" defaultValue=""/>
6060
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
6161
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
62+
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
6263
</sectionSchema>
6364
</configSchema>

src/config/iisnode_schema.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
5959
<attribute name="promoteServerVars" type="string" defaultValue=""/>
6060
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
6161
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
62+
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
6263
</sectionSchema>
6364
</configSchema>

src/config/iisnode_schema_x64.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,6 @@ Details at http://learn.iis.net/page.aspx/241/configuration-extensibility/
5959
<attribute name="promoteServerVars" type="string" defaultValue=""/>
6060
<attribute name="configOverrides" type="string" expanded="true" defaultValue="iisnode.yml"/>
6161
<attribute name="recycleSignalEnabled" type="bool" defaultValue="false"/>
62+
<attribute name="idlePageOutTimePeriod" type="uint" defaultValue="0" /> <!-- disabled with default value 0 -->
6263
</sectionSchema>
6364
</configSchema>

src/iisnode/cmoduleconfiguration.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ CModuleConfiguration::CModuleConfiguration()
3232
debuggerVirtualDirLength(0),
3333
debuggerVirtualDirPhysicalPath(NULL),
3434
recycleSignalEnabled(FALSE),
35-
debuggerExtensionDll(NULL)
35+
debuggerExtensionDll(NULL),
36+
idlePageOutTimePeriod(0)
3637
{
3738
InitializeSRWLock(&this->srwlock);
3839
}
@@ -865,6 +866,10 @@ HRESULT CModuleConfiguration::ApplyConfigOverrideKeyValue(IHttpContext* context,
865866
{
866867
CheckError(GetString(valueStart, &config->interceptor, TRUE));
867868
}
869+
else if(0 == stricmp(keyStart, "idlePageOutTimePeriod"))
870+
{
871+
CheckError(GetDWORD(valueStart, &config->idlePageOutTimePeriod));
872+
}
868873

869874
return S_OK;
870875
Error:
@@ -1223,6 +1228,7 @@ HRESULT CModuleConfiguration::GetConfig(IHttpContext* context, CModuleConfigurat
12231228
CheckError(GetString(section, L"configOverrides", &c->configOverrides));
12241229
CheckError(GetString(section, L"nodeProcessCommandLine", &c->nodeProcessCommandLine));
12251230
CheckError(GetString(section, L"interceptor", &c->interceptor));
1231+
CheckError(GetDWORD(section, L"idlePageOutTimePeriod", &c->idlePageOutTimePeriod));
12261232

12271233
// debuggerPathSegment
12281234

@@ -1299,6 +1305,11 @@ LPWSTR CModuleConfiguration::GetNodeProcessCommandLine(IHttpContext* ctx)
12991305
GETCONFIG(nodeProcessCommandLine)
13001306
}
13011307

1308+
DWORD CModuleConfiguration::GetIdlePageOutTimePeriod(IHttpContext* ctx)
1309+
{
1310+
GETCONFIG(idlePageOutTimePeriod)
1311+
}
1312+
13021313
LPWSTR CModuleConfiguration::GetInterceptor(IHttpContext* ctx)
13031314
{
13041315
GETCONFIG(interceptor)

src/iisnode/cmoduleconfiguration.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class CModuleConfiguration : public IHttpStoredContext
2828
DWORD maxLogFiles;
2929
BOOL loggingEnabled;
3030
BOOL debuggingEnabled;
31+
DWORD idlePageOutTimePeriod;
3132
PWSTR debuggerExtensionDll;
3233
BOOL debugHeaderEnabled;
3334
BOOL recycleSignalEnabled;
@@ -90,6 +91,7 @@ class CModuleConfiguration : public IHttpStoredContext
9091

9192
static HRESULT GetConfig(IHttpContext* context, CModuleConfiguration** config);
9293

94+
static DWORD GetIdlePageOutTimePeriod(IHttpContext* ctx);
9395
static DWORD GetAsyncCompletionThreadCount(IHttpContext* ctx);
9496
static DWORD GetNodeProcessCountPerApplication(IHttpContext* ctx);
9597
static LPWSTR GetNodeProcessCommandLine(IHttpContext* ctx);

src/iisnode/cnodeapplication.cpp

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,50 @@
11
#include "precomp.h"
22

3+
volatile DWORD CNodeApplication::dwInternalAppId = 0;
4+
35
CNodeApplication::CNodeApplication(CNodeApplicationManager* applicationManager, BOOL isDebugger, NodeDebugCommand debugCommand, DWORD debugPort)
46
: applicationManager(applicationManager), scriptName(NULL), processManager(NULL),
57
isDebugger(isDebugger), peerApplication(NULL), debugCommand(debugCommand),
6-
debugPort(debugPort), needsRecycling(FALSE), configPath(NULL)
8+
debugPort(debugPort), needsRecycling(FALSE), configPath(NULL), pIdleTimer(NULL),
9+
fIdleCallbackInProgress(FALSE), fRequestsProcessedInLastIdleTimeoutPeriod(FALSE),
10+
fEmptyWorkingSetAtStart(FALSE), dwIdlePageOutTimePeriod(0)
11+
{
12+
}
13+
14+
VOID
15+
CALLBACK
16+
CNodeApplication::IdleTimerCallback(
17+
IN PTP_CALLBACK_INSTANCE Instance,
18+
IN PVOID Context,
19+
IN PTP_TIMER Timer
20+
)
721
{
22+
CNodeApplication* pApplication = (CNodeApplication*) Context;
23+
if(pApplication != NULL)
24+
{
25+
if(!pApplication->fIdleCallbackInProgress)
26+
{
27+
pApplication->fIdleCallbackInProgress = TRUE;
28+
29+
if(!pApplication->fRequestsProcessedInLastIdleTimeoutPeriod || !pApplication->fEmptyWorkingSetAtStart)
30+
{
31+
pApplication->fEmptyWorkingSetAtStart = TRUE;
32+
pApplication->EmptyWorkingSet();
33+
if( pApplication->fEmptyW3WPWorkingSet )
34+
{
35+
SetProcessWorkingSetSize(GetCurrentProcess(), -1, -1);
36+
}
37+
}
38+
39+
pApplication->fRequestsProcessedInLastIdleTimeoutPeriod = FALSE;
40+
41+
if(pApplication->pIdleTimer != NULL)
42+
{
43+
pApplication->pIdleTimer->SetTimer(pApplication->dwIdlePageOutTimePeriod, 0);
44+
}
45+
}
46+
pApplication->fIdleCallbackInProgress = FALSE;
47+
}
848
}
949

1050
CNodeApplication::~CNodeApplication()
@@ -14,6 +54,13 @@ CNodeApplication::~CNodeApplication()
1454

1555
void CNodeApplication::Cleanup()
1656
{
57+
if(this->pIdleTimer != NULL)
58+
{
59+
this->pIdleTimer->CancelTimer();
60+
delete this->pIdleTimer;
61+
this->pIdleTimer = NULL;
62+
}
63+
1764
this->GetApplicationManager()->GetFileWatcher()->RemoveWatch(this);
1865

1966
if (NULL != this->scriptName)
@@ -41,6 +88,26 @@ HRESULT CNodeApplication::Initialize(PCWSTR scriptName, IHttpContext* context)
4188

4289
CheckNull(scriptName);
4390

91+
if(CModuleConfiguration::GetIdlePageOutTimePeriod(context) > 0)
92+
{
93+
dwIdlePageOutTimePeriod = CModuleConfiguration::GetIdlePageOutTimePeriod(context);
94+
if(dwInternalAppId == 0)
95+
{
96+
dwInternalAppId ++;
97+
this->fEmptyW3WPWorkingSet = TRUE;
98+
}
99+
if(pIdleTimer == NULL)
100+
{
101+
pIdleTimer = new STTIMER;
102+
ErrorIf(pIdleTimer == NULL, E_OUTOFMEMORY);
103+
CheckError(pIdleTimer->InitializeTimer( CNodeApplication::IdleTimerCallback, this, 10000, 0));
104+
}
105+
else
106+
{
107+
pIdleTimer->SetTimer(10000, 0);
108+
}
109+
}
110+
44111
DWORD len = wcslen(scriptName) + 1;
45112
ErrorIf(NULL == (this->scriptName = new WCHAR[len]), ERROR_NOT_ENOUGH_MEMORY);
46113
wcscpy(this->scriptName, scriptName);
@@ -74,6 +141,11 @@ PCWSTR CNodeApplication::GetConfigPath()
74141
return this->configPath;
75142
}
76143

144+
HRESULT CNodeApplication::EmptyWorkingSet()
145+
{
146+
return this->processManager->EmptyWorkingSet();
147+
}
148+
77149
HRESULT CNodeApplication::SetConfigPath(IHttpContext * context)
78150
{
79151
HRESULT hr = S_OK;
@@ -109,6 +181,8 @@ HRESULT CNodeApplication::Dispatch(IHttpContext* context, IHttpEventProvider* pP
109181
CheckNull(context);
110182
CheckNull(pProvider);
111183

184+
fRequestsProcessedInLastIdleTimeoutPeriod = TRUE;
185+
112186
ErrorIf(NULL == (*ctx = new CNodeHttpStoredContext(this, this->GetApplicationManager()->GetEventProvider(), context)), ERROR_NOT_ENOUGH_MEMORY);
113187
IHttpModuleContextContainer* moduleContextContainer = context->GetModuleContextContainer();
114188
moduleContextContainer->SetModuleContext(*ctx, this->GetApplicationManager()->GetModuleId());

0 commit comments

Comments
 (0)