<div dir="ltr">The ioctl is standard, including in C unless you are using open() directly: it checks to see if the opened file is a terminal, to determine whether to set block or line buffering.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, May 10, 2019 at 11:09 AM Magicloud Magiclouds <<a href="mailto:magicloud.magiclouds@gmail.com">magicloud.magiclouds@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">So this is what I got. Seems like both calls two stat(stat/newfstatat)<br>
for dir checking and uid checking. But when open file for reading,<br>
there is an ioctl call (maybe from System.IO.Strict) which seems<br>
failed, for Haskell. I want to test the case without System.IO.Strict.<br>
But have no idea how to get exception catching works with lazy<br>
readFIle.<br>
<br>
For Haskell implenmentation,<br>
```<br>
stat("/proc/230", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0<br>
stat("/proc/230", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0<br>
openat(AT_FDCWD, "/proc/230/stat", O_RDONLY|O_NOCTTY|O_NONBLOCK) = 23<br>
fstat(23, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0<br>
ioctl(23, TCGETS, 0x7ffe88c18090)       = -1 ENOTTY (Inappropriate<br>
ioctl for device)<br>
read(23, "230 (scsi_eh_5) S 2 0 0 0 -1 212"..., 8192) = 155<br>
read(23, "", 8192)                      = 0<br>
close(23)<br>
```<br>
For Rust implenmentation,<br>
```<br>
newfstatat(3, "1121", {st_mode=S_IFDIR|0555, st_size=0, ...},<br>
AT_SYMLINK_NOFOLLOW) = 0<br>
stat("/proc/1121", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0<br>
open("/proc/1121/stat", O_RDONLY|O_CLOEXEC) = 4<br>
fcntl(4, F_SETFD, FD_CLOEXEC)           = 0<br>
fstat(4, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0<br>
read(4, "1121 (ibus-engine-sim) S 1077 10", 32) = 32<br>
read(4, "77 1077 0 -1 4194304 425 0 1 0 5", 32) = 32<br>
read(4, "866 1689 0 0 20 0 3 0 3490 16454"..., 64) = 64<br>
read(4, "4885264596992 94885264603013 140"..., 128) = 128<br>
read(4, "0724521155542 140724521155575 14"..., 256) = 64<br>
read(4, "", 192)                        = 0<br>
close(4)<br>
```<br>
<br>
On Fri, May 10, 2019 at 3:49 PM Magicloud Magiclouds<br>
<<a href="mailto:magicloud.magiclouds@gmail.com" target="_blank">magicloud.magiclouds@gmail.com</a>> wrote:<br>
><br>
> Good point. Let me see what strace can tell me.<br>
><br>
> On Fri, May 10, 2019 at 3:46 PM Iustin Pop <<a href="mailto:iustin@k1024.org" target="_blank">iustin@k1024.org</a>> wrote:<br>
> ><br>
> > On 2019-05-10 10:00:45, Magicloud Magiclouds wrote:<br>
> > > Hi,<br>
> > > I have asked this in Stackoverflow without getting an answer.<br>
> > > Wondering if people here could have some thoughts.<br>
> > ><br>
> > > I have a function reading the content of /proc every second.<br>
> > > Surprisingly, its CPU usage in top is around 5%, peak at 8%. But same<br>
> > > logic in C or Rust just takes like 1% or 2%. Wondering if this can be<br>
> > > improved. /proc is virtual filesystem, so this is not related to HDD<br>
> > > performance. And I noticed this difference because my CPU is too old<br>
> > > (Core Gen2). On modern CPU, as tested by others, the difference is<br>
> > > barely noticeable.<br>
> > ><br>
> > > watch u limit0s limit0h = do<br>
> > >   listDirectory "/proc/" >>= mapM_ (\fp -> do<br>
> > >     isMyPid' <- maybe False id <$> wrap2Maybe (isMyPid fp u)<br>
> > >     wrap2Maybe (Strict.readFile ("/proc/" </> fp </> "stat")))<br>
> > >   threadDelay 1000000<br>
> > >   watch u limit0s limit0h<br>
> > >   where<br>
> > >     wrap2Maybe :: IO a -> IO (Maybe a)<br>
> > >     wrap2Maybe f = catch ((<$>) Just $! f) (\(_ :: IOException) -><br>
> > > return Nothing)<br>
> > >     isMyPid :: FilePath -> UserID -> IO Bool<br>
> > >     isMyPid fp me = do<br>
> > >       let areDigit = fp >= "0" && fp <= "9"<br>
> > >       isDir <- doesDirectoryExist $ "/proc/" </> fp<br>
> > >       owner <- fileOwner <$> getFileStatus ("/proc" </> fp)<br>
> > >       return $ areDigit && isDir && (owner == me)<br>
> ><br>
> > Interesting, I can see a few potential issues. But first, have you<br>
> > measure how many syscalls does this do in Haskell vs. C vs Rust? That<br>
> > would allow you to separate the problem between internal Haskell<br>
> > problems (e.g. String) vs. different algorithm in Haskell.<br>
> ><br>
> > For exacmple, one issue that could lead to unneded syscalls is your<br>
> > "isMyPid" function. AFAIK there's no caching done by getFileStatus, so<br>
> > you're stat'ing (and making a syscall) each path twice, once to get file<br>
> > type (is it directory) information, and then a second time to get owner<br>
> > information.<br>
> ><br>
> > You also build `"/proc/" <> fp` twice (and thus evaluate it twice).<br>
> ><br>
> > But without understanding "how" Haskell it slower, it's not clear where<br>
> > the problem lies (in syscalls or in GC or …).<br>
> ><br>
> > regards,<br>
> > iustin<br>
><br>
><br>
><br>
> --<br>
> 竹密岂妨流水过<br>
> 山高哪阻野云飞<br>
><br>
> And for G+, please use magiclouds#<a href="http://gmail.com" rel="noreferrer" target="_blank">gmail.com</a>.<br>
<br>
<br>
<br>
-- <br>
竹密岂妨流水过<br>
山高哪阻野云飞<br>
<br>
And for G+, please use magiclouds#<a href="http://gmail.com" rel="noreferrer" target="_blank">gmail.com</a>.<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div>brandon s allbery kf8nh</div><div><a href="mailto:allbery.b@gmail.com" target="_blank">allbery.b@gmail.com</a></div></div></div></div></div>