Phần nào của việc ném một Ngoại lệ là tốn kém?

259
Martin Carney 2016-04-01 10:32.

Trong Java, sử dụng ném / bắt như một phần của logic khi thực sự không có lỗi nói chung là một ý tưởng tồi (một phần) bởi vì việc ném và bắt một ngoại lệ rất tốn kém và thực hiện nhiều lần trong một vòng lặp thường chậm hơn nhiều so với cấu trúc điều khiển không liên quan đến việc ném các ngoại lệ.

Câu hỏi của tôi là, có phải chi phí phát sinh khi tự ném / bắt hay khi tạo đối tượng Ngoại lệ (vì nó nhận được rất nhiều thông tin thời gian chạy bao gồm ngăn xếp thực thi)?

Nói cách khác, nếu tôi làm

Exception e = new Exception();

nhưng đừng ném nó, đó là phần lớn chi phí ném, hay việc xử lý ném + bắt có tốn kém không?

Tôi không hỏi liệu việc đặt mã vào khối try / catch có làm tăng thêm chi phí thực thi mã đó hay không, tôi đang hỏi liệu bắt Exception là phần đắt tiền hay việc tạo (gọi hàm tạo) Exception là phần đắt tiền .

Một cách khác để hỏi điều này là, nếu tôi tạo một phiên bản Exception và ném đi bắt lại nó, điều đó có nhanh hơn đáng kể so với việc tạo một Exception mới mỗi khi tôi ném không?

6 answers

271
apangin 2016-04-01 11:35.

Tạo một đối tượng ngoại lệ không tốn kém hơn so với việc tạo các đối tượng thông thường khác. Chi phí chính được ẩn trong fillInStackTracephương thức gốc đi qua ngăn xếp cuộc gọi và thu thập tất cả thông tin cần thiết để xây dựng dấu vết ngăn xếp: các lớp, tên phương thức, số dòng, v.v.

Sai lầm về chi phí ngoại lệ cao xuất phát từ thực tế là hầu hết các nhà Throwablexây dựng gọi ngầm fillInStackTrace. Tuy nhiên, có một nhà xây dựng để tạo ra một Throwablemà không có một vết đống. Nó cho phép bạn tạo các vật có thể ném rất nhanh để tạo. Một cách khác để tạo ngoại lệ nhẹ là ghi đè fillInStackTrace.


Bây giờ những gì về việc ném một ngoại lệ?
Trên thực tế, nó phụ thuộc vào vị trí mà một ngoại lệ ném ra được bắt .

Nếu nó được bắt trong cùng một phương thức (hoặc chính xác hơn là trong cùng một ngữ cảnh, vì ngữ cảnh có thể bao gồm một số phương thức do nội tuyến), thì thrownhanh và đơn giản như goto(tất nhiên, sau khi biên dịch JIT).

Tuy nhiên, nếu một catchkhối nằm ở đâu đó sâu hơn trong ngăn xếp, thì JVM cần phải giải phóng các khung ngăn xếp và quá trình này có thể mất nhiều thời gian hơn. Nó thậm chí còn mất nhiều thời gian hơn, nếu có synchronizedcác khối hoặc phương thức liên quan, bởi vì việc tháo vòng có nghĩa là giải phóng các màn hình thuộc sở hữu của các khung ngăn xếp bị loại bỏ.


Tôi có thể xác nhận các tuyên bố trên bằng các điểm chuẩn thích hợp, nhưng may mắn thay, tôi không cần phải làm điều này, vì tất cả các khía cạnh đã được trình bày hoàn hảo trong bài đăng của Alexey Shipilev, kỹ sư hiệu suất của HotSpot: Hiệu suất đặc biệt của Lil 'Exception .

72
erickson 2016-04-01 11:20.

Thao tác đầu tiên trong hầu hết các hàm Throwabletạo là điền vào dấu vết ngăn xếp, đây là nơi chiếm phần lớn chi phí.

Tuy nhiên, có một hàm tạo được bảo vệ với cờ để vô hiệu hóa dấu vết ngăn xếp. Hàm tạo này cũng có thể truy cập được khi mở rộng Exception. Nếu bạn tạo một loại ngoại lệ tùy chỉnh, bạn có thể tránh việc tạo dấu vết ngăn xếp và có được hiệu suất tốt hơn với chi phí ít thông tin hơn.

Nếu bạn tạo một ngoại lệ duy nhất thuộc bất kỳ loại nào bằng cách thông thường, bạn có thể ném lại nó nhiều lần mà không cần điền vào dấu vết ngăn xếp. Tuy nhiên, dấu vết ngăn xếp của nó sẽ phản ánh nơi nó được xây dựng, chứ không phải nơi nó được ném trong một trường hợp cụ thể.

Các phiên bản Java hiện tại thực hiện một số nỗ lực để tối ưu hóa việc tạo dấu vết ngăn xếp. Mã gốc được gọi để điền vào dấu vết ngăn xếp, nó ghi lại dấu vết trong một cấu trúc gốc, trọng lượng nhẹ hơn. Tương ứng Java StackTraceElementđối tượng được lười biếng tạo ra từ hồ sơ này chỉ khi getStackTrace(), printStackTrace()hoặc các phương pháp khác đòi hỏi phải có các dấu vết được gọi là.

Nếu bạn loại bỏ việc tạo dấu vết ngăn xếp, chi phí chính khác là giải nén ngăn xếp giữa lần ném và lần bắt. Càng ít khung can thiệp gặp phải trước khi bắt được ngoại lệ, điều này càng nhanh.

Thiết kế chương trình của bạn để các ngoại lệ chỉ được đưa ra trong những trường hợp thực sự đặc biệt và khó có thể biện minh cho những tối ưu hóa như thế này.

25
Harry 2016-04-01 11:46.

Có một bài viết tốt về Ngoại lệ ở đây.

http://shipilev.net/blog/2014/exceptions-performance/

Kết luận là xây dựng dấu vết ngăn xếp và tháo cuộn xếp chồng là những phần đắt tiền. Đoạn mã dưới đây tận dụng một tính năng trong 1.7đó chúng ta có thể bật và tắt dấu vết ngăn xếp. Sau đó, chúng tôi có thể sử dụng điều này để xem các tình huống khác nhau có loại chi phí nào

Sau đây là thời gian cho việc tạo Đối tượng một mình. Tôi đã thêm Stringở đây để bạn có thể thấy rằng nếu không có ngăn xếp được ghi thì hầu như không có sự khác biệt trong việc tạo JavaExceptionĐối tượng và a String. Khi bật tính năng viết ngăn xếp, sự khác biệt là rất lớn, tức là chậm hơn ít nhất một bậc của cường độ.

Time to create million String objects: 41.41 (ms)
Time to create million JavaException objects with    stack: 608.89 (ms)
Time to create million JavaException objects without stack: 43.50 (ms)

Phần sau cho biết mất bao lâu để quay lại từ một cú ném ở độ sâu cụ thể một triệu lần.

|Depth| WriteStack(ms)| !WriteStack(ms)| Diff(%)|
|   16|           1428|             243| 588 (%)|
|   15|           1763|             393| 449 (%)|
|   14|           1746|             390| 448 (%)|
|   13|           1703|             384| 443 (%)|
|   12|           1697|             391| 434 (%)|
|   11|           1707|             410| 416 (%)|
|   10|           1226|             197| 622 (%)|
|    9|           1242|             206| 603 (%)|
|    8|           1251|             207| 604 (%)|
|    7|           1213|             208| 583 (%)|
|    6|           1164|             206| 565 (%)|
|    5|           1134|             205| 553 (%)|
|    4|           1106|             203| 545 (%)|
|    3|           1043|             192| 543 (%)| 

Điều sau đây gần như chắc chắn là một sự đơn giản hóa tổng ...

Nếu chúng ta lấy độ sâu 16 khi ghi ngăn xếp thì việc tạo đối tượng sẽ chiếm khoảng ~ 40% thời gian, dấu vết ngăn xếp thực tế chiếm phần lớn điều này. ~ 93% việc khởi tạo đối tượng JavaException là do dấu vết ngăn xếp được thực hiện. Điều này có nghĩa là việc giải nén ngăn xếp trong trường hợp này sẽ chiếm 50% thời gian còn lại.

Khi chúng ta tắt tính năng tạo đối tượng theo dõi ngăn xếp chiếm một phần nhỏ hơn nhiều tức là 20% và việc mở ngăn xếp bây giờ chiếm 80% thời gian.

Trong cả hai trường hợp, việc giải nén ngăn xếp chiếm một phần lớn thời gian tổng thể.

public class JavaException extends Exception {
  JavaException(String reason, int mode) {
    super(reason, null, false, false);
  }
  JavaException(String reason) {
    super(reason);
  }

  public static void main(String[] args) {
    int iterations = 1000000;
    long create_time_with    = 0;
    long create_time_without = 0;
    long create_string = 0;
    for (int i = 0; i < iterations; i++) {
      long start = System.nanoTime();
      JavaException jex = new JavaException("testing");
      long stop  =  System.nanoTime();
      create_time_with += stop - start;

      start = System.nanoTime();
      JavaException jex2 = new JavaException("testing", 1);
      stop = System.nanoTime();
      create_time_without += stop - start;

      start = System.nanoTime();
      String str = new String("testing");
      stop = System.nanoTime();
      create_string += stop - start;

    }
    double interval_with    = ((double)create_time_with)/1000000;
    double interval_without = ((double)create_time_without)/1000000;
    double interval_string  = ((double)create_string)/1000000;

    System.out.printf("Time to create %d String objects: %.2f (ms)\n", iterations, interval_string);
    System.out.printf("Time to create %d JavaException objects with    stack: %.2f (ms)\n", iterations, interval_with);
    System.out.printf("Time to create %d JavaException objects without stack: %.2f (ms)\n", iterations, interval_without);

    JavaException jex = new JavaException("testing");
    int depth = 14;
    int i = depth;
    double[] with_stack    = new double[20];
    double[] without_stack = new double[20];

    for(; i > 0 ; --i) {
      without_stack[i] = jex.timerLoop(i, iterations, 0)/1000000;
      with_stack[i]    = jex.timerLoop(i, iterations, 1)/1000000;
    }
    i = depth;
    System.out.printf("|Depth| WriteStack(ms)| !WriteStack(ms)| Diff(%%)|\n");
    for(; i > 0 ; --i) {
      double ratio = (with_stack[i] / (double) without_stack[i]) * 100;
      System.out.printf("|%5d| %14.0f| %15.0f| %2.0f (%%)| \n", i + 2, with_stack[i] , without_stack[i], ratio);
      //System.out.printf("%d\t%.2f (ms)\n", i, ratio);
    }
  }
 private int thrower(int i, int mode) throws JavaException {
    ExArg.time_start[i] = System.nanoTime();
    if(mode == 0) { throw new JavaException("without stack", 1); }
    throw new JavaException("with stack");
  }
  private int catcher1(int i, int mode) throws JavaException{
    return this.stack_of_calls(i, mode);
  }
  private long timerLoop(int depth, int iterations, int mode) {
    for (int i = 0; i < iterations; i++) {
      try {
        this.catcher1(depth, mode);
      } catch (JavaException e) {
        ExArg.time_accum[depth] += (System.nanoTime() - ExArg.time_start[depth]);
      }
    }
    //long stop = System.nanoTime();
    return ExArg.time_accum[depth];
  }

  private int bad_method14(int i, int mode) throws JavaException  {
    if(i > 0) { this.thrower(i, mode); }
    return i;
  }
  private int bad_method13(int i, int mode) throws JavaException  {
    if(i == 13) { this.thrower(i, mode); }
    return bad_method14(i,mode);
  }
  private int bad_method12(int i, int mode) throws JavaException{
    if(i == 12) { this.thrower(i, mode); }
    return bad_method13(i,mode);
  }
  private int bad_method11(int i, int mode) throws JavaException{
    if(i == 11) { this.thrower(i, mode); }
    return bad_method12(i,mode);
  }
  private int bad_method10(int i, int mode) throws JavaException{
    if(i == 10) { this.thrower(i, mode); }
    return bad_method11(i,mode);
  }
  private int bad_method9(int i, int mode) throws JavaException{
    if(i == 9) { this.thrower(i, mode); }
    return bad_method10(i,mode);
  }
  private int bad_method8(int i, int mode) throws JavaException{
    if(i == 8) { this.thrower(i, mode); }
    return bad_method9(i,mode);
  }
  private int bad_method7(int i, int mode) throws JavaException{
    if(i == 7) { this.thrower(i, mode); }
    return bad_method8(i,mode);
  }
  private int bad_method6(int i, int mode) throws JavaException{
    if(i == 6) { this.thrower(i, mode); }
    return bad_method7(i,mode);
  }
  private int bad_method5(int i, int mode) throws JavaException{
    if(i == 5) { this.thrower(i, mode); }
    return bad_method6(i,mode);
  }
  private int bad_method4(int i, int mode) throws JavaException{
    if(i == 4) { this.thrower(i, mode); }
    return bad_method5(i,mode);
  }
  protected int bad_method3(int i, int mode) throws JavaException{
    if(i == 3) { this.thrower(i, mode); }
    return bad_method4(i,mode);
  }
  private int bad_method2(int i, int mode) throws JavaException{
    if(i == 2) { this.thrower(i, mode); }
    return bad_method3(i,mode);
  }
  private int bad_method1(int i, int mode) throws JavaException{
    if(i == 1) { this.thrower(i, mode); }
    return bad_method2(i,mode);
  }
  private int stack_of_calls(int i, int mode) throws JavaException{
    if(i == 0) { this.thrower(i, mode); }
    return bad_method1(i,mode);
  }
}

class ExArg {
  public static long[] time_start;
  public static long[] time_accum;
  static {
     time_start = new long[20];
     time_accum = new long[20];
  };
}

Các khung ngăn xếp trong ví dụ này rất nhỏ so với những gì bạn thường thấy.

Bạn có thể xem qua mã bytecode bằng javap

javap -c -v -constants JavaException.class

tức là đây là cho phương pháp 4 ...

   protected int bad_method3(int, int) throws JavaException;
flags: ACC_PROTECTED
Code:
  stack=3, locals=3, args_size=3
     0: iload_1       
     1: iconst_3      
     2: if_icmpne     12
     5: aload_0       
     6: iload_1       
     7: iload_2       
     8: invokespecial #6                  // Method thrower:(II)I
    11: pop           
    12: aload_0       
    13: iload_1       
    14: iload_2       
    15: invokespecial #17                 // Method bad_method4:(II)I
    18: ireturn       
  LineNumberTable:
    line 63: 0
    line 64: 12
  StackMapTable: number_of_entries = 1
       frame_type = 12 /* same */

Exceptions:
  throws JavaException
13
Austin D 2016-04-01 11:00.

Việc tạo ra Exceptionvới một nullvết đống mất khoảng nhiều thời gian như các throwtry-catchcùng khối. Tuy nhiên, việc lấp đầy dấu vết ngăn xếp mất trung bình 5 lần .

Tôi đã tạo điểm chuẩn sau để chứng minh tác động đến hiệu suất. Tôi đã thêm vào -Djava.compiler=NONECấu hình Chạy để tắt tối ưu hóa trình biên dịch. Để đo lường tác động của việc xây dựng dấu vết ngăn xếp, tôi đã mở rộng Exceptionlớp để tận dụng hàm tạo không ngăn xếp:

class NoStackException extends Exception{
    public NoStackException() {
        super("",null,false,false);
    }
}

Mã điểm chuẩn như sau:

public class ExceptionBenchmark {

    private static final int NUM_TRIES = 100000;

    public static void main(String[] args) {

        long throwCatchTime = 0, newExceptionTime = 0, newObjectTime = 0, noStackExceptionTime = 0;

        for (int i = 0; i < 30; i++) {
            throwCatchTime += throwCatchLoop();
            newExceptionTime += newExceptionLoop();
            newObjectTime += newObjectLoop();
            noStackExceptionTime += newNoStackExceptionLoop();
        }

        System.out.println("throwCatchTime = " + throwCatchTime / 30);
        System.out.println("newExceptionTime = " + newExceptionTime / 30);
        System.out.println("newStringTime = " + newObjectTime / 30);
        System.out.println("noStackExceptionTime = " + noStackExceptionTime / 30);

    }

    private static long throwCatchLoop() {
        Exception ex = new Exception(); //Instantiated here
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            try {
                throw ex; //repeatedly thrown
            } catch (Exception e) {

                // do nothing
            }
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long newExceptionLoop() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            Exception e = new Exception();
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long newObjectLoop() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            Object o = new Object();
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long newNoStackExceptionLoop() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            NoStackException e = new NoStackException();
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

}

Đầu ra:

throwCatchTime = 19
newExceptionTime = 77
newObjectTime = 3
noStackExceptionTime = 15

Điều này ngụ ý rằng việc tạo ra một cái NoStackExceptiontốn kém tương đương với việc liên tục ném một cái giống nhau Exception. Nó cũng cho thấy rằng việc tạo Exceptionvà lấp đầy dấu vết ngăn xếp của nó mất khoảng 4 lần lâu hơn.

4
Harry 2016-04-02 14:55.

Phần này của câu hỏi ...

Một cách khác để hỏi điều này là, nếu tôi tạo một phiên bản Exception và ném đi bắt lại nó, điều đó có nhanh hơn đáng kể so với việc tạo một Exception mới mỗi khi tôi ném không?

Có vẻ như đang hỏi liệu việc tạo ngoại lệ và lưu vào bộ nhớ đệm ở đâu đó có cải thiện hiệu suất không. Đúng vậy. Nó cũng giống như việc tắt ngăn xếp đang được ghi khi tạo đối tượng vì nó đã được thực hiện.

Đây là thời gian tôi có, vui lòng đọc cảnh báo sau ...

|Depth| WriteStack(ms)| !WriteStack(ms)| Diff(%)|
|   16|            193|             251| 77 (%)| 
|   15|            390|             406| 96 (%)| 
|   14|            394|             401| 98 (%)| 
|   13|            381|             385| 99 (%)| 
|   12|            387|             370| 105 (%)| 
|   11|            368|             376| 98 (%)| 
|   10|            188|             192| 98 (%)| 
|    9|            193|             195| 99 (%)| 
|    8|            200|             188| 106 (%)| 
|    7|            187|             184| 102 (%)| 
|    6|            196|             200| 98 (%)| 
|    5|            197|             193| 102 (%)| 
|    4|            198|             190| 104 (%)| 
|    3|            193|             183| 105 (%)| 

Tất nhiên vấn đề với điều này là dấu vết ngăn xếp của bạn bây giờ chỉ đến nơi bạn khởi tạo đối tượng chứ không phải nơi nó được ném ra.

3
Martin Carney 2016-04-01 11:37.

Sử dụng câu trả lời của @ AustinD làm điểm khởi đầu, tôi đã thực hiện một số chỉnh sửa. Mã ở dưới cùng.

Ngoài việc thêm trường hợp một phiên bản Ngoại lệ được ném liên tục, tôi cũng đã tắt tối ưu hóa trình biên dịch để chúng tôi có thể nhận được kết quả hiệu suất chính xác. Tôi đã thêm -Djava.compiler=NONEvào các đối số VM, theo câu trả lời này . (Trong nhật thực, hãy chỉnh sửa Cấu hình Chạy → Đối số để đặt đối số VM này)

Kết quả:

new Exception + throw/catch = 643.5
new Exception only          = 510.7
throw/catch only            = 115.2
new String (benchmark)      = 669.8

Vì vậy, việc tạo ngoại lệ tốn khoảng 5x như ném + bắt nó. Giả sử trình biên dịch không tối ưu hóa nhiều chi phí.

Để so sánh, đây là cùng một lần chạy thử nghiệm mà không cần tắt tối ưu hóa:

new Exception + throw/catch = 382.6
new Exception only          = 379.5
throw/catch only            = 0.3
new String (benchmark)      = 15.6

Mã:

public class ExceptionPerformanceTest {

    private static final int NUM_TRIES = 1000000;

    public static void main(String[] args) {

        double numIterations = 10;

        long exceptionPlusCatchTime = 0, excepTime = 0, strTime = 0, throwTime = 0;

        for (int i = 0; i < numIterations; i++) {
            exceptionPlusCatchTime += exceptionPlusCatchBlock();
            excepTime += createException();
            throwTime += catchBlock();
            strTime += createString();
        }

        System.out.println("new Exception + throw/catch = " + exceptionPlusCatchTime / numIterations);
        System.out.println("new Exception only          = " + excepTime / numIterations);
        System.out.println("throw/catch only            = " + throwTime / numIterations);
        System.out.println("new String (benchmark)      = " + strTime / numIterations);

    }

    private static long exceptionPlusCatchBlock() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            try {
                throw new Exception();
            } catch (Exception e) {
                // do nothing
            }
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long createException() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            Exception e = new Exception();
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long createString() {
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            Object o = new String("" + i);
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }

    private static long catchBlock() {
        Exception ex = new Exception(); //Instantiated here
        long start = System.currentTimeMillis();
        for (int i = 0; i < NUM_TRIES; i++) {
            try {
                throw ex; //repeatedly thrown
            } catch (Exception e) {
                // do nothing
            }
        }
        long stop = System.currentTimeMillis();
        return stop - start;
    }
}

Related questions

MORE COOL STUFF

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett chia tay chồng sau 3 ngày bên nhau và vẫn kết hôn với anh ấy 25 năm sau

Cate Blanchett đã bất chấp những lời khuyên hẹn hò điển hình khi cô gặp chồng mình.

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Tại sao Michael Sheen là một diễn viên phi lợi nhuận

Michael Sheen là một diễn viên phi lợi nhuận nhưng chính xác thì điều đó có nghĩa là gì?

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Hallmark Star Colin Egglesfield Các món ăn gây xúc động mạnh đối với người hâm mộ tại RomaDrama Live! [Loại trừ]

Ngôi sao của Hallmark Colin Egglesfield chia sẻ về những cuộc gặp gỡ với người hâm mộ ly kỳ tại RomaDrama Live! cộng với chương trình INSPIRE của anh ấy tại đại hội.

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Tại sao bạn không thể phát trực tuyến 'chương trình truyền hình phía Bắc'

Bạn sẽ phải phủi sạch đầu đĩa Blu-ray hoặc DVD để xem tại sao Northern Exposure trở thành một trong những chương trình nổi tiếng nhất của thập niên 90.

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

8 công dụng tuyệt vời của Baking Soda và Giấm

8 công dụng tuyệt vời của Baking Soda và Giấm

Bạn biết đấy, hai sản phẩm này là nguồn điện để làm sạch, riêng chúng. Nhưng cùng với nhau, chúng có một loạt công dụng hoàn toàn khác.

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Hạn hán, biến đổi khí hậu đe dọa tương lai của thủy điện Hoa Kỳ

Thủy điện rất cần thiết cho lưới điện của Hoa Kỳ, nhưng nó chỉ tạo ra năng lượng khi có nước di chuyển. Bao nhiêu nhà máy thủy điện có thể gặp nguy hiểm khi các hồ và sông cạn kiệt?

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Quyên góp tóc của bạn để giúp giữ nước sạch của chúng tôi

Tóc tỉa từ các tiệm và các khoản quyên góp cá nhân có thể được tái sử dụng như những tấm thảm thấm dầu và giúp bảo vệ môi trường.

Xem đoạn giới thiệu cho bộ phim chuyển thể đầy khói lửa, có sự góp mặt của ngôi sao Edward Norton từ phim Motherless Brooklyn của Jonathan Lethem

Xem đoạn giới thiệu cho bộ phim chuyển thể đầy khói lửa, có sự góp mặt của ngôi sao Edward Norton từ phim Motherless Brooklyn của Jonathan Lethem

Edward Norton đã muốn đưa cuốn tiểu thuyết Motherless Brooklyn của Jonathan Lethem's Joycean 1999 lên màn ảnh kể từ khi nó được xuất bản. Bây giờ, 20 năm sau, một đoạn giới thiệu đã xuất hiện cho câu chuyện sôi nổi, đưa câu chuyện của Lethem trở lại những năm 1950 với rất nhiều gương mặt quen thuộc.

Cách dễ dàng chọn không tham gia trọng tài ràng buộc thẻ Apple

Cách dễ dàng chọn không tham gia trọng tài ràng buộc thẻ Apple

Có thích thú khi sử dụng Thẻ Apple mới của bạn không? Trước khi bạn bắt đầu chi tiêu, có một nhiệm vụ bổ sung cần xem xét: chọn không tham gia trọng tài ràng buộc. Bạn sẽ phát hiện ra các điều khoản trọng tài ràng buộc trong nhiều thỏa thuận tài chính vì nó giúp ngăn các ngân hàng và đối tác kinh doanh của họ không phải ra tòa.

Những người chơi Fortnite World Cup không ghi bàn có cảm giác hài hước về điều đó

Những người chơi Fortnite World Cup không ghi bàn có cảm giác hài hước về điều đó

Điểm số tại vòng chung kết Fortnite World Cup Solo hôm nay là rất lớn, với người chiến thắng Bugha ghi được nhiều hơn 26 điểm so với người về thứ hai là Psalm. Nhưng không phải ai cũng có thể giành chiến thắng: Bốn cầu thủ ra về với 0 điểm, nhưng — ít nhất là trên Twitter — họ là những người thể thao tốt về điều đó.

Báo cáo: Cánh cửa tuyển sinh có thể đã mở cho các ứng viên UCLA có mối quan hệ có ảnh hưởng

Báo cáo: Cánh cửa tuyển sinh có thể đã mở cho các ứng viên UCLA có mối quan hệ có ảnh hưởng

Huấn luyện viên trưởng của bộ môn thể dục dụng cụ UCLA Valorie Kondos-Field theo dõi Katelyn Ohashi thi đấu thăng bằng trong trận gặp Stanford tại Pauley Pavilion vào ngày 10 tháng 3 năm 2019 ở Los Angeles, California. Vụ bê bối gian lận tuyển sinh đại học tiết lộ các chi tiết của một quá trình chính thức hóa để đưa những đứa trẻ thất bại của các gia đình giàu có và nổi tiếng vào các trường đại học đáng tin cậy và danh tiếng, sử dụng một "cửa phụ" đắt tiền cho các bậc cha mẹ mà sự giàu có của họ khiến họ không có cơ hội. chỉ cần tài trợ cho một cánh mới trong khuôn viên trường.

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Forced to Borrow Paris' 'I Love Paris' Sweatshirt After 'Airline Loses All [My] Luggage'

Nicky Hilton Rothschild's luggage got lost, but luckily she has an incredible closet to shop: Sister Paris Hilton's!

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa

Kate Middleton dành một ngày bên bờ nước ở London, cùng với Jennifer Lopez, Julianne Hough và hơn thế nữa. Từ Hollywood đến New York và mọi nơi ở giữa, hãy xem các ngôi sao yêu thích của bạn đang làm gì!

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

17 tuổi bị đâm chết trong khi 4 người khác bị thương trong một cuộc tấn công bằng dao trên sông Wisconsin

Các nhà điều tra đang xem xét liệu nhóm và nghi phạm có biết nhau trước vụ tấn công hay không

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Thanh thiếu niên, Gia đình Florida Hội đồng quản trị trường học về Luật 'Không nói đồng tính': 'Buộc chúng tôi tự kiểm duyệt'

Vụ kiện, nêu tên một số học khu, lập luận rằng dự luật "Không nói đồng tính" được ban hành gần đây của Florida "có hiệu quả im lặng và xóa bỏ học sinh và gia đình LGBTQ +"

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Hãy tưởng tượng tạo ra một chiến lược nội dung thực sự CHUYỂN ĐỔI. Nó có thể.

Vào năm 2021, tôi khuyến khích bạn suy nghĩ lại mọi thứ bạn biết về khách hàng mà bạn phục vụ và những câu chuyện bạn kể cho họ. Lùi lại.

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Sự mất mát của voi ma mút đã mở ra trái tim tôi để yêu

Vào ngày sinh nhật thứ 9 của Felix The Cat, tôi nhớ về một trong những mất mát lớn nhất trong cuộc đời trưởng thành của tôi - Sophie của tôi vào năm 2013. Tôi đã viết bài luận này và chia sẻ nó trên nền tảng này một thời gian ngắn vào năm 2013.

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Khi bạn không thể trở thành người mà Internet muốn bạn trở thành

Tôi ghét từ "tàu đắm". Mọi người cảm thấy thoải mái trong la bàn đạo đức của riêng mình, và khi làm như vậy, họ thấy mình vượt qua sự phán xét.

Tầm nhìn đám mây phi tập trung của DFINITY Blockchain

Lưu ý của người biên tập: Bạn đang xem tài liệu lỗi thời từ blog DFINITY đang được bảo quản cho mục đích lưu trữ.

Tầm nhìn đám mây phi tập trung của DFINITY Blockchain

Bài đăng này khám phá tầm nhìn về đám mây phi tập trung của nhóm DFINITY và cách nó liên quan đến các nhà cung cấp blockchain truyền thống và đám mây hiện có như Amazon Web Services. Các minh chứng về công nghệ DFINITY được áp dụng bởi một mạng lưới quy mô lớn sẽ được thực hiện vào mùa thu năm 2017, sau đó sẽ được gây quỹ Chính cho quỹ hỗ trợ phi lợi nhuận, với mạng “đám mây mở” dự kiến ​​sẽ ra mắt vào đầu mùa hè năm 2018 .

Language