Buffered I/O 与 Non-Buffered I/O性能差异的实例体验

本文介绍了两种不同的方法来读取文件中间特定数量的行,一种是逐字符读取,另一种是使用行缓存优化读取过程。通过对比这两种方法在处理大文件时的效率,展示了使用缓冲区的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        帮同学作一个作业,写了两个程序,完成的功能类似LINUX中的head和tail命令,可以获取一个文件中间的几行。这两个程序实现的是同一个功能,但是一个用的是一个类似LIBC中的fgetc的函数到文件里一个一个字符地取;而第二个程序则是用了行缓存,通过INIT_LINE_BUFFER和INC_LINE_BUFFER来控制,缓存大小和扩展大小。程序旨在说明问题,如果代码上有什么丑陋的,请包涵。

未做buffer的程序代码:
  1None.gif#include <stdio.h>
  2None.gif#include <stdlib.h>
  3None.gif#include <sys/types.h>
  4None.gif#include <sys/stat.h>
  5None.gif#include <string.h>
  6None.gif#include <unistd.h>
  7None.gif#include <fcntl.h>
  8None.gif
  9None.gif#define CHAR_BUFFER 1
 10None.gif#define BUFFER_SIZE 1024
 11None.gif#define LINE_BUFFER 128
 12None.gif#define MAX_FILE_LINE_NUM 1000000
 13None.gif
 14None.gifint rw_ptr;  // read-write pointer
 15None.gifint lineNum;  // number of lines in the file
 16None.gif
 17None.gifint position_rw_pntr(int fd, int num_lines);
 18None.gifchar* get_next_line(int fd);
 19None.gifint get_next_char(int fd);
 20None.gif
 21None.gifint main(int argc, char *argv[]) 
 22ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 23InBlock.gif    int midLines;
 24InBlock.gif    int i = 0;
 25InBlock.gif    char* lineString;
 26InBlock.gif    int succ;
 27InBlock.gif    int fd;
 28ExpandedSubBlockStart.gifContractedSubBlock.gif    if (argc != 3dot.gif{
 29InBlock.gif        printf("Usage: lab2 <lines> <file>\n");
 30InBlock.gif        return -1;
 31ExpandedSubBlockEnd.gif    }

 32InBlock.gif    
 33InBlock.gif    midLines = atoi(argv[1]);
 34InBlock.gif    if ((fd = open(argv[2], O_RDONLY)) == -1
 35ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 36InBlock.gif        perror("Open file error");
 37InBlock.gif        return EXIT_FAILURE;
 38ExpandedSubBlockEnd.gif    }

 39InBlock.gif
 40InBlock.gif    if (position_rw_pntr(fd, midLines) == -1)
 41ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 42InBlock.gif        perror("Position_rw_pntr Error");
 43InBlock.gif        return EXIT_FAILURE;
 44ExpandedSubBlockEnd.gif    }

 45InBlock.gif        
 46InBlock.gif    while (i != midLines && i != lineNum) 
 47ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 48InBlock.gif        lineString = get_next_line(fd);
 49InBlock.gif        printf("%s\n", lineString);
 50InBlock.gif        i++;
 51ExpandedSubBlockEnd.gif    }

 52InBlock.gif
 53InBlock.gif    free(lineString);
 54InBlock.gif    close(fd);
 55InBlock.gif    
 56InBlock.gif    return EXIT_SUCCESS;
 57ExpandedBlockEnd.gif}

 58None.gif
 59None.gifint position_rw_pntr(int fd, int num_lines) 
 60ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 61InBlock.gif    int start;
 62InBlock.gif    int i, n;
 63InBlock.gif    char buf[BUFFER_SIZE];
 64InBlock.gif    int* lineCount = (int *)malloc(MAX_FILE_LINE_NUM * sizeof(int));
 65InBlock.gif    int byteNum = 0;
 66InBlock.gif
 67InBlock.gif    if (lseek(fd, 0, SEEK_SET) == -1
 68ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 69InBlock.gif        return -1;
 70ExpandedSubBlockEnd.gif    }

 71InBlock.gif    
 72InBlock.gif    lineNum = 0;
 73InBlock.gif    lineCount[lineNum] = 0;
 74InBlock.gif    while ((n = read(fd, buf, BUFFER_SIZE)) != 0 ) 
 75ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 76InBlock.gif        for (i = 0; i < n; i++
 77ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 78InBlock.gif            byteNum++;
 79InBlock.gif            if (buf[i] == '\n'
 80ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 81InBlock.gif                lineCount[++lineNum] = byteNum;
 82ExpandedSubBlockEnd.gif            }

 83ExpandedSubBlockEnd.gif        }

 84ExpandedSubBlockEnd.gif    }

 85InBlock.gif
 86InBlock.gif    if (lineNum < num_lines)
 87ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 88InBlock.gif        rw_ptr = 0;
 89ExpandedSubBlockEnd.gif    }

 90InBlock.gif    else
 91ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{    
 92InBlock.gif        if (lineNum % 2)
 93ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 94InBlock.gif            rw_ptr = lineCount[(lineNum - num_lines) / 2 + (lineNum - num_lines + 1% 2 - 1];
 95ExpandedSubBlockEnd.gif        }

 96InBlock.gif        else
 97ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 98InBlock.gif            rw_ptr = lineCount[(lineNum - num_lines) / 2 + (lineNum - num_lines) % 2 - 1];
 99ExpandedSubBlockEnd.gif        }

100ExpandedSubBlockEnd.gif    }

101InBlock.gif    
102InBlock.gif    return 1;
103ExpandedBlockEnd.gif}

104None.gif
105None.gifchar* get_next_line(int fd) 
106ExpandedBlockStart.gifContractedBlock.gifdot.gif{
107InBlock.gif    int n, i;
108InBlock.gif    char byteChar;
109InBlock.gif    char* buf;
110InBlock.gif
111InBlock.gif    if (lseek(fd, rw_ptr, SEEK_SET) == -1
112ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
113InBlock.gif        return NULL;
114ExpandedSubBlockEnd.gif    }

115InBlock.gif    
116InBlock.gif    buf = (char *)malloc(LINE_BUFFER * sizeof(char));
117InBlock.gif
118InBlock.gif    for (i = 0; i < LINE_BUFFER; i++
119ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
120InBlock.gif        byteChar = (char)get_next_char(fd);
121InBlock.gif        if (byteChar == EOF || byteChar == '\n')
122ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
123InBlock.gif            buf[i] = '\0';
124InBlock.gif            break;
125ExpandedSubBlockEnd.gif        }

126InBlock.gif        else
127ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
128InBlock.gif            buf[i] = byteChar;
129ExpandedSubBlockEnd.gif        }

130ExpandedSubBlockEnd.gif    }

131InBlock.gif
132InBlock.gif    return buf;
133ExpandedBlockEnd.gif}

134None.gif
135None.gifint get_next_char(int fd)
136ExpandedBlockStart.gifContractedBlock.gifdot.gif{
137InBlock.gif    char charBuf[1];
138InBlock.gif    if (lseek(fd, rw_ptr, SEEK_SET) == -1
139ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
140InBlock.gif        return EOF;
141ExpandedSubBlockEnd.gif    }

142InBlock.gif    
143InBlock.gif    rw_ptr++;
144InBlock.gif    if (read(fd, charBuf, 1== 0
145ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
146InBlock.gif        return EOF;
147ExpandedSubBlockEnd.gif    }

148InBlock.gif    return charBuf[0];
149ExpandedBlockEnd.gif}

150None.gif


做了buffer的程序代码:
  1None.gif#include <stdio.h>
  2None.gif#include <stdlib.h>
  3None.gif#include <sys/types.h>
  4None.gif#include <sys/stat.h>
  5None.gif#include <string.h>
  6None.gif#include <unistd.h>
  7None.gif#include <fcntl.h>
  8None.gif
  9None.gif#define BUFFER_SIZE 1024
 10None.gif#define INIT_BUFF_SIZE 64
 11None.gif#define INC_BUFF_SIZE 8
 12None.gif#define LINE_BUFFER 128
 13None.gif#define MAX_FILE_LINE_NUM 1000000
 14None.gif
 15None.gifint rw_ptr;  // read-write pointer
 16None.gifint lineNum;  // number of lines in the file
 17None.gifchar lineBuf[INIT_BUFF_SIZE];
 18None.gifint linePtr;
 19None.gifint curBufSize;
 20None.gif
 21None.gifint position_rw_pntr(int fd, int num_lines);
 22None.gifchar* get_next_line(int fd);
 23None.gifint get_next_char(int fd);
 24None.gif
 25None.gifint main(int argc, char *argv[]) 
 26ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 27InBlock.gif    int midLines;
 28InBlock.gif    int i = 0;
 29InBlock.gif    char* lineString;
 30InBlock.gif    int succ;
 31InBlock.gif    int fd;
 32ExpandedSubBlockStart.gifContractedSubBlock.gif    if (argc != 3dot.gif{
 33InBlock.gif        printf("Usage: lab2 <lines> <file>\n");
 34InBlock.gif        return -1;
 35ExpandedSubBlockEnd.gif    }

 36InBlock.gif
 37InBlock.gif    midLines = atoi(argv[1]);
 38InBlock.gif    if ((fd = open(argv[2], O_RDONLY)) == -1
 39ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 40InBlock.gif        perror("Open file error");
 41InBlock.gif        return EXIT_FAILURE;
 42ExpandedSubBlockEnd.gif    }

 43InBlock.gif
 44InBlock.gif    if (position_rw_pntr(fd, midLines) == -1)
 45ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 46InBlock.gif        perror("Position_rw_pntr Error");
 47InBlock.gif        return EXIT_FAILURE;
 48ExpandedSubBlockEnd.gif    }

 49InBlock.gif
 50InBlock.gif    while (i != midLines && i != lineNum) 
 51ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 52InBlock.gif        lineString = get_next_line(fd);
 53InBlock.gif        printf("%s\n", lineString);
 54InBlock.gif        i++;
 55ExpandedSubBlockEnd.gif    }

 56InBlock.gif
 57InBlock.gif    free(lineString);
 58InBlock.gif    close(fd);
 59InBlock.gif
 60InBlock.gif    return EXIT_SUCCESS;
 61ExpandedBlockEnd.gif}

 62None.gif
 63None.gifint position_rw_pntr(int fd, int num_lines) 
 64ExpandedBlockStart.gifContractedBlock.gifdot.gif{
 65InBlock.gif    int start;
 66InBlock.gif    int i, n;
 67InBlock.gif    char buf[BUFFER_SIZE];
 68InBlock.gif    int* lineCount = (int *)malloc(MAX_FILE_LINE_NUM * sizeof(int));
 69InBlock.gif    int byteNum = 0;
 70InBlock.gif
 71InBlock.gif    if (lseek(fd, 0, SEEK_SET) == -1
 72ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 73InBlock.gif        return -1;
 74ExpandedSubBlockEnd.gif    }

 75InBlock.gif
 76InBlock.gif    lineNum = 0;
 77InBlock.gif    lineCount[lineNum] = 0;
 78InBlock.gif    while ((n = read(fd, buf, BUFFER_SIZE)) != 0 ) 
 79ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 80InBlock.gif        for (i = 0; i < n; i++
 81ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 82InBlock.gif            byteNum++;
 83InBlock.gif            if (buf[i] == '\n'
 84ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 85InBlock.gif                lineCount[++lineNum] = byteNum;
 86ExpandedSubBlockEnd.gif            }

 87ExpandedSubBlockEnd.gif        }

 88ExpandedSubBlockEnd.gif    }

 89InBlock.gif
 90InBlock.gif    if (lineNum < num_lines)
 91ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 92InBlock.gif        rw_ptr = 0;
 93ExpandedSubBlockEnd.gif    }

 94InBlock.gif    else
 95ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{    
 96InBlock.gif        if (lineNum % 2)
 97ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 98InBlock.gif            rw_ptr = lineCount[(lineNum - num_lines) / 2 + (lineNum - num_lines + 1% 2 - 1];
 99ExpandedSubBlockEnd.gif        }

100InBlock.gif        else
101ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
102InBlock.gif            rw_ptr = lineCount[(lineNum - num_lines) / 2 + (lineNum - num_lines) % 2 - 1];
103ExpandedSubBlockEnd.gif        }

104ExpandedSubBlockEnd.gif    }

105InBlock.gif
106InBlock.gif    return 1;
107ExpandedBlockEnd.gif}

108None.gif
109None.gifchar* get_next_line(int fd) 
110ExpandedBlockStart.gifContractedBlock.gifdot.gif{
111InBlock.gif    int n, i;
112InBlock.gif    char byteChar;
113InBlock.gif    char* buf;
114InBlock.gif
115InBlock.gif    if (lseek(fd, rw_ptr, SEEK_SET) == -1
116ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
117InBlock.gif        return NULL;
118ExpandedSubBlockEnd.gif    }

119InBlock.gif
120InBlock.gif    linePtr = 0;
121InBlock.gif    buf = (char *)malloc(LINE_BUFFER * sizeof(char));
122InBlock.gif    
123InBlock.gif    for (i = 0; i < LINE_BUFFER; i++
124ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
125InBlock.gif        byteChar = (char)get_next_char(fd);
126InBlock.gif        if (byteChar == EOF || byteChar == '\n')
127ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
128InBlock.gif            buf[i] = '\0';
129InBlock.gif            break;
130ExpandedSubBlockEnd.gif        }

131InBlock.gif        else
132ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
133InBlock.gif            buf[i] = byteChar;
134ExpandedSubBlockEnd.gif        }

135ExpandedSubBlockEnd.gif    }

136InBlock.gif
137InBlock.gif    return buf;
138ExpandedBlockEnd.gif}

139None.gif
140None.gifint get_next_char(int fd)
141ExpandedBlockStart.gifContractedBlock.gifdot.gif{
142InBlock.gif    int n;
143InBlock.gif    if (lseek(fd, rw_ptr, SEEK_SET) == -1
144ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
145InBlock.gif        return EOF;
146ExpandedSubBlockEnd.gif    }

147InBlock.gif
148InBlock.gif    if (linePtr == 0)
149ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
150InBlock.gif        if ((curBufSize = read(fd, lineBuf, INIT_BUFF_SIZE)) == 0)
151ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
152InBlock.gif            return EOF;
153ExpandedSubBlockEnd.gif        }

154InBlock.gif        linePtr = 0;
155ExpandedSubBlockEnd.gif    }

156InBlock.gif    
157InBlock.gif    if (linePtr < curBufSize)
158ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
159InBlock.gif        rw_ptr++;
160InBlock.gif        return lineBuf[linePtr++];
161ExpandedSubBlockEnd.gif    }

162InBlock.gif    else
163ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
164InBlock.gif        if ((curBufSize = read(fd, lineBuf, INC_BUFF_SIZE)) == 0)
165ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
166InBlock.gif            return EOF;
167ExpandedSubBlockEnd.gif        }

168InBlock.gif        else
169ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
170InBlock.gif            rw_ptr++;
171InBlock.gif            linePtr = 0;
172InBlock.gif            return lineBuf[linePtr++];
173ExpandedSubBlockEnd.gif        }

174ExpandedSubBlockEnd.gif    }

175ExpandedBlockEnd.gif}

176None.gif
177None.gif

最后用了一个shell脚本来测试两个的运行时间,比较其优劣(其中的BigFile.txt是一个很大的文件):
#!/bin/bash

set `date`
echo start test part1 at $
4
../part1/lab2.exe 300000 BigFile.txt > part1.bt
set `date`
echo finish test part1 at $
4
set `date`
echo start test part2 at $
4
../part2/lab2.exe 300000 BigFile.txt > part2.bt
set `date`
echo finish test part2 at $
4

用个跑下来,前者要比后者慢一倍。可见buffer的好处。如果调高buffer的size,效果将更明显。

转载于:https://www.cnblogs.com/sjpisaboy/archive/2006/04/14/375599.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值