`
躁动的绵羊
  • 浏览: 95967 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

面试题讨论(一)

阅读更多

     首先,请JE上的高手、老鸟们原谅我把这道题拿出来讨论,也许,这题对你们来说只是小菜一碟,我却是觉得这种题目比较少见,我也不太清楚。但是,我想拿出来与大家分享下,讨论讨论,希望能挖掘出它的原理,让不清楚的小鸟们长长见识,当然也包括我,呵呵!
    
      这是一道用友的面试题。题目是:请优化下面代码,并给出原因:
  
     

                for(int i = 0;i<10000;i++) {
                     for(int j = 0;j<1000;j++) {
                          for(int k = 0;k<100;k++) {
                             function(i,j,k);\
                          }
                     }
                   }
      



      这道题优化起来也许很容易,但要说出其中的原理我觉得比较难,希望能看到更多的是原理方面的讨论,越深刻越好!

 

分享到:
评论
42 楼 wkwj520 2010-12-04  
把循环次数最少的放到外面;另外可以把i++换成++i。
41 楼 taolei0628 2010-12-04  
初始化、比较、蛋疼。
40 楼 aws 2010-12-03  
原本
10000,1000,100
是在i=1,j=1,k=99的時候,變成i=1,j=2,k=1
结果是
99
2
4
而改变循环顺序之后
100,1000,10000
在i=1,j=1,K=99之后,是i=1,j=1,k=100
99
100
101
进行所谓优化之后,不论在毫秒级别提升了多少速度,但是结果的顺序却改变了

如果这个循环里执行的方法涉及到前后依赖的操作

那么这个改变符合不符合原本的业务要求,值得商榷
39 楼 抛出异常的爱 2010-12-02  
vootoss 写道
sam_kee 写道
就是把循环次数少的放在最外层也没啥用,刚才有个人提了三种方法,很好啊

大规模运算的时候能减少一些内存地址跳转的开销

抛出异常的爱 写道
java -server StupidThreadTest 

public class StupidThreadTest {
    public static void doSomeStuff() {
        double uselessSum = 0;
        for (int i=0; i<1000; i++) {
            for (int j=0;j<1000; j++) {
                uselessSum += (double) i + (double) j;
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        doSomeStuff();
        
        int nThreads = Integer.parseInt(args[0]);
        Thread[] threads = new Thread[nThreads];
        for (int i=0; i<nThreads; i++)
            threads[i] = new Thread(new Runnable() {
                public void run() { doSomeStuff(); }
            });
        long start = System.currentTimeMillis();
        for (int i = 0; i < threads.length; i++)
            threads[i].start();
        for (int i = 0; i < threads.length; i++)
            threads[i].join();
        long end = System.currentTimeMillis();
        System.out.println("Time: " + (end-start) + "ms");
    }
}
      

引用


表面上看, doSomeStuff() 方法可以给线程分点事做,所以我们能够从 StupidThreadBenchmark 的运行时间推导出多线程调度开支的一些情况。但是,因为 uselessSum 从没被用过,所以编译器能够判断出 doSomeStuff 中的全部代码是死的,然后把它们全部优化掉。一旦循环中的代码消失,循环也就消失了,只留下一个空空如也的 doSomeStuff。表 1 显示了使用客户机和服务器方式执行 StupidThreadBenchmark 的性能。两个 JVM 运行大量线程的时候,都表现出差不多是线性的运行时间,这个结果很容易被误解为服务器 JVM 比客户机 JVM 快 40 倍。而实际上,是服务器编译器做了更多优化,发现整个 doSomeStuff 是死代码。虽然确实有许多程序在服务器 JVM 上会提速,但是您在这里看到的提速仅仅代表一个写得糟糕的评测,而不能成为服务器 JVM 性能的证明。但是如果您没有细看,就很容易会把两者混淆。


38 楼 vootoss 2010-12-02  
sam_kee 写道
就是把循环次数少的放在最外层也没啥用,刚才有个人提了三种方法,很好啊

大规模运算的时候能减少一些内存地址跳转的开销
37 楼 sam_kee 2010-12-02  
就是把循环次数少的放在最外层也没啥用,刚才有个人提了三种方法,很好啊
36 楼 vootoss 2010-12-02  
i++ , j++ , k++  都是要push/pop的 ,想办法换成 ++i , ++j , ++k,
同时调整循环位置就可以了
35 楼 aws 2010-09-15  
a123159521 写道
一般采用三层循环进行计算的,在实际的业务中一般是作为过滤条件,竟然程序数据已经到了W级别的了,必须对For循环进行优化,使用优化后的程序,可以少执行1000 000次,你说是不是一个优化.


这种过滤,还是插入临时表然后sql吧……
34 楼 aws 2010-09-15  
这种毫秒级别10%的提升有意义么?
一条执行时间以秒为单位的SQL语句就把你优化出来的这几毫秒给抵消了
33 楼 a123159521 2010-09-15  
一般采用三层循环进行计算的,在实际的业务中一般是作为过滤条件,竟然程序数据已经到了W级别的了,必须对For循环进行优化,使用优化后的程序,可以少执行1000 000次,你说是不是一个优化.
32 楼 抛出异常的爱 2010-09-15  
引用
采用优化策略却在时间上却提升了10%,虽然是毫妙级别的,
但是如果function是一个执行时间很长的程序,那么程序的提升将会很大.

压栈出栈提升10%
如果运算时间长
效率会提升很大....

这结论是怎么得出来的?
31 楼 a123159521 2010-09-15  
代码如下:
/*
* 0.0.0 ~99.9.0
* 执行次数 100*10*1=1000次
* 执行时间 812
*/
public void doThing(){
for(int i = 0;i<10000;i++) {
     for(int j = 0;j<1000;j++) {
          for(int k = 0;k<100;k++) {
             function(i,j,k);
          }
     }
   }
}

/*
* 0.0.0 ~ 0.9.99
* 执行次数 1*10*100=1000次
* 执行时间 703
*/
public void doOpThing(){
for(int i = 0;i<100;i++) {
     for(int j = 0;j<1000;j++) {
          for(int k = 0;k<10000;k++) {
             function(i,j,k);
          }
     }
   }
}

/*
* 0.0.0 ~ 0.9.99
* 执行次数 1*10*100=1000次
* 执行时间 703
*/
public void doOp2Thing(){
int i,j,k;
for(i = 0;i<100;i++) {
     for(j = 0;j<1000;j++) {
          for(k = 0;k<10000;k++) {
             function(i,j,k);
          }
     }
   }
}
其实这道题的目的并不是让你写出优化的方法,而是考你JVM的编译解析原理.
/ Method descriptor #6 ()V
  // Stack: 4, Locals: 4
  public void doThing();
     0  iconst_0             --将int型0推送至栈顶
     1  istore_1 [i]           --将栈顶int型数值存入第二个本地变量
     2  goto 44              --无条件转移
     5  iconst_0             --将int型0推送至栈顶
     6  istore_2 [j]           --将栈顶int型数值存入第三个本地变量
     7  goto 34              --无条件转移
    10  iconst_0             --将int型0推送至栈顶
    11  istore_3 [k]          --将栈顶int型数值存入第四个本地变量
    12  goto 25             --无条件转移
    15  aload_0 [this]        --将第一个引用类型本地变量推送至栈顶
    16  iload_1 [i]            --将第二个int型本地变量推送至栈顶
    17  iload_2 [j]            --将栈顶int型数值存入第三个本地变量
    18  iload_3 [k]            --将栈顶int型数值存入第四个本地变量
19  invokevirtual org.yclframework.auth.test.dao.ibatis.Optimize.function(int, int, int) : void [24] –执行方法
[以上执行过程都是一致的,两个方法]
    22  iinc 3 1 [k]    --将指定int型变量增加指定值,这里是++
    25  iload_3 [k]    --将第四个int型本地变量推送至栈顶
    26  bipush 100    --将单字节的常量值(-128~127)推送至栈顶
    28  if_icmplt 15   --比较栈顶两int型数值大小,当结果小于0时跳转
    31  iinc 2 1 [j]    --将指定int型变量增加指定值,这里是++
    34  iload_2 [j]    --将栈顶int型数值存入第三个本地变量
    35  sipush 1000   --将一个短整型常量值(-32768~32767)推送至栈顶
    38  if_icmplt 10   --比较栈顶两int型数值大小,当结果小于0时跳转
    41  iinc 1 1 [i]    --将指定int型变量增加指定值,这里是++
    44  iload_1 [i]    --将栈顶int型数值存入第二个本地变量
    45  sipush 10000  --将一个短整型常量值(-32768~32767)推送至栈顶
    48  if_icmplt 5    --比较栈顶两int型数值大小,当结果小于0时跳转
    51  return        --方法返回
      Line numbers:
        [pc: 0, line: 17]
        [pc: 5, line: 18]
        [pc: 10, line: 19]
        [pc: 15, line: 20]
        [pc: 22, line: 19]
        [pc: 31, line: 18]
        [pc: 41, line: 17]
        [pc: 51, line: 24]
      Local variable table:
        [pc: 0, pc: 52] local: this index: 0 type: org.yclframework.auth.test.dao.ibatis.Optimize
        [pc: 2, pc: 51] local: i index: 1 type: int
        [pc: 7, pc: 41] local: j index: 2 type: int
        [pc: 12, pc: 31] local: k index: 3 type: int
编译成Calss的doThing(),其与doOpThing()唯一不同的是执行顺序,其执行顺序如下:
    22  iinc 3 1 [k]
    25  iload_3 [k]
    26  sipush 10000
    29  if_icmplt 15
    32  iinc 2 1 [j]
    35  iload_2 [j]
    36  sipush 1000
    39  if_icmplt 10
    42  iinc 1 1 [i]
    45  iload_1 [i]
    46  bipush 100
    48  if_icmplt 5
51  return
doOpThing()与doOp2Thing()的执行顺序一模一样.
在出入栈操作中,doThing出入栈如下:
变量    出入栈次数 /比较次数
K        100*1000*10000
J        1000*10000
I        10000
在出入栈操作中,doOpThing的出入栈如下:
变量    出入栈次数 /比较次数
K       10000*1000*100
J        1000*100
I        100
其实For循环里面使用的都是局部变量,其变量采用的是本地变量,只初始化一次
接下来都是出入栈和比较的操作,大家可以看到出入栈和比较次数都是相当快的.
采用优化策略却在时间上却提升了10%,虽然是毫妙级别的,但是如果function是一个执行时间很长的程序,那么程序的提升将会很大.

30 楼 pikachu 2010-09-15  
<div class="quote_title">躁动的绵羊 写道</div>
<div class="quote_div">
<p>     首先,请JE上的高手、老鸟们原谅我把这道题拿出来讨论,也许,这题对你们来说只是小菜一碟,我却是觉得这种题目比较少见,我也不太清楚。但是,我想拿出来与大家分享下,讨论讨论,希望能挖掘出它的原理,让不清楚的小鸟们长长见识,当然也包括我,呵呵! <br>     <br>      这是一道用友的面试题。题目是:请优化下面代码,并给出原因: <br>   <br>      </p>
<pre name="code" class="java">                for(int i = 0;i&lt;10000;i++) {
                     for(int j = 0;j&lt;1000;j++) {
                          for(int k = 0;k&lt;100;k++) {
                             function(i,j,k);\
                          }
                     }
                   }
      </pre>
<p><br><br>      这道题优化起来也许很容易,但要说出其中的原理我觉得比较难,希望能看到更多的是原理方面的讨论,越深刻越好!</p>
<p> </p>
</div>
<p>没看到有任何需要优化的地方.程序不是跑的很好么?</p>
<p>除非整个程序设计都是错误的,不需要那么多循环</p>
<p> </p>
29 楼 flashing 2010-09-14  
这种题目挺无语的。实际当中尽量避免多重循环是一条重要的编码准则,另外还有一条重要的编码准则是:当性能问题没有成为问题前,不要做任何优化。
出现三重循环的时候应该考虑考虑是不是设计或者算法有问题。
几乎99%的时候性能取决于架构。
28 楼 qvjing520 2010-09-14  
用友的人是怎么说的?一楼的确实可以提高性能可以用计时器测一下
27 楼 weirhp 2010-09-14  
你们这么一优化,执行的结果还对嘛!!想想function的第一个参数是什么样的变化!!
这个优化?
是不是只需在循环前定义变量就OK吗?
26 楼 抛出异常的爱 2010-09-14  
参考:
http://www.iteye.com/topic/761731
25 楼 xiaoh08 2010-09-14  
zhlfz 写道
见过,个人觉得这个比较 好
for(int i = 0;i<100;i++) {   

    for(int j = 0;j<1000;j++) {   

          
          for(int k = 0;k<10000;k++) {   



         }   

    }   

   }

我觉得下面的会更好一些
int i=0,j=0,k=0;
for(i = 0;i<100;i++) {   

    for(j = 0;j<1000;j++) {   

          
          for(k = 0;k<10000;k++) {   



         }   

    }   

   }
24 楼 pouyang 2010-09-14  
瑞友(用友收购的公司)约我去面试,外包做项目,我还去吗?(现在也在做外包)
23 楼 javavaj 2010-09-14  
垃圾回收更及时

相关推荐

    模拟IC面试题analog面试题.doc

    模拟IC面试题 analog面试题.doc 在这个模拟IC面试题中,我们可以总结出以下几个重要的知识点: 1. Op-Amp 结构比较 在这个问题中,我们需要比较三种不同的 Op-Amp 结构:2-stage op-amp (active load, class-A ...

    C++面试题点播一

    在文件中提到的第一个面试题,需要分析一个C++程序,并预测其运行结果。此题涉及到C++的构造函数、虚函数和多态的原理。给出的程序示例中,存在一个多态的例子,其中基类A定义了一个虚函数func,并在构造函数中调用...

    MBA无领导小组讨论面试题(一).doc

    MBA 无领导小组讨论面试题(一) 本文将围绕 MBA 无领导小组讨论面试题(一)中涉及到的知识点进行详细的分析和解释。 危机公关管理 危机公关管理是一种特殊的公关模式,它是在企业或组织面临危机时,为了保护...

    软件测试面试题-收集了一些经典的软件测试面试题.zip

    以下是一些可能出现在“软件测试面试题-收集了一些经典的软件测试面试题.zip”文件中的常见问题及其详细解答: 1. **什么是软件测试?** 软件测试是一种系统性的活动,旨在发现软件产品中的错误、缺陷或遗漏。它的...

    计算机和JAVA 面试题大全

    - 面试题:如何通过反射创建并调用一个类的方法? - 讨论注解的用途,如代码自动生成、元数据提供等。 11. **集合框架高级话题** - 学习泛型的使用,理解类型擦除的概念。 - 面试题:解释什么是并发容器,比如...

    微软试题合集 微软面试题

    微软作为全球知名的科技巨头,其面试题历来备受关注,这些题目不仅体现了微软对技术人才的期望,也成为了求职者提升自身技能的重要参考资料。本压缩包中的“微软试题合集”涵盖了多个领域的技术问题,旨在测试候选人...

    .net面试题.net面试题.net面试题.net面试题(经典)

    .NET面试题是评估应聘者对.NET框架理解和应用能力的重要方式,涵盖了从基础概念到高级特性的广泛知识领域。以下是一些可能出现在.NET面试中的关键知识点: 1. **.NET框架基础**:理解.NET Framework的基本结构,...

    CCIE面试题集合下载

    【标题】"CCIE面试题集合下载"所涵盖的知识点主要集中在Cisco Certified Internetwork Expert(CCIE)认证的面试部分,这是一个高级IT认证,专为网络专业人士设计,旨在验证他们在网络基础设施设计、实施和故障排除...

    sql面试题,java面试题

    首先,让我们关注SQL面试题。SQL(Structured Query Language)是用于管理关系数据库的标准语言,包括数据查询、更新、插入和删除等操作。常见的SQL面试题涵盖以下几个方面: 1. 数据库基本概念:理解数据库、表、...

    BI常见面试题

    BI 常见面试题汇总 BI(Business Intelligence)是企业智能化的核心组件,涉及到数据分析、报表设计、数据仓库、数据挖掘等多个方面。面试BI相关岗位时,需要具备丰富的知识储备和实践经验。以下是BI常见面试题汇总...

    JavaWeb全栈面试题

    JavaWeb全栈面试题涵盖了Java基础、Web开发、数据库、服务器、线程管理、内存分布、前端技术等多个关键领域,是全面评估一个开发者综合技能的重要参考。以下将针对这些知识点进行详细阐述: 1. **Java基础**:Java...

    鹅厂面试题、大厂面试题、JVM面试题

    在这篇文章中,我们将讨论鹅厂面试题、大厂面试题、JVM面试题,并对每个问题进行详细的解释和分析。 首先,让我们来讨论 TCP 和 UDP 的区别。TCP 是一个全双工协议,这意味着它可以同时发送和接收数据,而 UDP 则是...

    2021最新大厂AI面试题:107题(含答案及解析).pdf

    在vivo数据挖掘面试题中,讨论了数组和背包问题,这些都是算法领域中的经典问题,对应着leetcode中的相关题目。 明略科技AI岗位面试题中涉及到了熵、交叉熵的概念,熵是信息论中的一个基本概念,交叉熵则是衡量两个...

    java企业面试试题

    04-25-13-27-22-755.doc`虽然标题提到了C++,但在这个Java主题中,可能是由于C++和Java在某些方面有共通之处,例如面向对象编程,因此这份文档可能包含了一些与C++相关的Java面试题,或者是一些跨语言的比较和讨论。...

    全国软件公司面试题集锦 面试题

    【全国软件公司面试题集锦】是一份涵盖了广泛IT领域知识的面试题库,旨在帮助求职者准备在软件公司的面试过程中可能遇到的问题。这份资源包含了各种技术层面的问题,包括但不限于编程语言、数据结构、算法、操作系统...

    前端面试题含答案.pdf

    前端面试题含答案.pdf 是一份包含多个与前端开发相关的问题的文件,该文件涵盖了 HTML、CSS、JavaScript 等多个方面的知识点。下面是对该文件中部分内容的知识点解释: 1. CSS 样式定义:问题 1 中,讨论了 display...

    Java面试题笔试题大全

    Java作为全球最流行的编程语言之一,其面试题和笔试题是评估开发者技能的重要标准。这份“Java面试题笔试题大全”资源旨在帮助求职者全面准备Java相关的技术面试和笔试环节,提升成功几率。CHM(Compiled Help ...

    嵌入式经典面试题及答案

    今天,我们将讨论一些经典的嵌入式面试题及答案,从预处理器到数据声明,涵盖了多个方面的知识点。 预处理器 预处理器是一个重要的部分,在嵌入式系统中经常用于定义常数和宏。下面是一个经典的面试题: 1. 用...

    VMWARE虚拟化技术面试题.pdf

    VMWARE虚拟化技术面试题 本资源涉及VMWARE虚拟化技术的面试题,涵盖了虚拟化技术的多个方面,包括vSphere组件、虚拟机属性、虚拟化vCenter的优势、虚拟机迁移、模板与虚拟机的区别、虚拟机快照、分布式交换机体系...

    5年java面试题汇总.docx

    Java工程师面试题汇总涵盖了广泛的IT领域知识,包括基础的Java语法、数据库原理、多线程概念、ORM框架MyBatis、缓存系统Redis、微服务框架Spring Cloud以及全文搜索引擎Elasticsearch。这些知识点是Java开发者在职业...

Global site tag (gtag.js) - Google Analytics