single block read

db file sequential read: 单个块读到SGA buffer中
db file scattered read:多个块读到不连续的SGA buffer中
direct read:单个或者多个块读到PGA中,绕开SGA

一个连续读是单块读。如果db_block_size是8k,那么就是读8K的内容。一个单块读只要由
一个磁盘服务就可以了,不需要所有的磁盘来服务。
如果有高并发的时候,不同的单块请求发布到不同的磁盘上。

环境:
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE    11.2.0.2.0      Production
TNS for Linux: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production

Oracle数据库的ASM开启了Direct IO和asynch IO。这样重复执行而不受file system buffer
的影响。

ASM/ASMLib本身支持Direct IO。

SQL> show parameter disk

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
asm_diskgroups                       string
asm_diskstring                       string
disk_asynch_io                       boolean     TRUE

创建表test,每条记录占用一个block,1,000,000 rows。

drop table test purge;

create table test (tid number, tcode varchar2(40), name char(2000), name1 char(2000), name2 char(2000), name3 char(1000)) nologging;

insert /*+ append */ into test select rownum, to_char(rownum), to_char(rownum), to_char(rownum), to_char(rownum), to_char(rownum)
from dba_objects a, dba_objects b where rownum < 4000000;

commit;

create index test_ix on test (tid) nologging;

exec DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=> USER, TABNAME =>'TEST', CASCADE => TRUE,estimate_percent=>20);

创建存储过程,循环执行查询,每个循环执行十次,分别根据tid查询
1, 1001, 2001, ..., 9001
2, 1002, 2002, ..., 9002
...
1000, 2000, 3000, ..., 10000
这样每个查询只查一条记录,也就是一个block,执行的是db file sequential read。

create or replace procedure iotest1(p_start in number, p_length number)
is
 l_num1     number;
 l_num2     number;
 l_num3     number;
 l_num4     number;
 l_num5     number;
 l_num6     number;
 l_num7     number;
 l_num8     number;
 l_num9     number;
 l_num10    number;
    l_name    test.name%TYPE;
begin
 l_num1 := (p_start - 1) * p_length * 10 + 1;
 l_num2 := l_num1 + p_length;
 l_num3 := l_num2 + p_length;
 l_num4 := l_num3 + p_length;
 l_num5 := l_num4 + p_length;
 l_num6 := l_num5 + p_length;
 l_num7 := l_num6 + p_length;
 l_num8 := l_num7 + p_length;
 l_num9 := l_num8 + p_length;
 l_num10 := l_num9 + p_length;
 for i in 1..p_length loop
  begin
    select name into l_name from test where tid = l_num1;
  exception
    when others then
       null;
  end;
  begin
    select name into l_name from test where tid = l_num2;
  exception
    when others then
       null;
  end;
  begin
    select name into l_name from test where tid = l_num3;
  exception
    when others then
       null;
  end;
  begin
    select name into l_name from test where tid = l_num4;
  exception
    when others then
       null;
  end;
  begin
    select name into l_name from test where tid = l_num5;
  exception
    when others then
       null;
  end;
  begin
    select name into l_name from test where tid = l_num6;
  exception
    when others then
       null;
  end;
  begin
    select name into l_name from test where tid = l_num7;
  exception
    when others then
       null;
  end;
  begin
    select name into l_name from test where tid = l_num8;
  exception
    when others then
       null;
  end;
  begin
    select name into l_name from test where tid = l_num9;
  exception
    when others then
       null;
  end;
  begin
    select name into l_name from test where tid = l_num10;
  exception
    when others then
       null;
  end;
  l_num1 := l_num1 + 1;
  l_num2 := l_num2 + 1;
  l_num3 := l_num3 + 1;
  l_num4 := l_num4 + 1;
  l_num5 := l_num5 + 1;
  l_num6 := l_num6 + 1;
  l_num7 := l_num7 + 1;
  l_num8 := l_num8 + 1;
  l_num9 := l_num9 + 1;
  l_num10 := l_num10 + 1;
 end loop;
end;
/


SQL script. 文件iotest.sql:

spool "log/&1.log"
set timing on
set echo on

rem SET AUTOT TRACE

rem alter session set events '10046 trace name context forever, level 12';

exec iotest1(&1, &2);

select 1 from dual;

spool off


shell脚本启动并发数执行脚本iotest1.

#!/bin/bash
n=1
while (( $n <= 4 ))
do
 sqlplus "soe/soe@pft11g" @iotest.sql $n 10000 &
 n=$(( n+1 )) 
done


执行脚本,执行前先清楚buffer_cache, 这样数据总是从disk中读取。
./test.sh

alter system flush buffer_cache;

10046 trace文件:

PARSING IN CURSOR #182928975496 len=38 dep=1 uid=91 ct=3 lid=91 tim=1310448537343524 hv=2604437590 ad='cad77988' sqlid='b986t72dmt42q'
SELECT NAME FROM TEST WHERE TID = :B1
END OF STMT
PARSE #182928975496:c=0,e=110,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1408842701,tim=1310448537343523
BINDS #182928975496:
 Bind#0
  acdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
  acflg=13 fl2=206001 frm=00 csi=00 siz=24 ff=0
  kxsbbbfp=2a97610130  bln=22  avl=02  flg=09
  value=1
EXEC #182928975496:c=0,e=203,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1408842701,tim=1310448537343818
WAIT #182928975496: nam='Disk file operations I/O' ela= 8 FileOperation=2 fileno=5 filetype=2 obj#=78157 tim=1310448537343975
WAIT #182928975496: nam='db file sequential read' ela= 5591 file#=5 block#=1001732 blocks=1 obj#=78157 tim=1310448537349665
WAIT #182928975496: nam='db file sequential read' ela= 5760 file#=5 block#=1002416 blocks=1 obj#=78157 tim=1310448537355626
WAIT #182928975496: nam='db file sequential read' ela= 117 file#=5 block#=1001733 blocks=1 obj#=78157 tim=1310448537355871
WAIT #182928975496: nam='db file sequential read' ela= 4430 file#=5 block#=132 blocks=1 obj#=78156 tim=1310448537360495

...

PARSING IN CURSOR #182928973440 len=38 dep=1 uid=91 ct=3 lid=91 tim=1310448537360960 hv=2604437590 ad='cad77988' sqlid='b986t72dmt42q'
SELECT NAME FROM TEST WHERE TID = :B1
END OF STMT
PARSE #182928973440:c=0,e=47,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1408842701,tim=1310448537360958
BINDS #182928973440:
 Bind#0
  acdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
  acflg=13 fl2=206001 frm=00 csi=00 siz=24 ff=0
  kxsbbbfp=2a97610160  bln=22  avl=04  flg=09
  value=10001
EXEC #182928973440:c=0,e=139,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1408842701,tim=1310448537361178
WAIT #182928973440: nam='db file sequential read' ela= 151 file#=5 block#=1001753 blocks=1 obj#=78157 tim=1310448537361438
WAIT #182928973440: nam='db file sequential read' ela= 2646 file#=5 block#=10265 blocks=1 obj#=78156 tim=1310448537364254

...

PARSING IN CURSOR #182928943368 len=38 dep=1 uid=91 ct=3 lid=91 tim=1310448537413503 hv=2604437590 ad='cad77988' sqlid='b986t72dmt42q'
SELECT NAME FROM TEST WHERE TID = :B1
END OF STMT
PARSE #182928943368:c=0,e=41,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1408842701,tim=1310448537413502
BINDS #182928943368:
 Bind#0
  acdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
  acflg=13 fl2=206001 frm=00 csi=00 siz=24 ff=0
  kxsbbbfp=2a976102e0  bln=22  avl=04  flg=09
  value=90001

...

 Bind#0
  acdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
  acflg=13 fl2=206001 frm=00 csi=00 siz=24 ff=0
  kxsbbbfp=2a97610130  bln=22  avl=02  flg=09
  value=10000
EXEC #182928975496:c=0,e=91,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1408842701,tim=1310448606608220
WAIT #182928975496: nam='db file sequential read' ela= 330 file#=5 block#=10264 blocks=1 obj#=78156 tim=1310448606608619
FETCH #182928975496:c=0,e=414,p=1,cr=4,cu=0,mis=0,r=1,dep=1,og=1,plh=1408842701,tim=1310448606608666

...

BINDS #182928943368:
 Bind#0
  acdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
  acflg=13 fl2=206001 frm=00 csi=00 siz=24 ff=0
  kxsbbbfp=2a976102e0  bln=22  avl=02  flg=09
  value=100000
EXEC #182928943368:c=0,e=91,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1408842701,tim=1310448606612785
WAIT #182928943368: nam='db file sequential read' ela= 130 file#=5 block#=100618 blocks=1 obj#=78156 tim=1310448606612982
FETCH #182928943368:c=0,e=212,p=1,cr=4,cu=0,mis=0,r=1,dep=1,og=1,plh=1408842701,tim=1310448606613028
CLOSE #182928943368:c=0,e=1,dep=1,type=3,tim=1310448606613073

格式化10046 trace文件,等待事件都是db file sequential read:

tkprof pft11g_ora_21499.trc aa.txt

SQL ID: b986t72dmt42q Plan Hash: 1408842701

SELECT NAME
FROM
 TEST WHERE TID = :B1


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse       10      0.00       0.00          0          0          0           0
Execute 100000      9.27       9.64          0          0          0           0
Fetch   100000     13.73      46.64     100224     400222          0      100000
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total   200010     23.01      56.28     100224     400222          0      100000

Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 91     (recursive depth: 1)
Number of plan statistics captured: 10

Rows (1st) Rows (avg) Rows (max)  Row Source Operation
---------- ---------- ----------  ---------------------------------------------------
         1          1          1  TABLE ACCESS BY INDEX ROWID TEST (cr=4 pr=2 pw=0 time=6983 us cost=5 size=2006 card=1)
         1          1          1   INDEX RANGE SCAN TEST_IX (cr=3 pr=1 pw=0 time=2653 us cost=3 size=0 card=1)(object id 78157)

Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  Disk file operations I/O                        1        0.00          0.00
  db file sequential read                    100224        0.19         36.28

/***************************************************************************************/
一个session运行前后视图v$sysstat的数据:

运行前的:
SQL> select * from v$sysstat where name like '%physical%read%' and statistic# = 46;
 
STATISTIC# NAME                                                                  CLASS      VALUE    STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
        46 physical read total IO requests                                           8    4806187 3343375620
 
运行后的:
SQL> select * from v$sysstat where name like '%physical%read%' and statistic# = 46;
 
STATISTIC# NAME                                                                  CLASS      VALUE    STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
        46 physical read total IO requests                                           8    4907177 3343375620

这段时间内的single block reads的次数,这和10046中的100,224接近:
4,907,177 - 4,806,187 = 100,990

iostat的输出结果:

Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          0.00   2.42 577.98  2.02 9247.68   35.56  4623.84    17.78    16.01     0.24    0.42   0.36  20.83
sda1         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda2         0.00   0.40  0.00  0.40    0.00    6.46     0.00     3.23    16.00     0.00    6.00   6.00   0.24
sda3         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda4         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda5         0.00   0.00 577.98  0.00 9247.68    0.00  4623.84     0.00    16.00     0.21    0.36   0.36  20.59
sda6         0.00   0.00  0.00  0.20    0.00    1.62     0.00     0.81     8.00     0.00   10.00  10.00   0.20
sda7         0.00   2.02  0.00  1.41    0.00   27.47     0.00    13.74    19.43     0.03   23.29   4.86   0.69
sdb          0.00   2.02 572.53  1.41 9163.64   32.32  4581.82    16.16    16.02     0.11    0.19   0.18  10.26
sdb1         0.00   0.00 572.53  0.40 9163.64    8.08  4581.82     4.04    16.01     0.10    0.18   0.17   9.92
sdb2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb3         0.00   2.02  0.00  1.01    0.00   24.24     0.00    12.12    24.00     0.01    6.20   6.20   0.63
sdc          0.00   0.61 585.66  1.41 9373.74   29.09  4686.87    14.55    16.02     0.13    0.23   0.20  11.64
sdc1         0.00   0.00 585.66  0.40 9373.74   12.93  4686.87     6.46    16.02     0.12    0.20   0.20  11.62
sdc2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdc3         0.00   0.61  0.00  1.01    0.00   16.16     0.00     8.08    16.00     0.02   16.20   8.60   0.87
sdd          0.00   0.00 588.28  0.61 9425.45   19.39  4712.73     9.70    16.04     0.23    0.40   0.39  23.09
sdd1         0.00   0.00 588.28  0.61 9425.45   19.39  4712.73     9.70    16.04     0.23    0.40   0.39  23.09
sdd2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd3         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd4         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

利用率是20%,响应时间也是小于10ms。IOPS每个达到570。

/***************************************************************************************/
同时运行四个session运行前后的数据:

修改iotest.sh文件
#!/bin/bash
n=1
while (( $n <= 4 ))
do
        sqlplus "soe/soe@pft11g" @iotest.sql $n 10000 &
        n=$(( n+1 ))
done

SQL> select * from v$sysstat where name like '%physical%read%' and statistic# = 46;
 
STATISTIC# NAME                                                                  CLASS      VALUE    STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
        46 physical read total IO requests                                           8    5009175 3343375620
 
SQL> select * from v$sysstat where name like '%physical%read%' and statistic# = 46;
 
STATISTIC# NAME                                                                  CLASS      VALUE    STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
        46 physical read total IO requests                                           8    5413281 3343375620

5,413,281 - 5,009,175 = 404,106

iostat的输出结果:

Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          1.41   4.22 101.20  1.41 1632.13   44.98   816.06    22.49    16.34     0.91    8.88   5.81  59.66
sda1         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda2         0.00   2.01  0.00  0.40    0.00   19.28     0.00     9.64    48.00     0.01   17.00  17.00   0.68
sda3         1.41   0.00  0.20  0.00   12.85    0.00     6.43     0.00    64.00     0.00    5.00   5.00   0.10
sda4         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda5         0.00   0.00 101.00  0.00 1619.28    0.00   809.64     0.00    16.03     0.88    8.70   5.84  58.96
sda6         0.00   0.00  0.00  0.40    0.00    3.21     0.00     1.61     8.00     0.01   21.50  21.50   0.86
sda7         0.00   2.21  0.00  0.60    0.00   22.49     0.00    11.24    37.33     0.02   27.33  27.33   1.65
sdb          0.00   2.01 99.40  1.81 1590.36   40.16   795.18    20.08    16.11     1.05   10.44   6.54  66.20
sdb1         0.00   0.00 99.40  0.80 1590.36   16.06   795.18     8.03    16.03     1.04   10.44   6.61  66.20
sdb2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb3         0.00   2.01  0.00  1.00    0.00   24.10     0.00    12.05    24.00     0.01   10.60  10.60   1.06
sdc          0.00   0.60 109.84  1.41 1783.13   27.31   891.57    13.65    16.27     1.43   12.87   6.94  77.25
sdc1         0.00   0.00 109.84  0.40 1783.13   12.85   891.57     6.43    16.29     1.40   12.66   6.97  76.81
sdc2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdc3         0.00   0.60  0.00  1.00    0.00   14.46     0.00     7.23    14.40     0.04   35.80  22.00   2.21
sdd          0.00   0.00 97.79  0.80 1577.51   25.70   788.76    12.85    16.26     0.65    6.54   4.97  49.04
sdd1         0.00   0.00 97.79  0.80 1577.51   25.70   788.76    12.85    16.26     0.64    6.54   4.97  49.00
sdd2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd3         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd4         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

利用率是60%,响应时间小于30ms。IOPS每个磁盘是100左右。

运行时间为16m27s左右,

404,106 / (16 m * 60 s + 27 s) = 404,106 / (987s) = 409 iops。这和iostat的结果接近(100*4 = 400)。


/***************************************************************************************/
同时运行八个session运行前后的数据:

修改iotest.sh文件
#!/bin/bash
n=1
while (( $n <= 8 ))
do
        sqlplus "soe/soe@pft11g" @iotest.sql $n 10000 &
        n=$(( n+1 ))
done

SQL> select * from v$sysstat where name like '%physical%read%' and statistic# = 46;
 
STATISTIC# NAME                                                                  CLASS      VALUE    STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
        46 physical read total IO requests                                           8    5414157 3343375620
 
SQL> select * from v$sysstat where name like '%physical%read%' and statistic# = 46;
 
STATISTIC# NAME                                                                  CLASS      VALUE    STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
        46 physical read total IO requests                                           8    6221660 3343375620

6,221,660 - 5,414,157 = 807,503

Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          1.40   8.22 169.14 14.43 2725.45  181.16  1362.73    90.58    15.83     6.42   34.89   5.17  94.91
sda1         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda2         0.00   7.01  0.00  9.02    0.00  128.26     0.00    64.13    14.22     1.23  136.07   7.87   7.09
sda3         1.40   0.00  0.20  0.00   12.83    0.00     6.41     0.00    64.00     0.00   24.00  24.00   0.48
sda4         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda5         0.00   0.00 168.94  0.00 2712.63    0.00  1356.31     0.00    16.06     2.90   17.09   5.56  93.85
sda6         0.00   0.00  0.00  0.20    0.00    1.60     0.00     0.80     8.00     0.00   12.00  12.00   0.24
sda7         0.00   1.20  0.00  5.21    0.00   51.30     0.00    25.65     9.85     2.28  437.88  29.08  15.15
sdb          0.00   3.81 163.33  2.20 2610.02   52.91  1305.01    26.45    16.09     1.52    9.24   4.67  77.31
sdb1         0.00   0.00 163.33  0.40 2610.02    8.02  1305.01     4.01    15.99     1.48    9.05   4.70  76.97
sdb2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb3         0.00   3.81  0.00  1.80    0.00   44.89     0.00    22.44    24.89     0.05   26.67  26.56   4.79
sdc          0.00   3.61 169.14  3.01 2714.23   62.53  1357.11    31.26    16.13     1.75   10.16   4.81  82.85
sdc1         0.00   0.00 168.94  0.40 2712.63   12.83  1356.31     6.41    16.09     1.66    9.79   4.87  82.44
sdc2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdc3         0.00   3.61  0.20  2.61    1.60   49.70     0.80    24.85    18.29     0.09   32.64  12.36   3.47
sdd          0.00   0.00 167.13  0.60 2677.35   19.24  1338.68     9.62    16.08     1.86   11.11   4.88  81.88
sdd1         0.00   0.00 167.13  0.60 2677.35   19.24  1338.68     9.62    16.08     1.86   11.11   4.88  81.88
sdd2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd3         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd4         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

利用率是90%,响应时间小于30ms。IOPS每个磁盘是170左右。

运行时间为19m58s左右,

807,503 / (19 m * 60 s + 58 s) = 807,503 / (1,198s) = 674 iops。这和iostat的结果接近(170*4 = 680)。

/***************************************************************************************/
同时运行12个session运行前后的数据:

Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          0.00   0.80 207.04  1.21 3322.33   16.10  1661.17     8.05    16.03     3.26   15.59   4.48  93.26
sda1         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda2         0.00   0.80  0.00  1.01    0.00   14.49     0.00     7.24    14.40     0.03   31.60  30.00   3.02
sda3         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda4         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda5         0.00   0.00 207.04  0.00 3322.33    0.00  1661.17     0.00    16.05     3.22   15.49   4.49  93.00
sda6         0.00   0.00  0.00  0.20    0.00    1.61     0.00     0.80     8.00     0.01   39.00  39.00   0.78
sda7         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb          0.00   2.01 225.96  1.61 3621.73   38.63  1810.87    19.32    16.08     2.73   11.99   4.12  93.84
sdb1         0.00   0.00 225.96  0.60 3621.73   14.49  1810.87     7.24    16.05     2.66   11.73   4.14  93.72
sdb2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb3         0.00   2.01  0.00  1.01    0.00   24.14     0.00    12.07    24.00     0.07   70.60  70.60   7.10
sdc          0.00   1.81 218.11  2.82 3486.52   35.41  1743.26    17.71    15.94     2.77   14.00   4.11  90.70
sdc1         0.00   0.00 218.11  0.40 3486.52   12.88  1743.26     6.44    16.01     2.60   12.07   4.14  90.48
sdc2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdc3         0.00   1.81  0.00  2.41    0.00   22.54     0.00    11.27     9.33     0.17  188.92  27.00   6.52
sdd          0.00   0.00 223.74  0.80 3586.32   25.75  1793.16    12.88    16.09     3.40   15.15   4.27  95.98
sdd1         0.00   0.00 223.74  0.80 3586.32   25.75  1793.16    12.88    16.09     3.40   15.15   4.27  95.98
sdd2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd3         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd4         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

利用率是90~95%,响应时间小于30ms。IOPS每个磁盘是200左右。

SQL> select * from v$sysstat where name like '%physical%read%' and statistic# = 46;
 
STATISTIC# NAME                                                                  CLASS      VALUE    STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
        46 physical read total IO requests                                           8    1750848 3343375620
 
SQL> select * from v$sysstat where name like '%physical%read%' and statistic# = 46;
 
STATISTIC# NAME                                                                  CLASS      VALUE    STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
        46 physical read total IO requests                                           8    2958415 3343375620
 
1,750,848 - 2,958,415 = 1,207,567

运行时间为24m02s左右,

1,207,567 / (24 m * 60 s + 2 s) = 1,207,567 / (1,442s) = 837 iops。这和iostat的结果接近(200*4 = 800)。

/***************************************************************************************/
同时运行16个session运行前后的数据:

Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util
sda          0.00   6.22 244.98  2.81 3910.04   71.69  1955.02    35.84    16.07     3.68   14.89   3.92  97.05
sda1         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda2         0.00   4.22  0.00  0.40    0.00   36.95     0.00    18.47    92.00     0.03   63.00  63.00   2.53
sda3         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda4         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda5         0.00   0.00 244.98  0.80 3910.04    5.82  1955.02     2.91    15.93     3.51   14.31   3.95  97.05
sda6         0.00   0.00  0.00  0.20    0.00    1.61     0.00     0.80     8.00     0.01   62.00  62.00   1.24
sda7         0.00   2.01  0.00  1.41    0.00   27.31     0.00    13.65    19.43     0.14   97.14  64.57   9.08
sdb          0.00   3.21 247.19  2.21 3980.72   51.41  1990.36    25.70    16.17     4.80   19.21   3.95  98.53
sdb1         0.00   0.00 247.19  0.60 3980.72   14.46  1990.36     7.23    16.12     4.45   17.94   3.97  98.25
sdb2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdb3         0.00   3.21  0.00  1.61    0.00   36.95     0.00    18.47    23.00     0.34  216.12 213.00  34.22
sdc          0.00   0.20 238.76  0.40 3852.21   14.46  1926.10     7.23    16.17     5.27   22.06   4.15  99.30
sdc1         0.00   0.00 238.76  0.20 3852.21    6.43  1926.10     3.21    16.15     5.26   22.04   4.15  99.18
sdc2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdc3         0.00   0.20  0.00  0.20    0.00    8.03     0.00     4.02    40.00     0.01   43.00  44.00   0.88
sdd          0.00   0.00 241.77  0.60 3871.49   19.28  1935.74     9.64    16.05     2.87   11.81   3.93  95.28
sdd1         0.00   0.00 241.77  0.60 3871.49   19.28  1935.74     9.64    16.05     2.87   11.81   3.93  95.28
sdd2         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd3         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00
sdd4         0.00   0.00  0.00  0.00    0.00    0.00     0.00     0.00     0.00     0.00    0.00   0.00   0.00

利用率是95~99%,响应时间小于10~200ms。IOPS每个磁盘是240左右。

SQL> select * from v$sysstat where name like '%physical%read%' and statistic# = 46;
 
STATISTIC# NAME                                                                  CLASS      VALUE    STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
        46 physical read total IO requests                                           8    2958647 3343375620
 
SQL> select * from v$sysstat where name like '%physical%read%' and statistic# = 46;
 
STATISTIC# NAME                                                                  CLASS      VALUE    STAT_ID
---------- ---------------------------------------------------------------- ---------- ---------- ----------
        46 physical read total IO requests                                           8    4571005 3343375620

4,571,005 - 2,958,647 = 1,612,358

运行时间为29m38s左右,

1,612,358 / (29 m * 60 s + 38 s) = 1,612,358 / (1,778s) = 906 iops。这和iostat的结果接近(240*4 = 960)。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25105315/viewspace-702028/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/25105315/viewspace-702028/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
标题 Embedded wire feed forward equalization Embedded wire feed forward equalization Embedded wire feed forward equalization Embedded wire feed forward equalization Feed-forward optical equalization using an electro-optic modulator with a multi-segment electrode and distributed drivers Method and apparatus for block-wise decision-feedback equalization for wireless communication Method and apparatus for block-wise decision-feedback equalization for wireless communication Method and apparatus for block-wise decision-feedback equalization for wireless communication Feed-forward optical equalization using an electro-optic modulator with a multi-segment electrode and distributed drivers Feed-forward optical equalization using an electro-optic modulator with a multi-segment electrode and distributed drivers Dual decision equalization method and device Feed-forward equalizer architectures Feed-forward equalizer architectures Method and apparatus for block-wise decision-feedback equalization for wireless communication Feed forward equalizer and a method for analog equalization of a data signal On-demand feed forward equalizer with distributed arithmetic architecture and method Feed forward equalizer and a method for analog equalization of a data signal Decision feedback equalization implementation of partial-response signaling in a magnetic recording channel Sparse and reconfigurable floating tap feed forward equalization Sparse and reconfigurable floating tap feed forward equalization Feed-forward/feedback system and method for non-causal channel equalization Feed-forward/feedback system and method for non-causal channel equalization Dual decision equalization apparatus Nested feed-forward optical equalization using an electro-optic modulator with a multi-segment electrode Nested feed-forward optical equalization using an electro-optic modulator with a multi-segment electrode Modified gain non-causal channel equalization using feed-forward and feedback compensation System and method to enhance feed-forward equalization in a high-speed serial interface Systems and methods for performing combined equalization in communication systems Systems and methods for performing combined equalization in communication systems Method and apparatus for block-wise decision-feedback equalization for wireless communication External dqs bi-directional loopback with use of feed forward equalization path External DQS bi-directional loopback with use of feed forward equalization path Method and apparatus for block-wise decision-feedback equalization for wireless communication Method and apparatus for block-wise decision-feedback equalization for wireless communication Method and apparatus for block-wise decision-feedback equalization for wireless communication Feed-forward equalization in a receiver Feed-forward equalization in a receiver Method and apparatus for block-wise decision-feedback equalization for wireless communication Method and apparatus for block-wise decision-feedback equalization for wireless communication Feed forward equalizer controlled by FEC correction rates Feed forward equalizer controlled by FEC correction rates Method and apparatus for adaptive dual decision equalization in multipath fading channels Method and apparatus for adaptive dual decision equalization in multipath fading channels Equalization amplifier Method And System For A Distributed Mach-Zehnder Interferometer With Integrated Feed Forward Equalizer Self calibrating transmit path correction system Adaptive turbo decision feedback equalization method and device Equalizer and method applied thereto Equalizer and method applied thereto Adaptive turbo decision feedback equalization method and device Adaptive equalizers and methods for carrying out equalization with a precoded transmitter Single-carrier receiver having a channel equalizer interacting with a Trellis decoder and a channel equalization method therefor Decision feedback equalizer and control method thereof Decision Feedback Equalizer and Control Method Thereof Single-carrier receiver having a channel equalizer interacting with a Trellis decoder and a channel equalization method therefor Method of equalization in digital mobile communication with improved tracking ability Feed-forward equalizer architectures Receiver for high rate digital communication system Feed-forward DC restoration in a perpendicular magnetic read channel Feed-forward DC restoration in a perpendicular magnetic read channel Receiver for high rate digital communication system Equalization system and method thereof Equalization system and method thereof Equalization device and equalizing method thereof Feed-forward equalizer architectures Equalization device and equalizing method thereof Feed forward equalizer with power-optimized distributed arithmetic architecture and method Method and system for low-power integrating decision feedback equalizer with fast switched-capacitor feed forward path Methods and systems for digitall
SQUASHFS 1.3r3 - A squashed read-only filesystem for Linux Copyright 2004 Phillip Lougher ([email protected]) Released under the GPL licence (version 2 or later). Squashfs is currently at version 1.3 release 3. Please see the CHANGES file for recent changes to squashfs. Squashfs is a highly compressed read-only filesystem for Linux. It uses zlib compression to compress both files, inodes and directories. Inodes in the system are very small and all blocks are packed to minimise data overhead. Block sizes greater than 4K are supported up to a maximum of 32K. Squashfs is intended for general read-only filesystem use, for archival use (i.e. in cases where a .tar.gz file may be used), and in constrained block device/memory systems (e.g. embedded systems) where low overhead is needed. The section 'mksquashfs' gives information on using the mksquashfs tool to create and append to squashfs filesystems. The 'using squashfs' section gives information on mounting and using squashfs filesystems stored on block devices and as normal files using the loopback device. 1. Squashfs overview -------------------- 1. Data, inodes and directories are compressed. 2. Squashfs stores full uid/gids (32 bits), and file creation time. 3. Files up to 2^32 bytes are supported. Filesystems can be up to 2^32 bytes. 4. Inode and directory data are highly compacted, and packed on byte boundaries. Each compressed inode is on average 8 bytes in length (the exact length varies on file type, i.e. regular file, directory, symbolic link, and block/char device inodes have different sizes). 5. Squashfs can use block sizes up to 32K (the default size is 32K). Using 32K blocks achieves greater compression ratios than the normal 4K block size. 6. File duplicates are detected and removed. 7. Both big and little endian architectures are supported. Squashfs can mount filesystems created on different byte order machines. 2. mksquashfs ------------- As squashfs is a read-only filesystem, the mksquashfs program must be used to create populated squashfs filesystems. Beginning with Squashfs 1.2, mksquashfs will also append directories and files to pre-existing squashfs filesystems, see the following 'appending to squashfs filesystems' subsection. SYNTAX:mksquashfs source1 source2 ... dest [options] [-e list of exclude dirs/files] Options are -info print files written to filesystem -b block size size of blocks in filesystem, default 32768 -noappend Do not append to existing filesystem on dest, write a new filesystem This is the default action if dest does not exist, or if no filesystem is on it -keep-as-directory If one source directory is specified, create a root directory containing that directory, rather than the contents of the directory -root-becomes name When appending source files/directories, make the original root become a subdirectory in the new root called name, rather than adding the new source items to the original root -noI -noInodeCompression do not compress inode table -noD -noDataCompression do not compress data blocks -nopad do not pad filesystem to a multiple of 4K -check_data add checkdata for greater filesystem checks -le create a little endian filesystem -be create a big endian filesystem -ef exclude file file is a list of exclude dirs/files - one per line -version print version, licence and copyright message Source1 source2 ... are the source directories/files containing the files/directories that will form the squashfs filesystem. If a single directory is specified (i.e. mksquashfs source output_fs) the squashfs filesystem will consist of that directory, with the top-level root directory corresponding to the source directory. If multiple source directories or files are specified, mksquashfs will merge the specified sources into a single filesystem, with the root directory containing each of the source files/directories. The name of each directory entry will be the basename of the source path. If more than one source entry maps to the same name, the conflicts are named xxx_1, xxx_2, etc. where xxx is the original name. To make this clear, take two example directories. Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". Source directory "goodies" contains "goodies1", "goodies2" and "goodies3". usage example 1: %mksquashfs /home/phillip/test output_fs This will generate a squashfs filesystem with root entries "file1", "file2" and "dir1". example 2: %mksquashfs /home/phillip/test goodies output_fs This will create a squashfs filesystem with the root containing entries "test" and "goodies" corresponding to the source directories "/home/phillip/test" and "goodies". example 3: %mksquashfs /home/phillip/test goodies test output_fs This is the same as the previous example, except a third source directory "test" has been specified. This conflicts with the first directory named "test" and will be renamed "test_1". Multiple sources allow filesystems to be generated without needing to copy all source files into a common directory. This simplifies creating filesystems. The -keep-as-directory option can be used when only one source directory is specified, and you wish the root to contain that directory, rather than the contents of the directory. For example: example 4: %mksquashfs /home/phillip/test output_fs -keep-as-directory This is the same as example 1, except for -keep-as-directory. This will generate a root directory containing directory "test", rather than the "test" directory contents "file1", "file2" and "dir1". The Dest argument is the destination where the squashfs filesystem will be written. This can either be a conventional file or a block device. If the file doesn't exist it will be created, if it does exist and a squashfs filesystem exists on it, mksquashfs will append. The -noappend option will write a new filesystem irrespective of whether an existing filesystem is present. The -e and -ef options allow files/directories to be specified which are excluded from the output filesystem. The -e option takes the exclude files/directories from the command line, the -ef option takes the exlude files/directories from the specified exclude file, one file/directory per line. If an exclude file/directory is absolute (i.e. prefixed with /, ../, or ./) the entry is treated as absolute, however, if an exclude file/directory is relative, it is treated as being relative to each of the sources in turn, i.e. %mksquashfs /tmp/source1 source2 output_fs -e ex1 /tmp/source1/ex2 out/ex3 Will generate exclude files /tmp/source1/ex2, /tmp/source1/ex1, source2/ex1, /tmp/source1/out/ex3 and source2/out/ex3. The -e and -ef exclude options are usefully used in archiving the entire filesystem, where it is wished to avoid archiving /proc, and the filesystem being generated, i.e. %mksquashfs / /tmp/root.sqsh -e proc /tmp/root.sqsh Multiple -ef options can be specified on the command line, and the -ef option can be used in conjuction with the -e option. The -info option displays the files/directories as they are compressed and added to the filesystem. The compression percentage achieved is printed, with the original uncompressed size. If the compression percentage is listed as 0% it means the file is a duplicate. The -b option allows the block size to be selected, this can be either 512, 1024, 2048, 4096, 8192, 16384, or 32768 bytes. The -noI and -noD options (also -noInodeCompression and -noDataCompression) can be used to force mksquashfs to not compress inodes/directories and data respectively. Giving both options generates an uncompressed filesystem. The -le and -be options can be used to force mksquashfs to generate a little endian or big endian filesystem. Normally mksquashfs will generate a filesystem in the host byte order. Squashfs, for portability, will mount different ordered filesystems (i.e. it can mount big endian filesystems running on a little endian machine), but these options can be used for greater optimisation. The -nopad option informs mksquashfs to not pad the filesystem to a 4K multiple. This is performed by default to enable the output filesystem file to be mounted by loopback, which requires files to be a 4K multiple. If the filesystem is being written to a block device, or is to be stored in a bootimage, the extra pad bytes are not needed. 2.1 appending to squashfs filesystems ------------------------------------- Beginning with squashfs1.2, mksquashfs can append to existing squashfs filesystems. Three extra options "-noappend", "-keep-as-directory", and "root-becomes" have been added. Running squashfs with the destination directory containing an existing filesystem, will add the source items to the existing filesystem. By default, the source items are added to the existing root directory. To make this clear... An existing filesystem "image" contains root entries "old1", and "old2". Source directory "/home/phillip/test" contains "file1", "file2" and "dir1". example 1: %mksquashfs /home/phillip/test image Will create a new "image" with root entries "old1", "old2", "file1", "file2" and "dir1" example 2: %mksquashfs /home/phillip/test image -keep-as-directory Will create a new "image" with root entries "old1", "old2", and "test". As shown in the previous section, for single source directories '-keep-as-directory' adds the source directory rather than the contents of the directory. example 3: %mksquashfs /home/phillip/test image -keep-as-directory -root-becomes original-root Will create a new "image" with root entries "original-root", and "test". The '-root-becomes' option specifies that the original root becomes a subdirectory in the new root, with the specified name. The append option with file duplicate detection, means squashfs can be used as a simple versioning archiving filesystem. A squashfs filesystem can be created with for example the linux-2.4.19 source. Appending the linux-2.4.20 source will create a filesystem with the two source trees, but only the changed files will take extra room, the unchanged files will be detected as duplicates. 3. Using squashfs ----------------- Squashfs filesystems should be mounted with 'mount' with the filesystem type 'squashfs'. If the filesystem is on a block device, the filesystem can be mounted directly, e.g. %mount -t squashfs /dev/sda1 /mnt Will mount the squashfs filesystem on "/dev/sda1" under the directory "/mnt". If the squashfs filesystem has been written to a file, the loopback device can be used to mount it (loopback support must be in the kernel), e.g. %mount -t squashfs image /mnt -o loop Will mount the squashfs filesystem in the file "image" under the directory "/mnt". 4. Filesystem layout -------------------- Brief filesystem design notes follow. A squashfs filesystem consists of five parts, packed together on a byte alignment: --------------- | superblock | |---------------| | data | | blocks | |---------------| | inodes | |---------------| | directories | |---------------| | uid/gid | | lookup table | --------------- Compressed data blocks are written to the filesystem as files are read from the source directory, and checked for duplicates. Once all file data has been written the completed inode, directory and uid/gid lookup tables are written. 4.1 Metadata ------------ Metadata (inodes and directories) are compressed in 8Kbyte blocks. Each compressed block is prefixed by a two byte length, the top bit is set if the block is uncompressed. A block will be uncompressed if the -noI option is set, or if the compressed block was larger than the uncompressed block. Inodes are packed into the metadata blocks, and are not aligned to block boundaries, therefore inodes overlap compressed blocks. An inode is identified by a two field tuple <start address of compressed block : offset into de-compressed block>. Inode contents vary depending on the file type. The base inode consists of: base inode: Inode type Mode uid index gid index The inode type is 4 bits in size, and the mode is 12 bits. The uid and gid indexes are 4 bits in length. Ordinarily, this will allow 16 unique indexes into the uid table. To minimise overhead, the uid index is used in conjunction with the spare bit in the file type to form a 48 entry index as follows: inode type 1 - 5: uid index = uid inode type 5 -10: uid index = 16 + uid inode type 11 - 15: uid index = 32 + uid In this way 48 unique uids are supported using 4 bits, minimising data inode overhead. The 4 bit gid index is used to index into a 15 entry gid table. Gid index 15 is used to indicate that the gid is the same as the uid. This prevents the 15 entry gid table filling up with the common case where the uid/gid is the same. The data contents of symbolic links are stored immediately after the symbolic link inode, inside the inode table. This allows the normally small symbolic link to be compressed as part of the inode table, achieving much greater compression than if the symbolic link was compressed individually. Similarly, the block index for regular files is stored immediately after the regular file inode. The block index is a list of block lengths (two bytes each), rather than block addresses, saving two bytes per block. The block address for a given block is computed by the summation of the previous block lengths. This takes advantage of the fact that the blocks making up a file are stored contiguously in the filesystem. The top bit of each block length is set if the block is uncompressed, either because the -noD option is set, or if the compressed block was larger than the uncompressed block. 4.2 Directories --------------- Like inodes, directories are packed into the metadata blocks, and are not aligned on block boundaries, therefore directories can overlap compressed blocks. A directory is, again, identified by a two field tuple <start address of compressed block containing directory start : offset into de-compressed block>. Directories are organised in a slightly complex way, and are not simply a list of file names and inode tuples. The organisation takes advantage of the observation that in most cases, the inodes of the files in the directory will be in the same compressed metadata block, and therefore, the inode tuples will have the same start block. Directories are therefore organised in a two level list, a directory header containing the shared start block value, and a sequence of directory entries, each of which share the shared start block. A new directory header is written once/if the inode start block changes. The directory header/directory entry list is repeated as many times as necessary. The organisation is as follows: directory_header: count (8 bits) inode start block (24 bits) directory entry: * count inode offset (13 bits) inode type (3 bits) filename size (8 bits) filename This organisation saves on average 3 bytes per filename. 4.3 File data ------------- File data is compressed on a block by block basis and written to the filesystem. The filesystem supports up to 32K blocks, which achieves greater compression ratios than the Linux 4K page size. The disadvantage with using greater than 4K blocks (and the reason why most filesystems do not), is that the VFS reads data in 4K pages. The filesystem reads and decompresses a larger block containing that page (e.g. 32K). However, only 4K can be returned to the VFS, resulting in a very inefficient filesystem, as 28K must be thrown away. Squashfs, solves this problem by explicitly pushing the extra pages into the page cache. 5. Author info -------------- Squashfs was written by Phillip Lougher, email [email protected], in Chepstow, Wales, UK. If you like the program, or have any problems, then please email me, as it's nice to get feedback!
package org.hds.Graphics; import java.net.*; import java.io.*; import java.util.*; import java.awt.*; import java.awt.image.*; public class GifDecoder { /** * File read status: No errors. */ public static final int STATUS_OK = 0; /** * File read status: Error decoding file (may be partially decoded) */ public static final int STATUS_FORMAT_ERROR = 1; /** * File read status: Unable to open source. */ public static final int STATUS_OPEN_ERROR = 2; protected BufferedInputStream in; protected int status; protected int width; // full image width protected int height; // full image height protected boolean gctFlag; // global color table used protected int gctSize; // size of global color table protected int loopCount = 1; // iterations; 0 = repeat forever protected int[] gct; // global color table protected int[] lct; // local color table protected int[] act; // active color table protected int bgIndex; // background color index protected int bgColor; // background color protected int lastBgColor; // previous bg color protected int pixelAspect; // pixel aspect ratio protected boolean lctFlag; // local color table flag protected boolean interlace; // interlace flag protected int lctSize; // local color table size protected int ix, iy, iw, ih; // current image rectangle protected Rectangle lastRect; // last image rect protected BufferedImage image; // current frame protected BufferedImage lastImage; // previous frame protected byte[] block = new byte[256]; // current data block protected int blockSize = 0; // block size // last graphic control extension info protected int dispose = 0; // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev protected int lastDispose = 0; protected boolean transparency = false; // use transparent color protected int delay = 0; // delay in milliseconds protected int totaldelay = 0; // delay in milliseconds protected int transIndex; // transparent color index protected static final int MaxStackSize = 4096; // max decoder pixel stack size // LZW decoder working arrays protected short[] prefix; protected byte[] suffix; protected byte[] pixelStack; protected byte[] pixels; protected ArrayList frames; // frames read from current file protected int frameCount; static class GifFrame { public GifFrame(BufferedImage im, int del) { image = im; delay = del; } public BufferedImage image; public int delay; } /** * Gets display duration for specified frame. * * @param n int index of frame * @return delay in milliseconds */ public int getDelay(int n) { // delay = -1; if ((n >= 0) && (n < frameCount)) { delay = ((GifFrame) frames.get(n)).delay; } return delay; } /** * Gets the number of frames read from file. * @return frame count */ public int getFrameCount() { return frameCount; } /** * Gets the number of frames read from file. * @return frame count */ public int gettotaldelay() { return totaldelay; } /** * Gets the first (or only) image read. * * @return BufferedImage containing first frame, or null if none. */ public BufferedImage getImage() { return getFrame(0); } /** * Gets the "Netscape" iteration count, if any. * A count of 0 means repeat indefinitiely. * * @return iteration count if one was specified, else 1. */ public int getLoopCount() { return loopCount; } /** * Creates new frame image from current data (and previous * frames as specified by their disposition codes). */ protected void setPixels() { // expose destination image's pixels as int array int[] dest = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); // fill in starting image contents based on last image's dispose code if (lastDispose > 0) { if (lastDispose == 3) { // use image before last int n = frameCount - 2; if (n > 0) { lastImage = getFrame(n - 1); } else { lastImage = null; } } if (lastImage != null) { int[] prev = ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData(); System.arraycopy(prev, 0, dest, 0, width * height); // copy pixels if (lastDispose == 2) { // fill last image rect area with background color Graphics2D g = image.createGraphics(); Color c = null; if (transparency) { c = new Color(0, 0, 0, 0); // assume background is transparent } else { c = new Color(lastBgColor); // use given background color } g.setColor(c); g.setComposite(AlphaComposite.Src); // replace area g.fill(lastRect); g.dispose(); } } } // copy each source line to the appropriate place in the destination int pass = 1; int inc = 8; int iline = 0; for (int i = 0; i < ih; i++) { int line = i; if (interlace) { if (iline >= ih) { pass++; switch (pass) { case 2 : iline = 4; break; case 3 : iline = 2; inc = 4; break; case 4 : iline = 1; inc = 2; } } line = iline; iline += inc; } line += iy; if (line < height) { int k = line * width; int dx = k + ix; // start of line in dest int dlim = dx + iw; // end of dest line if ((k + width) < dlim) { dlim = k + width; // past dest edge } int sx = i * iw; // start of line in source while (dx < dlim) { // map color and insert in destination int index = ((int) pixels[sx++]) & 0xff; int c = act[index]; if (c != 0) { dest[dx] = c; } dx++; } } } } /** * Gets the image contents of frame n. * * @return BufferedImage representation of frame, or null if n is invalid. */ public BufferedImage getFrame(int n) { BufferedImage im = null; if ((n >= 0) && (n < frameCount)) { im = ((GifFrame) frames.get(n)).image; } return im; } /** * Gets image size. * * @return GIF image dimensions */ public Dimension getFrameSize() { return new Dimension(width, height); } /** * Reads GIF image from stream * * @param BufferedInputStream containing GIF file. * @return read status code (0 = no errors) */ public int read(BufferedInputStream is) { init(); if (is != null) { in = is; readHeader(); if (!err()) { readContents(); if (frameCount < 0) { status = STATUS_FORMAT_ERROR; } } } else { status = STATUS_OPEN_ERROR; } try { is.close(); } catch (IOException e) { } return status; } /** * Reads GIF image from stream * * @param InputStream containing GIF file. * @return read status code (0 = no errors) */ public int read(InputStream is) { init(); if (is != null) { if (!(is instanceof BufferedInputStream)) is = new BufferedInputStream(is); in = (BufferedInputStream) is; readHeader(); if (!err()) { readContents(); if (frameCount < 0) { status = STATUS_FORMAT_ERROR; } } } else { status = STATUS_OPEN_ERROR; } try { is.close(); } catch (IOException e) { } return status; } /** * Reads GIF file from specified file/URL source * (URL assumed if name contains ":/" or "file:") * * @param name String containing source * @return read status code (0 = no errors) */ public int read(String name) { status = STATUS_OK; try { name = name.trim().toLowerCase(); if ((name.indexOf("file:") >= 0) || (name.indexOf(":/") > 0)) { URL url = new URL(name); in = new BufferedInputStream(url.openStream()); } else { in = new BufferedInputStream(new FileInputStream(name)); } status = read(in); } catch (IOException e) { status = STATUS_OPEN_ERROR; } return status; } /** * Decodes LZW image data into pixel array. * Adapted from John Cristy's ImageMagick. */ protected void decodeImageData() { int NullCode = -1; int npix = iw * ih; int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi, pi; if ((pixels == null) || (pixels.length < npix)) { pixels = new byte[npix]; // allocate new pixel array } if (prefix == null) prefix = new short[MaxStackSize]; if (suffix == null) suffix = new byte[MaxStackSize]; if (pixelStack == null) pixelStack = new byte[MaxStackSize + 1]; // Initialize GIF data stream decoder. data_size = read(); clear = 1 << data_size; end_of_information = clear + 1; available = clear + 2; old_code = NullCode; code_size = data_size + 1; code_mask = (1 << code_size) - 1; for (code = 0; code < clear; code++) { prefix[code] = 0; suffix[code] = (byte) code; } // Decode GIF pixel stream. datum = bits = count = first = top = pi = bi = 0; for (i = 0; i < npix;) { if (top == 0) { if (bits < code_size) { // Load bytes until there are enough bits for a code. if (count == 0) { // Read a new data block. count = readBlock(); if (count <= 0) break; bi = 0; } datum += (((int) block[bi]) & 0xff) << bits; bits += 8; bi++; count--; continue; } // Get the next code. code = datum & code_mask; datum >>= code_size; bits -= code_size; // Interpret the code if ((code > available) || (code == end_of_information)) break; if (code == clear) { // Reset decoder. code_size = data_size + 1; code_mask = (1 << code_size) - 1; available = clear + 2; old_code = NullCode; continue; } if (old_code == NullCode) { pixelStack[top++] = suffix[code]; old_code = code; first = code; continue; } in_code = code; if (code == available) { pixelStack[top++] = (byte) first; code = old_code; } while (code > clear) { pixelStack[top++] = suffix[code]; code = prefix[code]; } first = ((int) suffix[code]) & 0xff; // Add a new string to the string table, if (available >= MaxStackSize) break; pixelStack[top++] = (byte) first; prefix[available] = (short) old_code; suffix[available] = (byte) first; available++; if (((available & code_mask) == 0) && (available < MaxStackSize)) { code_size++; code_mask += available; } old_code = in_code; } // Pop a pixel off the pixel stack. top--; pixels[pi++] = pixelStack[top]; i++; } for (i = pi; i < npix; i++) { pixels[i] = 0; // clear missing pixels } } /** * Returns true if an error was encountered during reading/decoding */ protected boolean err() { return status != STATUS_OK; } /** * Initializes or re-initializes reader */ protected void init() { status = STATUS_OK; frameCount = 0; frames = new ArrayList(); gct = null; lct = null; } /** * Reads a single byte from the input stream. */ protected int read() { int curByte = 0; try { curByte = in.read(); } catch (IOException e) { status = STATUS_FORMAT_ERROR; } return curByte; } /** * Reads next variable length block from input. * * @return number of bytes stored in "buffer" */ protected int readBlock() { blockSize = read(); int n = 0; if (blockSize > 0) { try { int count = 0; while (n < blockSize) { count = in.read(block, n, blockSize - n); if (count == -1) break; n += count; } } catch (IOException e) { } if (n < blockSize) { status = STATUS_FORMAT_ERROR; } } return n; } /** * Reads color table as 256 RGB integer values * * @param ncolors int number of colors to read * @return int array containing 256 colors (packed ARGB with full alpha) */ protected int[] readColorTable(int ncolors) { int nbytes = 3 * ncolors; int[] tab = null; byte[] c = new byte[nbytes]; int n = 0; try { n = in.read(c); } catch (IOException e) { } if (n < nbytes) { status = STATUS_FORMAT_ERROR; } else { tab = new int[256]; // max size to avoid bounds checks int i = 0; int j = 0; while (i < ncolors) { int r = ((int) c[j++]) & 0xff; int g = ((int) c[j++]) & 0xff; int b = ((int) c[j++]) & 0xff; tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b; } } return tab; } /** * Main file parser. Reads GIF content blocks. */ protected void readContents() { // read GIF file content blocks boolean done = false; while (!(done || err())) { int code = read(); switch (code) { case 0x2C : // image separator readImage(); break; case 0x21 : // extension code = read(); switch (code) { case 0xf9 : // graphics control extension readGraphicControlExt(); break; case 0xff : // application extension readBlock(); String app = ""; for (int i = 0; i < 11; i++) { app += (char) block[i]; } if (app.equals("NETSCAPE2.0")) { readNetscapeExt(); } else skip(); // don't care break; default : // uninteresting extension skip(); } break; case 0x3b : // terminator done = true; break; case 0x00 : // bad byte, but keep going and see what happens break; default : status = STATUS_FORMAT_ERROR; } } } /** * Reads Graphics Control Extension values */ protected void readGraphicControlExt() { read(); // block size int packed = read(); // packed fields dispose = (packed & 0x1c) >> 2; // disposal method if (dispose == 0) { dispose = 1; // elect to keep old image if discretionary } transparency = (packed & 1) != 0; delay = readShort() * 10; // delay in milliseconds transIndex = read(); // transparent color index read(); // block terminator } /** * Reads GIF file header information. */ protected void readHeader() { String id = ""; for (int i = 0; i < 6; i++) { id += (char) read(); } /* * 如果id!=GIF89a佳毅判断不了暂时不用 */ if(!id.equals("GIF89a")) { status = STATUS_FORMAT_ERROR; return; } if (!id.startsWith("GIF")) { status = STATUS_FORMAT_ERROR; return; } readLSD(); if (gctFlag && !err()) {//全局定义颜色列表 gct = readColorTable(gctSize); bgColor = gct[bgIndex]; } } /** * Reads next frame image * 读每帧图片信息 */ protected void readImage() { ix = readShort(); // (sub)image position & size iy = readShort(); iw = readShort(); ih = readShort(); if(ix > width || iy > height || iw > width || ih > height)//当帧位置大小有问题佳毅不支持 {status = STATUS_FORMAT_ERROR;} int packed = read(); lctFlag = (packed & 0x80) != 0; // 1 - local color table flag局部颜色列表 interlace = (packed & 0x40) != 0; // 2 - interlace flag // 3 - sort flag // 4-5 - reserved lctSize = 2 << (packed & 7); // 6-8 - local color table size if (lctFlag) { status = STATUS_FORMAT_ERROR;//局部颜色列表 佳毅不支持 lct = readColorTable(lctSize); // read table act = lct; // make local table active } else { act = gct; // make global table active if (bgIndex == transIndex) bgColor = 0; } int save = 0; if (transparency) { save = act[transIndex]; act[transIndex] = 0; // set transparent color if specified } if (act == null) { status = STATUS_FORMAT_ERROR; // no color table defined } if (err()) return; decodeImageData(); // decode pixel data skip(); if (err()) return; frameCount++; // create new image to receive frame data image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE); setPixels(); // transfer pixel data to image frames.add(new GifFrame(image, delay)); // add image to frame list totaldelay += delay; if (transparency) { act[transIndex] = save; } resetFrame(); } /** * Reads Logical Screen Descriptor */ protected void readLSD() { // logical screen size width = readShort(); height = readShort(); // packed fields int packed = read(); gctFlag = (packed & 0x80) != 0; // 1 : global color table flag 全局定义颜色列表 true // 2-4 : color resolution // 5 : gct sort flag gctSize = 2 << (packed & 7); // 6-8 : gct size bgIndex = read(); // background color index pixelAspect = read(); // pixel aspect ratio } /** * Reads Netscape extenstion to obtain iteration count */ protected void readNetscapeExt() { do { readBlock(); if (block[0] == 1) { // loop count sub-block int b1 = ((int) block[1]) & 0xff; int b2 = ((int) block[2]) & 0xff; loopCount = (b2 << 8) | b1; } } while ((blockSize > 0) && !err()); } /** * Reads next 16-bit value, LSB first */ protected int readShort() { // read 16-bit value, LSB first return read() | (read() << 8); } /** * Resets frame state for reading next image. */ protected void resetFrame() { lastDispose = dispose; lastRect = new Rectangle(ix, iy, iw, ih); lastImage = image; lastBgColor = bgColor; int dispose = 0; boolean transparency = false; int delay = 0; lct = null; } protected void skip() { do { readBlock(); } while ((blockSize > 0) && !err()); } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值