使用算术表达式而不是三元表达式设置批量大小

时间:2018-06-04 13:43:21

标签: language-agnostic refactoring

在以下代码段中(硬编码值只是一个示例):

int nBulk = 30,      // bulk size
    nMax = 130;      // max records to retrieve
    nRetrieved = 0;  // records retrieved so far
do
{
   var response = GetRecords(nBulk);
   nRetrieved += response.Count;
   nBulk = nMax - nRetrieved >= nBulk ? nBulk : nMax - nRetrieved;
}
while (nRetrieved < response.Total && nRetrieved < nMax);
使用三元表达式为

nBulk分配了一个新值。

三元表达式可以用简单的算术表达式替换(即没有分支)吗?

2 个答案:

答案 0 :(得分:0)

没有任何内容表明nMax==response.Total:因此我推断上一个GetRecords请求将返回有效nRetrieved <= nRequested

如果GetRecords具有足够的可读容量,则无需从您显示的代码中修改循环内的nBulk

但是,如果我看到这样的代码,我的推论是修改nBulk的最后一次读取可能是必要的,因为GetRecords有副作用 - 比如填充缓冲区 - IOW,a保护是绝对必要的,以避免缓冲区溢出。

在这种情况下,分支是最少的问题:使用方法/函数修改状态,但需要知道发送者/呼叫者站点的内部缓冲区限制(nMax)是危险的! / p>

这就是为什么我倾向于移动保护技术。 nMax方法/函数中的GetRecords而不是外部,如果这样做,问题在发送站点得到解决:不再需要在循环中修改nBulk,也不需要设计约nMax

当然,测试将在GetRecords内移动,因此不会消失。但坦率地说,为什么会出现问题呢?你不能增加bulkSize,这样这个测试就变得完全可以忽略了吗?

如果由于某种原因你不能,那么:

  1. 首先阅读以获取剩余总剩余尺寸
  2. 通过截断到循环外的nMax来处理nRemaining&gt; = nMax时的情况
  3. 循环,同时nRemaining&gt; = nBulk,并有效地减少nRemaining nRetrieved
  4. 使用nRemaining请求执行最后一次GetRecords。
  5. 循环中还有一个测试(nRemaining&gt; = nBulk),所以这一切似乎都没用。

    要避免此测试,您必须确保当有足够的内容时,有效nRetrieved等于请求的nBulk(代码中没有任何内容表示)。

    在这种情况下,您可以在步骤3执行除法。nLoop=integer_floor_division(Total/nBulk),执行此循环次数(并让一些编译器为您执行循环展开,以便平均减少测试次数) ,然后在步骤4为剩余的(模数/余数)Total%nBulk执行GetRecords。

    所有你会得到的IMO是一个更脆弱和脆弱的代码,有可能通过填充代码缓存来消除边际收益......你应该问的问题是:我真的需要这种微优化吗?为什么?

答案 1 :(得分:0)

答案是,但这很难看:

nBulk = (nBulk + (nMax - nRetrieved) + Math.Abs(nBulk - (nMax - nRetrieved)))/2;

如果你想避免Abs,那么你可以这样做:

nBulk = (nBulk + (nMax - nRetrieved) 
      + Math.Sqrt((nBulk - (nMax - nRetrieved)) * (nBulk - (nMax - nRetrieved))))/2;

这可能更糟。

长话短说,没有好的&#34;语言不可知&#34;这样做的方法是因为没有Lanugae Agnostic方法可以从布尔转换为没有分支的整数。在那些您只是说:

的语言中
int i = (true);
然后,这是一个不同的故事。