好的,所以我正在努力加快加载服务器所需的时间。主要是从数据库中预加载用户帐户,并将它们添加到每个包含13个变量的播放器对象列表中。
我已经决定第一步是查看系统的哪些部分花费的时间最长,因此我设置DateTime变量来计算每段代码执行的毫秒数。
我们在数据库中有大约4万个帐户,它们几乎立即加载到一个字符串列表中,然后我们将它们推断到它们的变量中,这不是最有效的方法,但速度很快,它既有效又没有错误。
无论如何,将4万个帐户外推到他们的后续对象中需要大约4分钟,设置变量并将对象添加到预加载数据列表中。
我在每个变量设置周围添加了DateTime变量,然后确定了执行时间,只有一个问题,所有数字都是0,我假设我搞砸了我的代码,所以我在几个不同的地方测试了它,它有效。
所以,现在我有点难过,试图找出所有时间和CPU周期的去向。
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
我正在测试初始对象创建,13个变量,将对象添加到列表中,然后输出总时间。这不是准确的,只是为了帮助我理解我需要改变的地方,我对40k的0行感到有点不高兴
有什么我想念的吗?据我所知,加载这些数据不应超过30秒(加上循环本身的成本)。
DateTime是不正确的?或者我在某个地方陷入困境,或者......
我很感激您对此有任何见解。
感谢您的时间:
P.S。如果你想看到整个代码,就是这样:
int pcounti = 0;
current.Text = "Pre-Loading Players."; bar.Value = 35;
List<string[]> p1 = SDB.get("Select * from players");
if (p1 != null)
{
int dbplayercount = p1.Count;
//REMOVE ME
List<string> tolog = new List<string>();
foreach (string[] s in p1)
{
// Check if this user already has a PDB
try
{
PDB temppdb = PDB.find(s[1].Trim().ToLower());
if (temppdb != null)
{
Console.WriteLine("Deleting");
SDB.donow("DELETE FROM players WHERE username = '" + s[1] + "' AND UID != " + temppdb.UID);
}
}
catch (Exception e)
{
Console.WriteLine("Error:");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
// Generate PDB
try
{
//We need the database to be all lowercase :D
if (HasCapitals(s[1])) SDB.donow("UPDATE players SET username = '" + s[1].ToLower() + "' WHERE username = '" + s[1] + "'");
DateTime one = DateTime.Now.ToUniversalTime();
PDB pdb = new PDB();
DateTime two = DateTime.Now.ToUniversalTime();
pdb.UID = Convert.ToInt64(s[0]);
DateTime three = DateTime.Now.ToUniversalTime();
pdb.username = s[1].Trim().ToLower();
DateTime four = DateTime.Now.ToUniversalTime();
pdb.password = s[3];
DateTime five = DateTime.Now.ToUniversalTime();
pdb.group = Byte.Parse(s[4]);
DateTime six = DateTime.Now.ToUniversalTime();
pdb.ip = s[10];
DateTime seven = DateTime.Now.ToUniversalTime();
pdb.color = s[11];
DateTime eight = DateTime.Now.ToUniversalTime();
try
{
pdb.warn = Convert.ToInt32(s[14]);
}
catch
{
pdb.warn = 0;
}
DateTime nine = DateTime.Now.ToUniversalTime();
try
{
pdb.money = Convert.ToInt32(s[15]);
}
catch
{
pdb.money = 0;
}
DateTime ten = DateTime.Now.ToUniversalTime();
foreach (string st in s[16].Split(','))
{
if (String.IsNullOrEmpty(st)) continue;
pdb.Allowed.Add(st);
}
DateTime eleven = DateTime.Now.ToUniversalTime();
foreach (string st in s[17].Split(','))
{
if (String.IsNullOrEmpty(st)) continue;
pdb.Denied.Add(st);
}
DateTime twelve = DateTime.Now.ToUniversalTime();
pdb.Title = s[18];
DateTime thirteen = DateTime.Now.ToUniversalTime();
foreach (string st in s[19].Split(','))
{
if (String.IsNullOrEmpty(st)) continue;
pdb.Titles.Add(st);
}
DateTime fourteen = DateTime.Now.ToUniversalTime();
PDB.DB.Add(pdb);
DateTime fifteen = DateTime.Now.ToUniversalTime();
int one1 = ((two - one).Milliseconds);
int two1 = ((three - two).Milliseconds);
int three1 = ((four - three).Milliseconds);
int four1 = ((five - four).Milliseconds);
int five1 = ((six - five).Milliseconds);
int six1 = ((seven - six).Milliseconds);
int seven1 = ((eight - seven).Milliseconds);
int eight1 = ((nine - eight).Milliseconds);
int nine1 = ((ten - nine).Milliseconds);
int ten1 = ((eleven - ten).Milliseconds);
int eleven1 = ((twelve - eleven).Milliseconds);
int twelve1 = ((thirteen - twelve).Milliseconds);
int thirteen1 = ((fourteen - thirteen).Milliseconds);
int fourteen1 = ((fifteen - fourteen).Milliseconds);
int fifteen1 = ((fifteen - one).Milliseconds);
string sta = one1 + " " + two1 + " " + three1 + " " + four1 + " " + five1 + " " + six1 + " " + seven1 + " " + eight1 + " " + nine1 + " " + ten1 + " " + eleven1 + " " + twelve1 + " " + thirteen1 + " " + fourteen1 + " " + fifteen1;
tolog.Add(sta);
pcounti++;
}
catch (Exception e)
{
Console.WriteLine("Error:");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
continue;
}
// write to file
StreamWriter sw = new StreamWriter(File.Create("test.txt"));
foreach (string st in tolog)
{
sw.WriteLine(st);
}
sw.Flush();
sw.Close();
}
}
另外,请注意,写完大部分内容之后,我最后一次查看它,以确保我没有错过任何愚蠢的东西,并意识到我没有检查每个循环的前几行,我将它们添加到支票出来时也是这样。
另外,作为第二个注释,它在“之前”花了4分钟我添加了性能检查,现在不需要花费更多时间。
修改的 将Milliseconds更改为TotalMilliseconds会产生差异,但仅在将结果显示为double,而不是int时,会产生如下测试输出:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0.9765 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0.9765 0 0 0 0 0 0 0 0 0 0 0 0.9765
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0.9766 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
第一个数字最后没有添加到总数中。 另外,我应该提到的是,偶尔有一个混合在一起的0(也是第一次)但是我仍然像以前一样难倒,是时候剖析了。
编辑2 分析的结果,请注意,所有时间计数器和最后的进度条更新都不是永久性的,并且在最初的事件过程中不存在导致我首先尝试执行此操作的事件。 (即4-5分钟的加载时间)
答案 0 :(得分:2)
您还没有真正告诉我们性能下降的位置,或者表明核心SQL查询需要多长时间,但有些想法:
List<string[]> p1 = SDB.get("Select * from players");
这是缓冲整个数据集;就个人而言,我将使用非缓冲API,即在到达时处理每一行。我也会使用输入的对象,而不是string[]
- 像dapper-dot-net这样的东西可以非常巧妙地完成。
我还会分析这个单独的查询,看看它有多少时间与数据本地处理相比。
你似乎做了很多(2 * N + 1)的发现(PDB.find(s[1].Trim().ToLower()
)和UPDATE
/ DELETE
等等;我认为你淹没了潜伏期。对于这个卷,我很想将源数据抛出(SqlBulkCopy
)到数据库服务器上的一个表中并进行一些基于集合的查询(3;一次更新,一次删除,一次插入 - 或者MERGE
如果可用) 在数据库 。
答案 1 :(得分:1)
有更好的方法来分析代码,比如使用合适的分析器,可以轻松获得免费代码和试用版!
如果你想以这种方式分析代码,我会看一下StopWatch类。
答案 2 :(得分:0)
TotalMilliseconds
代替Milliseconds
。代表5秒的TimeSpan
对象,TotalMilliseconds
为5000但Milliseconds
为0!#region Check if this user already has a PDB
if (HasCapitals(s[1])) SDB.donow("UPDATE players SET username = '" + s[1].ToLower() + "' WHERE username = '" + s[1] + "'");
答案 3 :(得分:0)
我认为毫秒在这里不起作用,因为所有这些测量的操作都需要不到一毫秒。您可以尝试使用System.Diagnostics.Stopwatch并测量Ticks。此外,如果您尝试对每个步骤的相对性能进行基准测试,而不是测量每个玩家的数字,则累积它们(例如,总和为1,总和为1)并进行比较。
无论如何,我认为这不是一个分析代码的好方法,或者你可以通过对这样简单的分配时间进行基准测试来获得更多。您应该检查代码的其他部分,如SELECT语句或PDB.find