首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Windows服务生成的进程运行速度比GUI生成的进程慢3到4倍

Windows服务生成的进程运行速度比GUI生成的进程慢3到4倍
EN

Stack Overflow用户
提问于 2016-01-27 16:59:48
回答 2查看 102关注 0票数 1

我已经用Borland C++编写了一个服务应用程序。效果很好。在ServiceStart(TService *Sender,bool &Started)例程中,我调用mjwinrun来启动一个进程,该进程可以拾取并处理宏。此进程没有UI,任何错误都会记录到文件中。它继续运行,直到服务器重新启动、关闭或使用任务管理器终止进程为止。这是mjwinrun :-

代码语言:javascript
运行
复制
int mjwinrun(AnsiString cmd)
{
  STARTUPINFO mjstupinf; PROCESS_INFORMATION mjprcinf;
  memset(&mjstupinf,0,sizeof(STARTUPINFO)); mjstupinf.cb=sizeof(STARTUPINFO);
  if (!CreateProcess(NULL,cmd.c_str(),NULL,NULL,TRUE,0,NULL,GetCurrentDir().c_str(),&mjstupinf,&mjprcinf))
  {
    LogMessage("Could not launch "+cmd); return -1;
  }
  CloseHandle(mjprcinf.hThread); CloseHandle(mjprcinf.hProcess);
  return mjprcinf.dwProcessId;
}

cmd是启动宏队列处理器的命令行。我使用了一个CPU/内存密集型宏,并让它将其时间写入文件。以下是我的发现:-

1)如果宏处理器是在登录会话内从命令行启动的,则无论在哪个Windows内核下运行,宏都在6秒内完成。

2)如果宏处理器是从Vista内核或更早启动的服务(使用上面的mjwinrun )启动的,则宏将在6秒内完成。

3)如果宏处理器是从Windows 7内核或更高版本启动的服务(使用上面的mjwinrun )启动的,则宏将在超过18秒内完成。

我已经为CreateProcess尝试过所有不同的标志,它们都没有区别。我已经尝试了所有不同的帐户为这项服务,这没有任何区别。我试着为任务设置所有不同的优先级,I/O和Page,但它们都没有区别。这就好像服务产生的进程在某种程度上是节流的,不是在I/O方面,而是在CPU/内存使用方面。有什么想法吗? Windows 7的变化是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-02 14:49:12

我分离了一些代码来再现这一点,它最终归结为对数据库引擎的调用来查找字段定义(TTable方法FindField和FieldByName)。当在服务应用程序上运行而不是在GUI应用程序上运行时,这些操作在有很多字段的表上花费的时间要长得多。我设计了自己的方法来存储从字段名到字段定义的映射,因为我总是用一个中央例程打开数据库。我使用了每个表(所有BCB对象通用的)标记属性索引的字符串数组,其中每个字符串由;字段名;字段号;成对组成,然后执行字段名的.Pos来获取字段号。字段号为零填充,宽度为4。整个应用程序及其所有数据库只需使用几百KB的RAM。一旦到位,服务应用程序将以与GUI应用程序相同的速度运行。我唯一能想到的解释就是,服务应用程序本身和它们产生的任何进程都有一个固定的堆(我想我在某个地方默认读到了48 48MBytes )。由于有很多字段,内存溢出,不得不在磁盘上调用VM。GUI应用程序没有这样的限制,完全可以在实际内存中进行查找。不过,我可能完全错了。我学到的一件事是,FieldByName和FindField是昂贵的调用TTable函数,现在我用自己的机制取代了它们,这些机制似乎工作得更好,速度更快。这是我的查找例程:-

代码语言:javascript
运行
复制
AnsiString fldsbytag[MXSPRTBLS+100];

TField *fldfromtag(TAdsTable *tbl,AnsiString fld)
{
  int fi=fldsbytag[tbl->Tag].Pos(";"+fld.UpperCase()+";"),gi;
  if (fi==0) return tbl->FindField(fld);
  gi=StrToIntDef(fldsbytag[tbl->Tag].SubString(fi+fld.Length()+2,4),-1);
  if (gi<0 || gi>=tbl->Fields->Count) return tbl->FindField(fld);
  return tbl->Fields->Fields[gi];
}
票数 1
EN

Stack Overflow用户

发布于 2016-01-27 18:08:13

在没有更多细节的情况下,很难对这个问题作出权威性的回答。

但是,需要考虑的一个因素是描述了这里的Windows前台优先级提升。

您可能需要阅读Russinovich的书中关于进程/线程的章节,特别是关于调度的内容。你可以在网上找到这本书的PDF(两本书合在一起构成了整本书)。我相信最新版(或紧靠最新版)涵盖了Win 7中的变化。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35043542

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档