全局对象与多个新对象?

Posted

技术标签:

【中文标题】全局对象与多个新对象?【英文标题】:Global objects vs multiple new objects? 【发布时间】:2011-09-20 10:17:13 【问题描述】:

假设我有一个方法,该方法需要在每次运行期间创建少量对象,并且该方法将被多次调用,即从数据库中删除给定行的方法。每次都创建一个新对象并调用垃圾收集器(或类似的)在最后销毁它,还是每次都重新初始化该值会更好吗?

示例: 每次都使用新的构造函数:

private void RemoveFolder(string dir)

    OleDbCommand cmd2 = connection.CreateCommand();
    OleDbParameter parameterC = new OleDbParameter();
    cmd2.Parameters.Add(parameterC);
    parameterC.Value = dir;

    cmd2.CommandText = "DELETE * FROM [Directories] WHERE Path = ?";
    cmd2.ExecuteNonQuery();
    cmd2.Dispose();

使用单个全局变量(在构造函数中初始化):

private void RemoveFolder(string dir)

    parameterC.Value = dir;

    cmd2.CommandText = "DELETE * FROM [Directories] WHERE Path = ?";
    cmd2.ExecuteNonQuery();

编辑:当我说得更好时,我的意思是在正常的非“关键任务”程序中“作为一个整体”,其中性能的大幅提升将胜过稳定性的小幅下降.

EDIT2

多次调用类似方法的示例

(注意这是我的另一种方法,AddFolder)

foreach (DirectoryInfo directory in directories)

    parameter.Value = directory.FullName;
    cmd.CommandText = "SELECT LastModified FROM Directories WHERE Path = ?";
    reader = cmd.ExecuteReader();

    while (reader.Read())
    
        output += reader.GetString(0);
    

    if (output == null)
    
        Console.WriteLine("New Directory! " + directory.FullName);
        AddFolder(directory);
    
    output = null;
    reader.Close();
 

【问题讨论】:

能否请您显示多次执行此方法的代码 【参考方案1】:

您的问题是我需要优化该代码吗?

我的总体看法,

    如果两个容易优化它,并且代码仍然比它简单, 否则,如果不确定它是否会产生影响而不是这样, 如果不确定,请测量它 在相关代码附近留下评论

如何测量它? 您可以查看您的程序是否运行缓慢,或者它是否使用了太多内存..

【讨论】:

【参考方案2】:

关于您的第二次编辑,

您可以将 foreach 循环转换为 LINQ, 聚合所有目录,然后立即 将目录添加到您的数据库中

你的代码会看起来更优雅,它会解决你的主要问题

见http://www.linqtutorial.net/linqExamples.html有一段如何用LINQ替换迭代循环

【讨论】:

【参考方案3】:

您在这里遇到的主要性能问题是您为查询的“准备”支付了多少费用。准备是解析查询和(更重要的是)确定查询计划的地方。查询计划的确定可能相当昂贵,您希望尽量减少必须完成的次数

(注意:即使您示例中的 DELETE ... WHERE ... 也需要查询计划。)

某些 DBMS 和 ADO.NET 提供程序在“重用”查询计划方面比其他提供程序更好。例如,在 Oracle/ODP.NET 上,您是否反复重新创建 DbCommand 可能并不重要 - Oracle 将倾向于“看到”这是以前使用的相同查询并重用查询计划。

另一方面,如果您想确保查询准备一次并重复使用多次,无论您使用什么 DBMS,保持相同的 DbCommand 对象不是一个坏主意在整个应用程序执行过程中(甚至显式调用 DbCommand.Prepare),如下所示:

var conn = new OracleConnection("your connection string"); // Or DB2Connection, SqlConnection or NpgsqlConnection or whatever...
conn.Open();

// Execute once:
var cmd = conn.CreateCommand();
cmd.CommandText = "DELETE FROM YOUR_TABLE WHERE YOUR_FIELD = :your_param";
var param = cmd.CreateParameter();
param.ParameterName = "your_param";
param.DbType = ...;
cmd.Parameters.Add(param);
cmd.Prepare(); // Not really important for Oracle, but may be important for others.

// Execute multiple times:
param.Value = "some value";
int row_count = cmd.ExecuteNonQuery();

// If you are concerned with long-lived connections, you'll typically be able to do this:
conn.Close();
// ...
conn.Open();
param.Value = "some other value";
row_count = cmd.ExecuteNonQuery();

// Etc..

所以:

如果您的程序仅在单个 DBMS/ADO.NET 提供程序上运行,并且您知道它将有效地重用查询计划,并且您不介意稍微昂贵的 C# 代码,那么您可能会选择“重复重新创建”解决方案。它还可能允许稍微短一点的 C# 代码。 但是,我更喜欢“创建一次,多次重复使用”的解决方案 - 无论我使用什么 DBMS,我都会获得最佳性能。即使在那些智能到足以重用查询计划的 DBMS 下,我仍然会避免重新执行 C# 代码和相关的垃圾收集压力。

【讨论】:

【参考方案4】:

我认为这里的关键建议是不要留下挥之不去的数据库连接,然后在临时基础上打开和操作。我注意到您的问题实际上围绕是否重用命令 - 当,在查看时,注意到您的连接必须已经是可重用的......我不建议这样做,并建议您将每个数据库操作视为一个原子单元工作量,包括连接利用率等。

【讨论】:

我通常会完全同意你的看法。但是,在扫描更改后连接会关闭(当前为 10 秒)。每次编辑都重新打开连接太慢而无法使用【参考方案5】:

最好使用第一种方法,这样执行查询的逻辑就停留在单个函数中。

【讨论】:

【参考方案6】:

我认为正确的版本介于两者之间

public foo() 

   var context = generateContext(dir);
   context.excute();

把两个目标分开

    创建上下文 执行它

在创建上下文中使用可以使用单例

【讨论】:

【参考方案7】:

我更喜欢使用全局变量,而不是每次操作都重新创建相同的对象。 一次性分配成本很小,而每次迭代创建对象的成本可能很高。

【讨论】:

这是我的想法。然而,我有幸见到的每个开发人员都表示,全局变量(或对象)一般来说是个坏消息。因此我的困境......

以上是关于全局对象与多个新对象?的主要内容,如果未能解决你的问题,请参考以下文章

我可以创建一个“全局”对象来存储多个对象的变量吗?

JavaScript之jQuery-9 jQuery 开发插件(添加新全局函数添加jQuery对象方法添加新简写方法方法参数)

如何在多个视图控制器之间全局共享数据

每次调用端点时,自托管 WCF 服务全局对象似乎都是新创建的

nodejs学习笔记 -- 全局对象与全局变量

python wsgi服务器中的全局对象