forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

SLow performance with DIRECT ACCESS unformatted files
Goto page Previous  1, 2, 3, 4  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Mon Jan 26, 2015 12:12 am    Post subject: Reply with quote

Bill,
You posted:
Quote:
There's disk cache, and there is disk cache....

Yes, Windows is an animal all to its own.

My experience of Windows 7 is that the disk cacheing works very well. It is much improved from XP. What sort of animal were you considering ?

My suggestion is that you do not use the "share=" option at all as depending on your access rights for the disk/directory you are using, it is a problem you don't need to introduce. If you are wanting to do inter-process locking, do it on a small file, not one that has large data transfers.

Another possible explanation for the times observed is when and how often the disk cache is being flushed to the disk. This may explain the case of write delays, as the cache may be flushed after each write.
When things are working well, the only flush takes place when the file is closed, although this is not always observed from the results.

I have a disk I/O test program for direct access files, although it typically uses larger blocks. The test sequence is:
- Open file
- Write N blocks
- Read N blocks
- Write N/10 blocks randomly
- Read N/10 blocks randomly
- Close file

I have 3 file access libraries:
- Standard Fortran
- My variable block size random access library (based on Fortran with extra buffers)
- File access library based on FTN95 file manipulation routines (or ifort routines)

I have tested this for a range of N for file sizes of 1k up to 3 x installed memory.

I have found that:
- Standard Fortran works as well as available system libraries
- There was a significant improvement in disk cache from XP to Win 7
- Disk flushing does not always occur on CLOSE !!
- for medium size files that can fit in the disk cache (say less than 6gb on my 8gb pc) disk cache can be a good substitute for a SSD, although they offer more flexible performance improvements.
- Cache performance is a function of other activities on the disk.

I have not tested share= alternatives, as the purpose of the tests was to identify ways of improving large data transfers.

I would expect that the problem you are observing is due to other factors and not FTN95 I/O performance.

John
Back to top
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Mon Jan 26, 2015 1:30 am    Post subject: Reply with quote

Here is the test code I used, should you desire to replicate my tests on your machine and share the results.
Code:
!FTN95 application...
PROGRAM main
 integer print_every
 integer failed_open,failed_delete,failed_close,failed_write
 character iorecord(194)
 character*8 ddate,oper(6),share(5)
 character*10 ttime
    character*5 zzone
    integer values(8),stest
    character*20 access(6),form(6),status(6)
    data status/'replace','old',   'old',   'replace',   'old',       'old'/
    data access/'direct', 'direct','direct','sequential','sequential','sequential'/
    data form/6*'unformatted'/
    data oper/   'write',  'write', 'read',  'write',     'write',     'read'/
    data share/'denynone','denyrw','denywr','denyrd','compat'/

! Test program to open a unformatted direct access file, then write several records
! then close it and try again. Each failure to open will be logged along with the error code and date/time
! a 2 second wait will be done, then re-try.
!
! The first time, we'll delete the file, then create as a new, then old from then on
!
 call date_and_time(ddate,ttime,zzone,values)
 print *,"Starting the test at: ",ddate(1:8),' ',ttime(1:10)
 max_recs=1000
 do stest=1,5 !share
 do jtest=1,6
  open(unit=15,file='testfile.dat',access=access(jtest),iostat=icode,err=12000,&
  form=form(jtest),recl=194,status=status(jtest),share=share(stest))
 ! the READ tests require that the file exists, so change 'replace' to 'old'
  start_loop = high_res_clock@(.true.)
 do 10000 i=1,max_recs
   call randomfile(iorecord,194) ! this is always left in to even out the loop timing
   !This next line must change to reflect read or write and rec= if needed
   go to (1000,1000,2000,3000,3000,4000),jtest
1000 continue
   write(15,rec=i,err=13000)iorecord
   go to 10000
2000 continue
   read(15,rec=i,err=13000,iostat=icheck)iorecord
    go to 10000
3000 continue
   write(15,err=13000)iorecord
   go to 10000
4000 continue
   read(15,err=13000)iorecord
   go to 10000
10000 continue
  end_loop = high_res_clock@(.false.)
  print *,oper(jtest),max_recs,' records took ',end_loop-start_loop,'For access=',trim(access(jtest)),&
  ' format=',trim(form(jtest)),' status=',trim(status(jtest)),' share=',trim(share(stest))
  close(unit=15)
  call sleep1@(2.)
  end do ! jtest
  end do ! stest
  pause
 stop
 13000 continue
 print *,"io error",icheck
 stop
 12000 continue
 print *,"open error",icode
 stop
 
END PROGRAM main
 subroutine randomfile(iorecord,length)
 character*1 iorecord(length)
 do i=1,length
   iorecord=char(int(255.*random@()))
 end do
  return
  end
   
Back to top
View user's profile Send private message Visit poster's website
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Mon Jan 26, 2015 1:34 am    Post subject: Reply with quote

Paul, it would be useful (to me, at least) to know how FTN95 opens a file in each of the available SHARE= modes. Right now, I can only guess. I might be able to find something with this small bit of detailed knowledge, perhaps even able to replicate in another language to identify the root cause. The way I figure it, if I found this, perhaps others have the same problem. And, if there is a root cause, it can be addressed (or not, as the case might be).

Rather than to say "Don't do it this way", perhaps the proper answer is "If you do it this way AND you get these kinds of results...".
Back to top
View user's profile Send private message Visit poster's website
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Mon Jan 26, 2015 5:22 am    Post subject: Reply with quote

Bill,

I ran your test
on Windows 7 Home Premium, Service Pack 1
i5-2300
921 GB partition of 2Tb HDD
in directory c:\temp\forum
ftn95 bill_file_io /-imp /lgo >zz
Code:
 [FTN95/Win32 Ver. 7.10.0 Copyright (c) Silverfrost Ltd 1993-2014]

    NO ERRORS  [<MAIN> FTN95/Win32 v7.10.0]
    NO ERRORS  [<RANDOMFILE> FTN95/Win32 v7.10.0]
Creating executable: c:\temp\forum\lgotemp@.exe
Program entered
 Starting the test at: 20150126 153114.426
 write           1000 rec      1.49023    sec; For ac=direct fo=unformatted st=replace sh=denynone
 write           1000 rec      1.63867    sec; For ac=direct fo=unformatted st=old sh=denynone
 read            1000 rec      1.07422    sec; For ac=direct fo=unformatted st=old sh=denynone
 write           1000 rec     0.982422    sec; For ac=sequential fo=unformatted st=replace sh=denynone
 write           1000 rec     0.978516    sec; For ac=sequential fo=unformatted st=old sh=denynone
 read            1000 rec     0.976563    sec; For ac=sequential fo=unformatted st=old sh=denynone
 write           1000 rec     0.982422    sec; For ac=direct fo=unformatted st=replace sh=denyrw
 write           1000 rec     0.972656    sec; For ac=direct fo=unformatted st=old sh=denyrw
 read            1000 rec     0.964844    sec; For ac=direct fo=unformatted st=old sh=denyrw
 write           1000 rec     0.978516    sec; For ac=sequential fo=unformatted st=replace sh=denyrw
 write           1000 rec     0.994141    sec; For ac=sequential fo=unformatted st=old sh=denyrw
 read            1000 rec     0.986328    sec; For ac=sequential fo=unformatted st=old sh=denyrw
 write           1000 rec     0.978516    sec; For ac=direct fo=unformatted st=replace sh=denywr
 write           1000 rec     0.998047    sec; For ac=direct fo=unformatted st=old sh=denywr
 read            1000 rec     0.974609    sec; For ac=direct fo=unformatted st=old sh=denywr
 write           1000 rec     0.980469    sec; For ac=sequential fo=unformatted st=replace sh=denywr
 write           1000 rec     0.974609    sec; For ac=sequential fo=unformatted st=old sh=denywr
 read            1000 rec     0.992188    sec; For ac=sequential fo=unformatted st=old sh=denywr
 write           1000 rec      1.51563    sec; For ac=direct fo=unformatted st=replace sh=denyrd
 write           1000 rec      1.56250    sec; For ac=direct fo=unformatted st=old sh=denyrd
 read            1000 rec      1.08008    sec; For ac=direct fo=unformatted st=old sh=denyrd
 write           1000 rec     0.980469    sec; For ac=sequential fo=unformatted st=replace sh=denyrd
 write           1000 rec     0.974609    sec; For ac=sequential fo=unformatted st=old sh=denyrd
 read            1000 rec     0.978516    sec; For ac=sequential fo=unformatted st=old sh=denyrd
 write           1000 rec      1.53906    sec; For ac=direct fo=unformatted st=replace sh=compat
 write           1000 rec      1.50000    sec; For ac=direct fo=unformatted st=old sh=compat
 read            1000 rec      1.08008    sec; For ac=direct fo=unformatted st=old sh=compat
 write           1000 rec     0.974609    sec; For ac=sequential fo=unformatted st=replace sh=compat
 write           1000 rec     0.984375    sec; For ac=sequential fo=unformatted st=old sh=compat
 read            1000 rec     0.976563    sec; For ac=sequential fo=unformatted st=old sh=compat
***Pause:
Enter system command or press ENTER key to restart:
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Mon Jan 26, 2015 9:14 am    Post subject: Reply with quote

Bill,

I changed randomfile to:
do i=1,length
iorecord(i)=char(int(255.*random@()))
end do
I also tidied up the formats and used SYSTEM_CLOCK for timing. I got the following results.
Code:
[FTN95/Win32 Ver. 7.10.0 Copyright (c) Silverfrost Ltd 1993-2014]

    NO ERRORS  [<MAIN> FTN95/Win32 v7.10.0]
    NO ERRORS  [<RANDOMFILE> FTN95/Win32 v7.10.0]
    NO ERRORS  [<ELAPSE_TIME> FTN95/Win32 v7.10.0]
Creating executable: c:\temp\forum\lgotemp@.exe
Program entered
 Starting the test at: 20150126 190544.999
 
write   1000 rec  0.4375 sec; For ac=direct fo=unformatted st=replace sh=denynone
write   1000 rec  0.4336 sec; For ac=direct fo=unformatted st=old sh=denynone
read    1000 rec  0.0859 sec; For ac=direct fo=unformatted st=old sh=denynone
write   1000 rec  0.0156 sec; For ac=sequential fo=unformatted st=replace sh=denynone
write   1000 rec  0.0234 sec; For ac=sequential fo=unformatted st=old sh=denynone
read    1000 rec  0.0234 sec; For ac=sequential fo=unformatted st=old sh=denynone
 
write   1000 rec  0.0156 sec; For ac=direct fo=unformatted st=replace sh=denyrw
write   1000 rec  0.0195 sec; For ac=direct fo=unformatted st=old sh=denyrw
read    1000 rec  0.0078 sec; For ac=direct fo=unformatted st=old sh=denyrw
write   1000 rec  0.0117 sec; For ac=sequential fo=unformatted st=replace sh=denyrw
write   1000 rec  0.0078 sec; For ac=sequential fo=unformatted st=old sh=denyrw
read    1000 rec  0.0117 sec; For ac=sequential fo=unformatted st=old sh=denyrw
 
write   1000 rec  0.0156 sec; For ac=direct fo=unformatted st=replace sh=denywr
write   1000 rec  0.0195 sec; For ac=direct fo=unformatted st=old sh=denywr
read    1000 rec  0.0117 sec; For ac=direct fo=unformatted st=old sh=denywr
write   1000 rec  0.0078 sec; For ac=sequential fo=unformatted st=replace sh=denywr
write   1000 rec  0.0117 sec; For ac=sequential fo=unformatted st=old sh=denywr
read    1000 rec  0.0078 sec; For ac=sequential fo=unformatted st=old sh=denywr
 
write   1000 rec  0.4180 sec; For ac=direct fo=unformatted st=replace sh=denyrd
write   1000 rec  0.4258 sec; For ac=direct fo=unformatted st=old sh=denyrd
read    1000 rec  0.0898 sec; For ac=direct fo=unformatted st=old sh=denyrd
write   1000 rec  0.0156 sec; For ac=sequential fo=unformatted st=replace sh=denyrd
write   1000 rec  0.0117 sec; For ac=sequential fo=unformatted st=old sh=denyrd
read    1000 rec  0.0313 sec; For ac=sequential fo=unformatted st=old sh=denyrd
 
write   1000 rec  0.4023 sec; For ac=direct fo=unformatted st=replace sh=compat
write   1000 rec  0.4297 sec; For ac=direct fo=unformatted st=old sh=compat
read    1000 rec  0.0859 sec; For ac=direct fo=unformatted st=old sh=compat
write   1000 rec  0.0156 sec; For ac=sequential fo=unformatted st=replace sh=compat
write   1000 rec  0.0195 sec; For ac=sequential fo=unformatted st=old sh=compat
read    1000 rec  0.0313 sec; For ac=sequential fo=unformatted st=old sh=compat

These results now show a difference for different share options, but not as dramatic as before.

John
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Mon Jan 26, 2015 10:19 am    Post subject: Reply with quote

Bill,

I did another test which is useful to compare with the previous by: - increased the record size to 1940
- introduced a test for no use of share=
The results are:
Code:

[FTN95/Win32 Ver. 7.10.0 Copyright (c) Silverfrost Ltd 1993-2014]

0011)   real      elapse_time, start_open, start_loop, end_loop
WARNING - 242: Variable START_OPEN has been given a value but never used
    NO ERRORS, 1 WARNING  [<MAIN> FTN95/Win32 v7.10.0]
    NO ERRORS  [<RANDOMFILE> FTN95/Win32 v7.10.0]
    NO ERRORS  [<DELETE_FILE> FTN95/Win32 v7.10.0]
    NO ERRORS  [<ELAPSE_TIME> FTN95/Win32 v7.10.0]
Creating executable: c:\temp\forum\lgotemp@.exe
Program entered
 Starting the test at: 20150126 201205.726
 
           for testfile1.dat
 testfile1.dat deleted
WRITE 1000 rec 0.055 sec; For ac=DIRECT     fo=UNFORMATTED st=REPLACE sh=       
WRITE 1000 rec 0.070 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=       
READ  1000 rec 0.051 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=       
 testfile1.dat deleted
WRITE 1000 rec 0.070 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=REPLACE sh=       
WRITE 1000 rec 0.063 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=       
READ  1000 rec 0.074 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=       
 
  DENYNONE for testfile2.dat
 testfile2.dat deleted
WRITE 1000 rec 0.531 sec; For ac=DIRECT     fo=UNFORMATTED st=REPLACE sh=DENYNONE
WRITE 1000 rec 0.539 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=DENYNONE
READ  1000 rec 0.141 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=DENYNONE
 testfile2.dat deleted
WRITE 1000 rec 0.066 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=REPLACE sh=DENYNONE
WRITE 1000 rec 0.074 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=DENYNONE
READ  1000 rec 0.082 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=DENYNONE
 
  DENYRW   for testfile3.dat
 testfile3.dat deleted
WRITE 1000 rec 0.070 sec; For ac=DIRECT     fo=UNFORMATTED st=REPLACE sh=DENYRW 
WRITE 1000 rec 0.070 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=DENYRW 
READ  1000 rec 0.070 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=DENYRW 
 testfile3.dat deleted
WRITE 1000 rec 0.066 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=REPLACE sh=DENYRW 
WRITE 1000 rec 0.070 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=DENYRW 
READ  1000 rec 0.074 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=DENYRW 
 
  DENYWR   for testfile4.dat
 testfile4.dat deleted
WRITE 1000 rec 0.070 sec; For ac=DIRECT     fo=UNFORMATTED st=REPLACE sh=DENYWR 
WRITE 1000 rec 0.070 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=DENYWR 
READ  1000 rec 0.070 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=DENYWR 
 testfile4.dat deleted
WRITE 1000 rec 0.066 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=REPLACE sh=DENYWR 
WRITE 1000 rec 0.066 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=DENYWR 
READ  1000 rec 0.063 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=DENYWR 
 
  DENYRD   for testfile5.dat
 testfile5.dat deleted
WRITE 1000 rec 0.797 sec; For ac=DIRECT     fo=UNFORMATTED st=REPLACE sh=DENYRD 
WRITE 1000 rec 0.621 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=DENYRD 
READ  1000 rec 0.152 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=DENYRD 
 testfile5.dat deleted
WRITE 1000 rec 0.066 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=REPLACE sh=DENYRD 
WRITE 1000 rec 0.090 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=DENYRD 
READ  1000 rec 0.074 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=DENYRD 
 
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Mon Jan 26, 2015 10:21 am    Post subject: Reply with quote

ctd.
Code:
  COMPAT   for testfile6.dat
 testfile6.dat deleted
WRITE 1000 rec 0.578 sec; For ac=DIRECT     fo=UNFORMATTED st=REPLACE sh=COMPAT 
WRITE 1000 rec 0.602 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=COMPAT 
READ  1000 rec 0.207 sec; For ac=DIRECT     fo=UNFORMATTED st=OLD     sh=COMPAT 
 testfile6.dat deleted
WRITE 1000 rec 0.066 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=REPLACE sh=COMPAT 
WRITE 1000 rec 0.074 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=COMPAT 
READ  1000 rec 0.070 sec; For ac=SEQUENTIAL fo=UNFORMATTED st=OLD     sh=COMPAT 


Fixing call randomfile now produces more expected performance.

The results also show that omitting SHARE= can improve the direct performance.
Sequential access is somewhat faster with the SHARE= options.
Is there a need for this file access management ?

You should try different combinations of rec_len and num_rec and see how the run times scale up, identifying cache usage.

The following is the latest test program I generated, where I tried to provide more consistent OPEN options. ( still not complete !!)


Code:
!FTN95 application...
 PROGRAM main
!  integer print_every
!  integer failed_open,failed_delete,failed_close,failed_write
  integer, parameter :: rec_len = 1940
  integer   max_recs, stest, jtest, i, icode, icheck
  character file_name*80
  character iorecord(rec_len)*1
  character ddate*8, ttime*10, zzone*5
  integer   values(8)
  real      elapse_time, start_open, start_loop, end_loop
  external  elapse_time
!
  character share(6)*8, oper(6)*6, access(6)*10, form(6)*11, status(6)*7
     DATA OPER   /'WRITE',  'WRITE', 'READ',  'WRITE',     'WRITE',     'READ'/
     DATA STATUS /'REPLACE','OLD',   'OLD',   'REPLACE',   'OLD',       'OLD'/
     DATA ACCESS /'DIRECT', 'DIRECT','DIRECT','SEQUENTIAL','SEQUENTIAL','SEQUENTIAL'/
     DATA FORM   /6*'UNFORMATTED'/
     DATA SHARE  /' ', 'DENYNONE', 'DENYRW', 'DENYWR', 'DENYRD', 'COMPAT'/

! Test program to open a unformatted direct access file, then write several records
! then close it and try again. Each failure to open will be logged along with the error code and date/time
! a 2 second wait will be done, then re-try.
!
! The first time, we'll delete the file, then create as a new, then old from then on
!
  call date_and_time(ddate,ttime,zzone,values)
  print *,"Starting the test at: ",ddate(1:8),' ',ttime(1:10)
!
  max_recs=1000
!
  do stest=1,6 ! share
    write (file_name, fmt='(a,i0,a)') 'testfile',stest,'.dat'
    print *," "
    print *," ",share(stest),' for ', trim (file_name)

    do jtest=1,6
      if ( jtest==1 .or. jtest==4) call delete_file (file_name)
      start_open = elapse_time ()
      if ( share(stest) == ' ') then
        open (unit   = 15,                 &
              file   = file_name,          &
              iostat = icode,              &
              err    = 12000,              &
              access = access(jtest),      &
              form   = form(jtest),        &
              status = status(jtest),      &
              recl   = rec_len )
      else if ( access(jtest) == 'DIRECT' ) then
        open (unit   = 15,                 &
              file   = file_name,          &
              iostat = icode,              &
              err    = 12000,              &
              access = access(jtest),      &
              form   = form(jtest),        &
              status = status(jtest),      &
              recl   = rec_len,            &
              share  = share(stest) )
      else
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Mon Jan 26, 2015 10:38 am    Post subject: Reply with quote

.ctd/
Code:
      else
        open (unit   = 15,                 &
              file   = file_name,          &
              iostat = icode,              &
              err    = 12000,              &
              access = access(jtest),      &
              form   = form(jtest),        &
              status = status(jtest),      &
              share  = share(stest) )
      end if
     ! the READ tests require that the file exists, so change 'replace' to 'old'

      start_loop = elapse_time () 
      do i=1,max_recs
        call randomfile (iorecord, rec_len) ! this is always left in to even out the loop timing
        !This next line must change to reflect read or write and rec= if needed
        select case (jtest) ! go to (1000,1000,2000,3000,3000,4000),jtest
         case (1:2)  ! write i
           write (15, rec=i, err=13000, iostat=icheck) iorecord
         case (3)    ! read i
           read  (15, rec=i, err=13000, iostat=icheck) iorecord
         case (4:5)  ! write s
           write (15,        err=13000, iostat=icheck) iorecord
         case (6)    ! read s
           read  (15,        err=13000, iostat=icheck) iorecord
        end select
      end do
      end_loop = elapse_time ()
 
      write (*,11) oper(jtest),max_recs,' rec ',     &
                   end_loop-start_loop, ' sec; For', &
                   ' ac=',access(jtest),             &
                   ' fo=',form(jtest),               &
                   ' st=',status(jtest),             &
                   ' sh=',share(stest)
11    format (a,i0, a,f0.3,a, 4(a,a) )   
      close (unit = 15, iostat = icode)
      call sleep1@ (2.)
    end do ! jtest
  end do ! stest
!  pause
  stop

 13000 continue
  print *,"io error during accessing file", icheck
  stop

 12000 continue
  print *,"open error", icode
  stop
   
 END PROGRAM main
 
 subroutine randomfile (iorecord, length)
   integer   length, i
   character iorecord(length)*1
   do i=1,length
     iorecord(i) = char(int(255.*random@()))
   end do
   return
 end
   
 subroutine delete_file (file_name)
   character file_name*(*)
   integer   icode
!
      open  (unit   = 15,                 &
             file   = file_name,          &
             status = 'UNKNOWN',          &
             iostat = icode )
!
      close (unit   = 15,                 &
             status = 'DELETE',           &
             iostat = icode )
!
      if ( icode == 0 ) then
        write (*,*) trim (file_name),' deleted'
      else
        write (*,*) '### Unable to delete ',trim (file_name),' : check status !!'
      end if
 end subroutine delete_file

 real function elapse_time ()
   integer*8 clock, clock_rate
   call system_clock ( clock, clock_rate )
   elapse_time = dble (clock) / dble (clock_rate)
 end function elapse_time


I hope this helps.
I'd be interested if you identify the problem combinations of ACCESS="DIRECT' and SHARE='xxx'
You should see that larger files do not have a huge time penalty, especially when you can skip cache buffering by reducing the number of CLOSE then OPEN operations.

John

ps: there should be an option for larger posts when required !! (or attachments)
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Mon Jan 26, 2015 12:19 pm    Post subject: Reply with quote

Bill,

I have produced a test program that tests more alternatives of size and disk buffering.
If you watch the program run, using windows explorer, you will see which share= options are continually updating the disk for access='direct'. Other options show the use of the disk cache with fewer changes to the stored file.
Sequential access does not appear to work this way and might not not support multiple read/write.
I tried to reduce flushing by minimising open/close, but that does not appear to be working as I hoped.

The latest test code is:
Code:
!  program to test share= performance
!
  call do_test (    194,  1000, .false. )
  call do_test (   2048,  2000, .false. )
  call do_test ( 2048*8, 10000, .false. )
  call do_test ( 2048*8, 10000, .true. )
end

!FTN95 application...
 subroutine do_test (rec_len, max_recs, Minimise_Close)
!
  logical :: Minimise_Close
  integer :: rec_len
  integer :: max_recs
!
  character iorecord(rec_len)*1
!
  logical :: open_file, close_file
!
  character file_name*80
  integer   stest, jtest, i, icode, icheck
!
  character share(6)*8, oper(6)*6, access(6)*10, form(6)*11, status(6)*7
     DATA OPER   /'WRITE',  'WRITE', 'READ',  'WRITE',     'WRITE',     'READ'/
     DATA STATUS /'REPLACE','OLD',   'OLD',   'REPLACE',   'OLD',       'OLD'/
     DATA ACCESS /'DIRECT', 'DIRECT','DIRECT','SEQUENTIAL','SEQUENTIAL','SEQUENTIAL'/
     DATA FORM   /6*'UNFORMATTED'/
     DATA SHARE  /' ', 'DENYNONE', 'DENYRW', 'DENYWR', 'DENYRD', 'COMPAT'/
!
  character ddate*8, ttime*10, zzone*5
  integer   values(8)
  real      elapse_time, start_open, start_loop, end_loop, mb_sec
  external  elapse_time

! Test program to open a unformatted direct access file, then write several records
! then close it and try again. Each failure to open will be logged along with the error code and date/time
! a 2 second wait will be done, then re-try.
!
! The first time, we'll delete the file, then create as a new, then old from then on
!
  call date_and_time(ddate,ttime,zzone,values)
  print *,"Starting the test at: ",ddate(1:8),' ',ttime(1:10),'  for',max_recs,' records length =',rec_len
!
  do stest=1,6 ! share
    write (file_name, fmt='(a,i0,a)') 'testfile',stest,'.dat'
    print *," "
    print *," ",share(stest),' for ', trim (file_name)

    do jtest=1,6
!
      if ( jtest==1 .or. jtest==4) call delete_file (file_name)
      if ( minimise_close ) then
        open_file  = ( jtest == 1 .or. jtest == 4)
        close_file = ( jtest == 3 .or. jtest == 6)
      else
        open_file  = .true.
        close_file = .true.
      end if
!
      start_open = elapse_time ()
      if ( open_file ) then
        if ( share(stest) == ' ') then  ! omit share =
         if ( access(jtest) == 'DIRECT' ) then
           open (unit   = 15,                 &
                 file   = file_name,          &
                 iostat = icode,              &
                 err    = 12000,              &
                 access = access(jtest),      &
                 form   = form(jtest),        &
                 status = status(jtest),      &
                 recl   = rec_len )
         else
           open (unit   = 15,                 &
                 file   = file_name,          &
                 iostat = icode,              &
                 err    = 12000,              &
                 access = access(jtest),      &
                 form   = form(jtest),        &
                 status = status(jtest) )
         end if
        else   ! include share =
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Mon Jan 26, 2015 12:21 pm    Post subject: Reply with quote

.ctd/
Code:
        else   ! include share =
         if ( access(jtest) == 'DIRECT' ) then
           open (unit   = 15,                 &
                 file   = file_name,          &
                 iostat = icode,              &
                 err    = 12000,              &
                 access = access(jtest),      &
                 form   = form(jtest),        &
                 status = status(jtest),      &
                 recl   = rec_len,            &
                 share  = share(stest) )
         else
           open (unit   = 15,                 &
                 file   = file_name,          &
                 iostat = icode,              &
                 err    = 12000,              &
                 access = access(jtest),      &
                 form   = form(jtest),        &
                 status = status(jtest),      &
                 share  = share(stest) )
         end if
        end if
        write (*,*) 'file opened'
      else if ( access(jtest) /= 'DIRECT' ) then
        rewind ( unit = 15 )
      end if
     ! the READ tests require that the file exists, so change 'replace' to 'old'
!
      start_loop = elapse_time () 
      do i=1,max_recs
        call randomfile (iorecord, rec_len) ! this is always left in to even out the loop timing
        !This next line must change to reflect read or write and rec= if needed
        select case (jtest) ! go to (1000,1000,2000,3000,3000,4000),jtest
         case (1:2)  ! write i
           write (15, rec=i, err=13000, iostat=icheck) iorecord
         case (3)    ! read i
           read  (15, rec=i, err=13000, iostat=icheck) iorecord
         case (4:5)  ! write s
           write (15,        err=13000, iostat=icheck) iorecord
         case (6)    ! read s
           read  (15,        err=13000, iostat=icheck) iorecord
        end select
      end do
      end_loop = elapse_time ()
!
      mb_sec = real(max_recs)*real(rec_len) / (end_loop-start_loop) / 1024. / 1024.
      write (*,11) oper(jtest),max_recs,' rec ',     &
                   end_loop-start_loop, ' sec; For', &
                   ' ac=',access(jtest),             &
                   ' fo=',form(jtest),               &
                   ' st=',status(jtest),             &
                   ' sh=',share(stest),              &
                   mb_sec
11    format (a,i0, a,f0.3,a, 4(a,a), f7.3,' Mb/sec' )   
!
      if ( close_file ) then
        close (unit = 15, iostat = icode)
        write (*,*) 'file closed'
        call sleep1@ (2.)
      end if
!
    end do ! jtest
  end do ! stest
!  pause
  return

 13000 continue
  print *,"io error during accessing file", icheck
  stop

 12000 continue
  print *,"open error", icode
  stop
   
 END subroutine do_test
 
 subroutine randomfile (iorecord, length)
   integer   length, i
   character iorecord(length)*1
   do i=1,length
     iorecord(i) = char(int(255.*random@()))
   end do
   return
 end
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Mon Jan 26, 2015 12:26 pm    Post subject: Reply with quote

.ctd 2/
Code:
 subroutine delete_file (file_name)
   character file_name*(*)
   integer   icode
!
      open  (unit   = 15,                 &
             file   = file_name,          &
             status = 'UNKNOWN',          &
             iostat = icode )
!
      close (unit   = 15,                 &
             status = 'DELETE',           &
             iostat = icode )
!
      if ( icode == 0 ) then
        write (*,*) trim (file_name),' deleted'
      else
        write (*,*) '### Unable to delete ',trim (file_name),' : check status !!'
      end if
 end subroutine delete_file

 real function elapse_time ()
   integer*8 clock, clock_rate
   call system_clock ( clock, clock_rate )
   elapse_time = dble (clock) / dble (clock_rate)
 end function elapse_time


It does demonstrate performance changes on my HDD, so hopefully it can show changes on your disk alternatives for the various share= options.
I hope the trend is consistent with the expected file access attributes.

John
Back to top
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Mon Jan 26, 2015 5:12 pm    Post subject: Reply with quote

John,

WOW, you certainly have gone over and above what I could have ever expected, and I am very grateful! You put a lot of effort into this.

If I could state in one sentence what you've found: The use of SHARE has an effect on the performance, and certain SHARE options have a bigger effect than others. There's a lot more you did here, but would that be accurate in your view?

Yes, the original code was inefficient (i.e. use of random()). The original thought there was that if the Antivirus was triggering on some random data, perhaps this would show it. After I was able to identify and workaround the odd IOSTAT values (10005 and 10002) when files were opened, the need for randomized data actually went away. But, left it for consistency.The random() was left in for the reads for timing comparisons.

I only perform one open/close for each block of records, so I am curious about your comment (Mon Jan 26, 2015 3:38 am MST).

It is interesting that the SHARE would cause a difference in performance, and while your numbers are certainly faster than mine it still begs the question: Why?

As far as bigger records, no, not possible. My software has a legacy that dates back to the early 80's, when it was run on machines as simple as S-100 bus, CP/M. File size is set by the variables required. Would that I could change the sizes or formats!! It would make life so much easier. Some of the files created in those early days are still in use today, just much bigger!

When some of the users started using a networking environment in the mid 90's, the question of access restrictions came up. With multiple users on individual machines, sometimes EXCLUSIVE access is required when updating the master files (most of which are binary, unformatted, direct), while in most cases, simple READ access is needed. As well, there are some sequential, formatted files that can be affected. So, yes, I do need to have the SHARE set appropriately, and the setting of this access is dependent on the file usage at the time, and the software asks for that access as needed when opening the file.

I hope to replicate your results on my primary machine later today. It will be an interesting comparison.

I am looking at "perfmon" to do some more detailed looks at the transfers and IO operations counts associated with these various operations. Once I get that up and running (and a little more time), I'll share it here.
Back to top
View user's profile Send private message Visit poster's website
JohnCampbell



Joined: 16 Feb 2006
Posts: 2554
Location: Sydney

PostPosted: Tue Jan 27, 2015 2:21 am    Post subject: Reply with quote

Bill,

I have now seen your problem !!

I transferred my latest test code to my notebook, which is running Windows 8.1. This OS must rival Vista as I find it an appalling downgrade from Windows 7.

I am getting huge delays on direct access files with some share= options. ( some cases 20sec, 40 sec and even 250 sec ! I'll update when the tests are complete.)
I am trying running in a normal DOS box then running as administrator. Both have big delays for direct access files. Must have something to do with directory access rights. As these delays occur while writing and not just when opening, there could be some incompatibility or tuning required with salflibc.dll and Win 8.1.

Not sure what the solution is, but certainly removing Windows 8.1 would be a good approach.

John
Back to top
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Tue Jan 27, 2015 3:12 am    Post subject: Reply with quote

John, perhaps removing 8.1 might be a bit premature. It is nice to see that it can happen to others!

I do suspect it has something to do with policies or permissions, but I am at a loss to know. I'm not a SYSADMIN!

Bill
Back to top
View user's profile Send private message Visit poster's website
mecej4



Joined: 31 Oct 2006
Posts: 1886

PostPosted: Tue Jan 27, 2015 5:14 pm    Post subject: Reply with quote

I have been using W8.0 since May 2013, and W8.1 since Dec 2013. While the tiles interface is correctly worthy of ridicule and condemnation, the underlying OS is solid and competent. I do most of my work at the command line, and have a third party Start program to make the system behave similarly to W7.

I took John's program of Jan 26, 2015 11:19 am, and modified it as follows.
    1. Removed the call to sleep@.
    2. Added a call to delete_file after the END DO !jtest
    3. Used CPU_TIME for timing instead of SYSTEM_CLOCK.

These changes allow the code to be run on a ramdisk using FTN95 and Intel Fortran. I see none of the problems of slowdown that others have mentioned, indicating that "something else" is the culprit. With FTN95 I get speeds of about 30 MB/s, for all except the runs with small files, where the speed can go down to 10 MB/s or less. With Intel Fortran, the corresponding speeds are 45 MB/s and 12 MB/s. (These "speeds" are as reported by the program, on a laptop with an i5-4200U CPU)

Once you set up a comfortable program development environment under it, you will not complain about W8x. In a multiprocessing environment, I/O to files with shared access is subject to many influences in addition to hardware, OS and compiler brand differences.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Goto page Previous  1, 2, 3, 4  Next
Page 2 of 4

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group