简体   繁体   English

抽象和封装与性能不一致 - 如何?

[英]Abstraction and Encapsulation are at odds with performance - How?

I've been reading the book, "Java Concurrency in Practice", where, in the Tread Safety chapter, it is mentioned that: "Sometimes Abstraction and Encapsulation are at odds with performance". 我一直在阅读“Java Concurrency in Practice”这本书,其中,在Tread Safety章节中,提到:“有时抽象和封装与性能不一致”。 I did not get this part. 我没有得到这一部分。 Can someone explain with an example, please? 有人可以用一个例子解释一下吗?

Thanks in advance. 提前致谢。

Long story short: first get it right, then improve performance afterwards. 长话短说:首先做对,然后改善表现。

There are times when you will jump through hoops to try and increase performance, sometimes leading to bugs or bad design. 有时你会跳过篮球试图提高性能,有时会导致错误或糟糕的设计。 Not to mention, it's time consuming! 更不用说,这很费劲! Programming strictly with performance in mind will result in code that's hard to scale, and programming strictly with design in mind will (possibly) result in more overhead. 严格按照性能进行编程将导致代码难以扩展,严格按照设计进行编程(可能)会导致更多开销。

I guess a good way to view it is encapsulation is a form of restricting; 我想一个很好的方法来看待封装是一种限制形式; setting limits for how something can be accessed/modified. 如何访问/修改某些内容的设置限制。 Those restrictions can come at a price of performance. 这些限制可能会以性能为代价。

The full quote states: 完整的报价说明:

Sometimes abstraction and encapsulation are at odds with performance — although not nearly as often as many developers believe — but it is always a good practice first to make your code right, and then make it fast 有时抽象和封装与性能不一致 - 虽然不像许多开发人员所认为的那样频繁 - 但是首先要使代码正确,然后快速完成总是一个好的做法

Example with threads: 线程示例:

The good and slow code: 好的和慢的代码:

//Several classes doing each one its thing.
public class Task1 implements Runnable { ... }
public class Task2 implements Runnable { ... }
public class Task3 implements Runnable { ... }

//Collection with runnable instances
List<Runnable> tasks = new ArrayList<Runnable>();

//A producer would have populated the list with some instances depending on some conditions
if(cond1) tasks.add(new Task1());
if(cond2) tasks.add(new Task2());
if(cond3) tasks.add(new Task3());

//Now we execute tasks without caring what do they do.
ExecutorService executor = Executors.newFixedThreadPool(1);
for(Runnable r : tasks){
    executor.execute(r);
}

Now the bad but fast code: 现在是糟糕但快速的代码:

new Thread(){
    @Override
    public void run(){
        if(cond1){
            //do task 1
        } else if(cond2){
            //do task 2
        } else if(cond3){
            //do task 3
        }
    }
}.start();

The first case is the best in terms of abstraction (and hence from the testing and maintenance points of view, which are the most important in professional software development). 第一种情况是抽象方面最好的(因此从测试和维护的角度来看,这是专业软件开发中最重要的)。 The producer and consumer are decoupled, and the consumer executor doesn't care about how the tasks are implemented. 生产者和消费者是分离的,消费者执行者并不关心如何实现任务。 BUT tasks have to be instantiated and that means slow. 但是必须实例化任务,这意味着缓慢。

In general, creating instances is slow because managing the heap needs CPU cycles, as memory needs to be tracked and allocated or released. 通常,创建实例很慢,因为管理堆需要CPU周期,因为需要跟踪和分配或释放内存。 In Java there's the additional problem of the Garbage Collector running randomly, which might be needed to allocate extra heap if we're short on memory. 在Java中,存在垃圾收集器随机运行的额外问题,如果我们内存不足,可能需要分配额外的堆。 A second slowdown comes from the function calls (the function run of each task must be called to do its thing). 第二个减速来自函数调用(必须调用每个任务的函数run来执行它的操作)。 Function calling is slower than not calling at all, because there has to be a tracking of the stack, and parameter passing, etc. 函数调用比根本不调用慢,因为必须跟踪堆栈和参数传递等。

The second snippet is messy and has every task payload mixed up. 第二个片段很乱,每个任务有效负载都混乱了。 This is real coding horror. 这是真正的编码恐怖。 Moreover, it both produces and consumes tasks. 而且,它既产生又消耗任务。 However, it's going to be damn fast as no instances are created and there are no function calls as the code of each task is inlined. 但是,由于没有创建任何实例,并且没有函数调用,因为每个任务的代码都是内联的,所以它会很快。

You might not see my point in this code as there are only 3 task being run only once, but imagine if tasks were produced at a rate of a thousand per second. 您可能没有在此代码中看到我的观点,因为只有3个任务只运行一次,但想象一下,如果任务是以每秒一千的速度生成的。 This could for instance happen in a web server processing requests, or by a plane's electronic flight instrument system processing flight instruments readings. 例如,这可能发生在处理请求的网络服务器中,或者由飞机的电子飞行仪表系统处理飞行仪表读数。

So it's often the case that the cleaner code is slower. 因此通常情况下,更干净的代码更慢。

As Knuth said, 正如Knuth所说,

"Premature optimization is the root of all evil" “过早优化是所有邪恶的根源”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM