董如意 孔庆 贺洋 陈凯
[摘要]随着计算机网络的广泛应用,越来越多的网络服务程序都要求服务器具有稳定的性能以提供可靠的服务。本文提出了基于机器学习的服务器调优系统的设计与实现方法,为提高服务器的可靠性及高效性提供了较好的解决方案。
[关键词]机器学习 服务器调优 线程池
[中图分类号]TP181 [文献标识码]A [文章编号]1009-5349(2016)02-0133-01
一、线程池调优系统总体设计
线程池调优系统由四个模块组成:线程池模块、性能监测模块、支持向量机调优模块。线程池模块负责线程池的创建与维护,任务队列的任务管理等,并将任务队列中的用户任务取出放入线程池中进行执行。性能监测模块负责对表征线程池性能的三个特征量吞吐量、任务运算时间和任务阻塞时间的监测,作为测试样本输入支持向量机调优模块中。支持向量机调优模块则通过性能监测模块提供的测试样本,得到所需的最佳线程池尺寸,并与当前的线程池尺寸进行对比,最后调整线程池尺寸到最佳。
二、线程池模块
线程池模块主要负责线程池内线程的创建、销毁、构造任务队列,并将任务队列中的用户任务取入线程池中分配空闲线程来执行。系统采用Win32的提供的线程库,以面向对象思想实现相关功能模块。线程池模块主要包括线程池类CPoolThread、任务队列类CJobDequeue、线程类CThread以及同步类CMutex。
线程类CThread最重要的一个方法是线程的创建方法CThread::Create()。线程创建方法采用了Win32线程库提供的线程创建应用程序接口CreateThread(Null,0,_ThreadEntry,this,0,&ThreadID;)来实现。线程池类CThreadPool主要提供了一个数组变量m_list_thread来维护一个线程池,线程池内的每个线程都存在了这个数组变量中,而具体的池内线程的操作都交给了线程类CThread来完成。线程池类CThreadPool主要包括初始化线程池的初始化方法CThreadPool::InitInstance()来实现线程池内所有线程的创建操作,具体通过CThread类的CThread::Create()方法来实现每个线程的创建。任务队列类CJobQueue是线程池类的一个对象,维护了一个任务队列数组列表m_normal_list,用户任务经过线程池类添加任务接口进入此数组列表中。任务队列类通过队列列表来维护管理等待中的用户任务。同步类CMutex主要是为了实现程序中的某些互斥操作设立的,通过对私有变量m_lock调用WinAPI函数的WaitForSingleObject()与ReleaseMutex()来实现程序的加锁与解锁操作。
三、性能监测模块
性能监测模块主要是监测表征线程池性能的三个特征量:吞吐量、任务运算时间和任务阻塞时间。由于吞吐量是监测用户任务进入任务队列的数量,因此,对吞吐量的监测可以在任务队列类中实现。而任务运算时间和任务阻塞时间直接是与线程的执行任务相关的,因此,将这两个量的监测放入线程类中实现。
性能监测模块对吞吐量的监测方法。每当有用户任务通过线程池类进入任务队列时,任务队列将其成员变量m_tuntu进行加1操作,实现对吞吐量的实时更新。
任务运算时间的监测方法主要通过调用Windows提供的API函数GetThreadTimes添加至线程类中的Run方法中来实现。GetThreadTimes函数可以返回四个参数:线程创建时间、线程退出时间、系统代码运算时间和用户代码运算时间。因此,可以通过对系统代码时间与用户代码时间求和来得到任务占用CPU的时间,也就是任务运算时间。具体做法是当线程类中Run方法启动用户任务时,即调用此API函数,获得任务进入线程池时间;当用户任务运行结束时,再次调用此API函数,即可获得任务离开线程池时间,将二者做差即可得到任务占用CPU的运算时间。
对任务阻塞时间的监测方法的实现则相对麻烦一些,因为没有直接测试任务阻塞时间的API函数.但是可以通过间接的方法来测量,即任务阻塞时间=任务执行时间-任务运算时间。其中,任务执行时间可以通过WindowsAPI函数getTickCount()来分别得到任务进入线程池与离开线程池时的CPU时钟,从而做差就可以求出任务执行时间;而任务运算时间也可以得到,因此再将两者做差就可以得出最后的任务阻塞时间。具体做法同监测任务运算时间时的做法,只是改变了监测的API函数。
四、支持向量机调优模块
根据支持向量机调优模型,将支持向量机调优模块写成线程类中的一个函数——调优函数Tuning()。
通过线程池类内的成员变量m_tuntu、m_cmptm和m_blktm获取当前线程池性能数据,输入到支持向量机方法中得到最佳线程池尺寸。当最佳线程池尺寸与当前线程池尺寸不符时,需要对线程池的尺寸进行调整。当需要增加线程池尺寸时,可以通过WindowsAPI函数CreateThread()来创建新线程;当需要减小线程池尺寸时,可以通过调用函数TerminateThread()来销毁空闲线程,最终达到所需的最佳线程池尺寸。
【参考文献】
[1]董如意.基于二阶段法的新型凸壳支持向量机研究[J].现代交际,2012(11).
责任编辑:张丽