相关变量和操作的分组?

时间:2011-07-29 03:06:19

标签: c performance grouping code-complete

在Code Complete第10章中,建议对相关语句进行分组,并给出以下示例:

void SummarizeData(...) {
    ...
    GetOldData( oldData, &numOldData );
    GetNewData( newData, &numNewData );
    totalOldData = Sum( oldData, numOldData );
    totalNewData = Sum( newData, numNewData );
    PrintOldDataSummary( oldData, totalOldData, numOldData );
    PrintNewDataSummary( newData, totalNewData, numNewData );
    SaveOldDataSummary( totalOldData, numOldData );
    SaveNewDataSummary( totalNewData, numNewData );
    ...
}

据说这种分组和并发处理是糟糕的设计,而是提供了更多分离的东西:

void SummarizeData(...) {
    GetOldData( oldData, &numOldData );
    totalOldData = Sum( oldData, numOldData );
    PrintOldDataSummary( oldData, totalOldData, numOldData );
    SaveOldDataSummary( totalOldData, numOldData );
    ...
    GetNewData( newData, &numNewData );
    totalNewData = Sum( newData, numNewData );
    PrintNewDataSummary( newData, totalNewData, numNewData );
    SaveNewDataSummary( totalNewData, numNewData );
    ...
}

我同意第二种方法更易于阅读和理解,并提供更清晰的代码,至少从我自己的角度来看。所以,我的问题是,第二种方法有任何缺点吗?例如,我能想到的一个可能的问题是与数据库的临时连接等:

void SummarizeData(...) {
    ...
    externalDataStore.open();
    externalDataStore.save(oldData, numOldData);
    externalDataStore.save(newData, numNewData);
    externalDataStore.close();
    ...
}

这第一种方法将在一个打开/关闭循环中完成两个保存操作。但是,采用第二种方法......

void SummarizeData(...) {
    ...
    externalDataStore.open();
    externalDataStore.save(oldData, numOldData);
    externalDataStore.close();
    ...
    externalDataStore.open();
    externalDataStore.save(newData, numNewData);
    externalDataStore.close();
    ...
}

您必须为每个操作打开和关闭连接。这看起来很浪费,但我不知道它在实践中会如何影响性能。

对不必要的长问题表示歉意......

2 个答案:

答案 0 :(得分:1)

我还没有完成Code 10中的第10章(还有几个晚上应该这样做!)但我认为这里的要点是以符合逻辑和易读的方式对你的代码行进行分组,< em>不影响程序功能。换句话说,清理它并尽可能重新排列它,但一旦它开始实际影响行为就停止。

在你的例子中,我们应该记住“过早优化是所有邪恶的根源”,但我认为我们仍然可以安全地假设你不应该关闭连接,如果你要打开它再次马上又一次取消了,因为这两个动作真的相互抵消了。作为一般规则,任何连接都应该在您第一次使用之前打开,并且在最后一次使用之后立即关闭,为了简单起见。

答案 1 :(得分:0)

我很无聊,所以我尝试使用Sqlite在Python中进行概念验证速度测试(我意识到这不是最好的方法)。

首先,50,000次迭代的基本测试,每次迭代后打开和关闭连接。

#!/usr/bin/env python

import sqlite3

class Creature(object):
    legs = 0

    eyes = 'monocular'

    kind = ''

conn = sqlite3.connect(':memory:')

c = conn.cursor()
c.execute('''create table testtable
        (date text, legs text, eyes text, kind text)''')
conn.commit()
c.close()

for i in range(50000):
    c = conn.cursor()

    creature1 = Creature()
    creature1.legs = 5
    creature1.eyes = 'monocular'
    creature1.kind = 'mungy'
    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature1.legs), creature1.eyes, creature1.kind))

    creature2 = Creature()
    creature2.legs = 3
    creature2.eyes = 'binocular'
    creature2.kind = 'thingy'
    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature2.legs), creature2.eyes, creature2.kind))

    creature3 = Creature()
    creature3.legs = 3
    creature3.eyes = 'monocular'
    creature3.kind = 'pungy'    
    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature3.legs), creature3.eyes, creature3.kind))

    conn.commit()
    c.close()

现在,50,000次迭代,但没有关闭连接。

#!/usr/bin/env python

import sqlite3

class Creature(object):
    legs = 0

    eyes = 'monocular'

    kind = ''

conn = sqlite3.connect(':memory:')

c = conn.cursor()
c.execute('''create table testtable
        (date text, legs text, eyes text, kind text)''')
conn.commit()
c.close()

c = conn.cursor()
for i in range(50000):

    creature1 = Creature()
    creature1.legs = 5
    creature1.eyes = 'monocular'
    creature1.kind = 'mungy'

    creature2 = Creature()
    creature2.legs = 3
    creature2.eyes = 'binocular'
    creature2.kind = 'thingy'

    creature3 = Creature()
    creature3.legs = 3
    creature3.eyes = 'monocular'
    creature3.kind = 'pungy'

    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature1.legs), creature1.eyes, creature1.kind))
    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature2.legs), creature2.eyes, creature2.kind))
    c.execute('insert into testtable values (?,?,?,?)', ('today', str(creature3.legs), creature3.eyes, creature3.kind))

    conn.commit()
c.close()

结果?

First method: Average 2.264s
Second method: Average 2.157s

所以,它有所不同,尽管可以忽略不计。

你有它。

绝对同意斯特凡说的话。